Untitled

 avatar
unknown
c_cpp
3 years ago
8.2 kB
47
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;
}