Untitled
unknown
c_cpp
3 years ago
8.2 kB
62
Indexable
/** Included files */ #include "mcc_generated_files/mcc.h" #include "lcd_jerry.h" #include <stdio.h> #include "app.h" //************************* Defines and enums ****************** #define led_time 100 // 100ms update interval #define lcd_time ((uint16_t)500) // 500ms update interval #define adc_sample_time 10 // 10ms sample time #define adc_update_time 100 // 100ms update interval #define adc_channels 4 enum { adc_idle = 0, adc_sampling = 1, adc_converting = 2, adc_all_done = 3 } adc_status; enum { led_init = 0, led_low = 1, led_high = 2, } led_status; #define LED1 LATD1 #define LED2 LATD0 #define LED3 LATC3 #define LED4 LATC4 #define LED5 LATC5 #define LED6 LATC6 #define LED7 LATC7 #define LED8 LATB4 #define LED9 LATB3 #define LED10 LATB5 #define led_Toggle(n) { LED##n = !LED##n; } #define led_On(n) { LED##n = 1; } #define led_Off(n) { LED##n = 0; } //************************* Global Variables ****************** uin32_t cell_voltages[4]; char volt_str[] = "1.11 V"; const uint16_t resistorRatioCell[4] = { 496, 367, 245, 123 }; const char digit[10] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' }; //************************* Functions ****************** void Handle_LED(void); void Handle_LCD(void); void Handle_ADC(void); void LCD_Display(uint32_t cellVoltage, uint8_t row, uint8_t column); void Lcd4_Clear(void); void Lcd4_Init(void); void configTimer0(void); uint32_t getTime(void); uint16_t readTimer0(void); /***************************************** Main application *****************************************/ void main (void){ //Initialize functions SYSTEM_Initialize(); // Timer0 Internal_clock, prescaler_32768, postscaler_1); Lcd4_Init(); ADCC_Initialize(); APP_LED_Initialize(); // Enable the Global Interrupts INTCONbits.GIE = 1; // Enable the Peripheral Interrupts INTCONbits.PEIE = 1; // LCD Greeting Lcd4_Clear(); Lcd4_Set_Cursor(1, 1); Lcd4_Write_String("Battery"); Lcd4_Set_Cursor(2, 1); Lcd4_Write_String("Simulation"); led4_Toggle(); __delay_ms(1500); led4_Toggle(); Lcd4_Clear(); configTimer0(); while(1) { Handle_LED(); Handle_ADC(); Handle_LCD(); } } void Handle_LED1(void) { static uint32_t last_time = 0; static uint8_t status = 0; /* Check the application's current state. */ uint32_t now = getTime(); uint32_t elapsed = last_time - now; switch (status) { /* Application's initial state. */ case led_init: { led_Off(6); // Set LED off status = led_low; break; } case led_low: { if (elapsed < led_off_time) { return; } led_On(6); // Toggle LED On status = led_high; break; } case led_high: { if (elapsed < led_on_time) { return; } led_Off(6); // Toggle LED off status = led_low; break; } /* The default state should never be executed. */ default: { /* TODO: Handle error in application's state machine. */ break; } } // last_time should be preserved for proper time tracking // the program must return earlier if no action is done. last_time = now; } void Handle_LED(void){ if ( elapsed < led_time){ return; } last_time = now; // Do LED stuff // Everytime you get here you know "led_time" time has passed } void Handle_ADC(void){ static uint32_t last_time = 0; static uint8_t channel = 0; static uint8_t status = adc_idle; static uint32_t voltage[4]; uint32_t now = getTime(); uint32_t elapsed = last_time - now; // Do ADC stuff switch (status){ case adc_idle: status++; ADPCH = 5 - channel; break; case adc_sampling: // wait for sampling time, but don't block program execution if ( elapsed < adc_sample_time){ // Return now to avoid time update return; } status++; ADCON0bits.ADGO = 1; break; case adc_converting: // If conversion done if(!ADCON0bits.ADGO){ // Convert adc value to voltage voltage[channel] = (((uint32_t)ADRESH << 8) | ADRESL) * 4 * resistorRatioCell[channel]; // Increase channel, check if all channels done if ( ++channel >= adc_channels ){ // Reset channel index channel = 0; // Converts readings at the balance wires to individual cell voltage for (uint8_t i = 0; i < 3; i++) { cellVoltage[i] = voltage[i] - voltage[i+1]; } status = adc_all_done; } else{ // Not done all channels yet, repeat status = adc_idle; } } break; case adc_all_done: // When all channels have been converted, wait the specified time for next conversion sequence if ( elapsed < adc_update_time ){ // Return now to avoid time update return; } // Time over, start over status = adc_idle; break; } last_time = now; } void Handle_LCD(void){ static uint32_t last_time = 0; uint32_t now = getTime(); uint32_t elapsed = last_time - now; if ( elapsed < lcd_time) ){ return; } last_time = now; LCD_Display(cellVoltage[0], 1, 0); LCD_Display(cellVoltage[1], 1, 8); LCD_Display(cellVoltage[2], 2, 0); LCD_Display(cellVoltage[3], 2, 8); } void LCD_Display(uint32_t cellVoltage, uint8_t row, uint8_t column) { volt_str[0] = digit[ ((cellVoltage / 100000) % 10) ]; volt_str[2] = digit[ ((cellVoltage / 10000) % 10) ]; volt_str[3] = digit[ ((cellVoltage / 1000) % 10) ]; Lcd4_Set_Cursor(row, column); Lcd4_Write_String(volt_str); } void configTimer0(void){ // Clear timer counters TMR0H=0; TMR0L=0; // Set config (16bit, postscaler=1:1) T0CON0 = 0x10; // Configure clock (syncronized with FOSC/4, prescale = 1:8192, Clock=HFINTOSC/4) // For 32MHz, F=8MHz, Timebase=8MHz/8192 = 1.024ms T0CON1 = 0x4D; // Enable timer T0CON0bits.T0EN = 1; } uint16_t readTimer0(void) { uint16_t time = TMR0L; // This order is critical, time |= (uint16_t)TMR0H<<8; // TMR0L must be read first! return time; } uint32_t getTime(void){ static uint32_t time = 0; // Full time storage static uint16_t last = 0; // Previous timer (To detect overflow) uint16_t current = readTimer0(); // Current timer value if (last > current){ // If last>current, overflow ocurred time += ((65536 - last) + current); } else{ time += ( current - last ); } last = current; return time; }
Editor is loading...