--- trunk/PIC/main.c 2007/01/29 09:45:25 2 +++ trunk/PIC/main.c 2007/01/31 12:40:37 27 @@ -1,15 +1,417 @@ /* H7 -projekt opgave */ - + +/////////////////////////////////////////////////////////////////////// +//Includes #include +#include +#include + #include "delay.h" #include "i2c.h" #include "lcd.h" - +///////////////////////////////////////////////////////////////////// +//Defines #define TC74 0x9A /* I2C TC74 IC */ +#define SLIP_END 192 +#define SLIP_ESC 219 +#define SLIP_ESCAPED_END 220 +#define SLIP_ESCAPED_ESC 221 + +#define BUFFERLEN 16 + +////////////////////////////////////////////////////////////////// +// Enumerations + +enum SlipState{ + SlipNormal, + SlipEscaped, + SlipError, + SlipStopped +}; + +enum BaudRates{ + Baud1200, + Baud2400, + Baud4800, + Baud9600, + Baud19200 +}; + +enum Commands{ + CmdRead, + CmdWrite, + CmdAck, + CmdNAck +}; + +enum Targets { + TLed3, //0 + TLed4, + TLed5, + TSwitch2, + TSwitch3, + TPotmeter, + TTemp, + TBaud = 10 +}; + +////////////////////////////////////////////////////////////////// +//Globale data +// Alle globale variabler bruger "global_" som prefix + +unsigned char global_comm_buffer[BUFFERLEN]; +unsigned char global_comm_length; + +bit global_comm_ready; +bit global_comm_error; + +unsigned char global_comm_slipstate; +unsigned char global_comm_baudrate; + +unsigned char global_lcd_buffer[2][BUFFERLEN]; + + +bit global_led_0; +bit global_led_1; +bit global_led_2; + +bit global_reset_baudrate; + +char global_temp; +unsigned char global_potmeter_hi; +unsigned char global_potmeter_lo; + +/////////////////////////////////////////////////////////////////// +// Interrupt funktioner + +void recieve_interrupt(void) +{ + unsigned char data = RCREG; + + if (global_comm_length == BUFFERLEN) //avoid buffer overrun + global_comm_slipstate == SlipError; + + switch (global_comm_slipstate) + { + case SlipNormal: + if (data == SLIP_END) + { + global_comm_ready = 1; + global_comm_slipstate = SlipStopped; + } + else if (data == SLIP_ESC) + { + global_comm_slipstate = SlipEscaped; + } + else + global_comm_buffer[ global_comm_length++ ] = data; + break; + + case SlipEscaped: + if (data == SLIP_ESCAPED_ESC) + { + global_comm_buffer[ global_comm_length++ ] = SLIP_ESC; + global_comm_slipstate = SlipNormal; + } + else if (data ==SLIP_ESCAPED_END) + { + global_comm_buffer[ global_comm_length++ ] = SLIP_END; + global_comm_slipstate = SlipNormal; + } + else + { + global_comm_slipstate = SlipError; + } + case SlipError: + if (data == SLIP_END) + { + global_comm_error = 1; + global_comm_slipstate = SlipStopped; + global_comm_ready = 1; + } + case SlipStopped: //vi var ikke klar til at modtage data + global_comm_error = 1; + } +} + +/* +void transmit_interrupt(void) +{ + RB2 = !RB2; +} +*/ +//Timer1 er en 16 bit timer, der kører med en 1:8 prescaler, +// og er styret fra en ekstern 32768 Hz krystal +//Når at registrene preloades med 0xEFFF vil det resultere i en +//timer overflow ca hvert sekund +void timer1_interrupt(void) +{ + TMR1H = 0xEF; + TMR1L = 0xFF; +} +void interrupt interrupt_handler(void) +{ + if (RCIF == 1) + { + recieve_interrupt(); + RCIF = 0; + } + /*if (TXIF == 1) + { + transmit_interrupt(); + TXIF = 0; + } + */ + + if (TMR1IF == 1) + { + timer1_interrupt(); + TMR1IF = 0; + } +} + +/////////////////////////////////////////////////////////////////// +// Slip funktioner + + +void slip_reset(void) +{ + global_comm_error = 0; + global_comm_slipstate = SlipNormal; + global_comm_ready = 0; + global_comm_length = 0; + memset(global_comm_buffer, 0, BUFFERLEN); +} + +void slip_highlevel_protocol(void) +{ + unsigned char cmd,target,data; + + cmd = global_comm_buffer[0] & 0x0F; + target = ( global_comm_buffer[0] >> 4 ) & 0x0F; + data = global_comm_buffer[1]; + + if (cmd == CmdRead || cmd == CmdWrite) + { + //sæt standart længde - da længden kun varierer ved læsning af potmeter + if (cmd == CmdRead) + global_comm_length = 2; + else + global_comm_length = 1; + + switch(target) + { + case TLed3: + if (cmd == CmdRead) + global_comm_buffer[1] = global_led_0; + else + global_led_0 = data; + break; + case TLed4: + if(cmd == CmdRead) + global_comm_buffer[1] = global_led_1; + else + global_led_1 = data; + break; + case TLed5: + if (cmd == CmdRead) + global_comm_buffer[1] = global_led_2; + else + global_led_2 = data; + break; + case TSwitch2: + if (cmd == CmdRead) + global_comm_buffer[1] = !RA4; + else + global_comm_error = 1; + break; + case TSwitch3: + if (cmd == CmdRead) + global_comm_buffer[1] = !RB0; + else + global_comm_error = 1; + break; + case TPotmeter: + if (cmd == CmdRead) + { + global_comm_buffer[1] = global_potmeter_hi; + global_comm_buffer[2] = global_potmeter_lo; + global_comm_length = 3; + } + else + global_comm_error = 1; + break; + case TTemp: + if (cmd == CmdRead) + global_comm_buffer[1] = global_temp; + else + global_comm_error = 1; + break; + case TBaud: + if (cmd == CmdRead) + global_comm_error = 1; + else + { + //we can only handle 1200,2400,9600,19200 + if (data == 0 || data == 1 || data == 3 || data == 4) + { + global_reset_baudrate = 1; + global_comm_baudrate = data; + } + else + global_comm_error = 1; + } + break; + default: + global_comm_error = 1; + + } + } + else //kommandoen var noget andet end read/write + { + global_comm_error = 1; + } + + + if (global_comm_error == 1) //we saw an error + { + global_comm_buffer[0] = CmdNAck | target<<4; + global_comm_length = 1; + } + else + { + global_comm_buffer[0] = CmdAck | target<<4; //skriv acknowledge feltet + } +} + +void slip_send_byte(char data) +{ + TXREG = data; + while (TRMT==0) ; + DelayUs(20); +} + +void slip_send_response(void) +{ + int i; + for (i=0; i< global_comm_length;i++) + { + if ( global_comm_buffer[i] == SLIP_ESC) + { + slip_send_byte(SLIP_ESC); + slip_send_byte(SLIP_ESCAPED_ESC); + } + else if (global_comm_buffer[i] == SLIP_END) + { + slip_send_byte(SLIP_ESC); + slip_send_byte(SLIP_ESCAPED_END); + } + else + { + slip_send_byte( global_comm_buffer[i]); + } + } + + slip_send_byte(SLIP_END); +} + +/////////////////////////////////////////////////////////////////// +// init funktioner + +void interrupt_init(void) +{ + TXIE = 0; //Disable AUX TX interrupt - testes med TXIF; + RCIE = 1; //Enable AUX Recieve interrupt - testes med RCIF; + + IPEN = 0; // IPEN=Interrupt Priority ENable bit - her bruges ingen prioritet + + PEIE = 1; // PEIE = PEriphal Interrupt Enable + + TXIF = 0; //nulstil intterupt flag + RCIF = 0; + + TMR1IE = 1; // Timer 1 + + GIE = 1; //Global interrupt enable bit +} + +void serial_init(void) +{ + SPEN = 0; //Make sure serial port is disabled + + // snupset fra Kim H Pedersens serialmain.c + // Set Port C bit 6 output (TxD) and bit 7 input (RxD) + TRISC6 = 0; + TRISC7 = 1; + + SPBRG = 25; // x = Fosc/(16 * Baud Rate) - 1 + // x = 4000000/(16 * 9600) - 1 + // x = 25.0417 ~ 25 + // Baud Rate = Fosc/(16 * (x+1)) + // Baud Rate = 4000000/(16 * (25+1)) + // Baud Rate = 9615 + TXSTA = 0x24; // TXSTA7 = 0 Don't care in asynchronous + // TXSTA6 = 0 8-bit transmission + // TXSTA5 = 1 Transmit enabled + // TXSTA4 = 0 Asynchronous mode + // TXSTA3 = 0 Unimplemented + // TXSTA2 = 1 High speed + // TXSTA1 = 0 TSR empty + // TXSTA0 = 0 9th bit */ + RCSTA = 0x90; // RCSTA7 = 0 Serial port disabled + // RCSTA6 = 0 8-bit reception + // RCSTA5 = 0 Don't care in asynchronous + // RCSTA4 = 1 Receiver enabled + // RCSTA3 = 0 Don't care (8-bit operation) + // RCSTA2 = 0 No framing error + // RCSTA1 = 0 Overrun error bit + // RCSTA0 = 0 9th bit */ + + //config completed + SPEN = 1; //Enable Serial port +} + +/* basic I/O ports */ +void io_init(void) +{ + TRISB3 = 0; //LED ports = output + TRISB2 = 0; + TRISB1 = 0; + + TRISB0 = 1; //Switch porte = input + TRISA0 = 1; +} + +void ad_init(void) +{ + // AD Conversion clock + ADCS0 = 0; + ADCS1 = 0; + ADCS2 = 0; + + //Select AN0/RA0 for AD source + CHS0=0; + CHS1=0; + CHS2=0; + + //Only AN0 is selected for AD and with Vdd/Vss as limits + PCFG0=0; + PCFG1=1; + PCFG2=1; + PCFG3=1; + + //Result is right justified + ADFM=1; + + //Fire up for A/D converter module + ADON=1; +} + void i2c_init(void) { +// I2C_MODULE hører hjemme i i2c.h #ifdef I2C_MODULE SSPMode(MASTER_MODE); SSPEN = 1; @@ -22,24 +424,145 @@ #endif } +void timer_init(void) +{ + TMR1CS = 1; //use external clock + + T1CKPS1 = 1; //1:8 prescale + T1CKPS0 = 1; + + TMR1H = 0xEF; + TMR1L = 0xFF; + + T1OSCEN = 1; //enable oscillator circuit + RD16 = 0; //normal 8 bit writes + TMR1ON = 1; +} + +/////////////////////////////////////////////////////////////////// +// Gennerelle funktioner + + char ReadTemp(void) { char temp; - i2c_WriteTo(TC74); + i2c_WriteTo(TC74); //write to, will automatically send a start condition i2c_PutByte(0x00); //tell TC74 we want to read i2c_ReadFrom(TC74); temp = i2c_GetByte(I2C_LAST); i2c_Stop(); //assert a stop condition on SDA & SCL return temp; -} +} + + + +void update_lcd(void) +{ + static char current_row = 0; + static char current_char = 0; + + if ( current_char >= BUFFERLEN || global_lcd_buffer[current_row][current_char] == 0 ) + { + current_row++; + current_char = 0; + lcd_goto(0x40); + } + + if (current_row >= 2) + { + sprintf(global_lcd_buffer[1], "T=%02d, P=%04d", global_temp, (global_potmeter_hi<<8) | global_potmeter_lo); + lcd_goto(0x00); + current_row = 0; + } + + lcd_putch(global_lcd_buffer[current_row][current_char]); + current_char++; +} + +void reset_baudrate(void) +{ + SPEN = 0; //disable serial port + + //set baudrate generator, i henhold til side 171 af PIC18F452 dokumentationen + switch (global_comm_baudrate) + { + case Baud1200: + SPBRG = 207; + strcpy(global_lcd_buffer[0],"Baud=1200 "); + break; + case Baud2400: + SPBRG = 103; + strcpy(global_lcd_buffer[0],"Baud=2400 "); + break; + case Baud9600: + SPBRG = 25; + strcpy(global_lcd_buffer[0],"Baud=9600 "); + break; + case Baud19200: + SPBRG = 12; + strcpy(global_lcd_buffer[0],"Baud=19200"); + break; + default: + strcpy(global_lcd_buffer[0],"Baud=9600 "); + SPBRG = 25; // this should not be possible, but default to 9600 anyway + } + SPEN = 1; // enable the serial port again +} + +/////////////////////////////////////////////////////////////////// +//Main + void main(void) { lcd_init(0); //init in 4-bit mode i2c_init(); + serial_init(); //9600 8N1 + ad_init(); + io_init(); + timer_init(); + interrupt_init(); + + + slip_reset(); //take SLIP FSM into normal state + global_comm_baudrate = Baud9600; //default baudrate = 9600 (allready set in serial_init) + global_reset_baudrate = 0; + +// initialisation completed and we are ready to recieve commands - enable serial reception + CREN = 1; + strcpy(global_lcd_buffer[0], "Baud=9600 "); while (1) { + if (global_comm_ready == 1) + { + slip_highlevel_protocol(); //parse the slip frame recieved & generate response + slip_send_response(); + slip_reset(); + } + + if ( global_reset_baudrate == 1) + { + reset_baudrate(); + global_reset_baudrate = 0; + } + + RB1 = global_led_0; + RB2 = global_led_1; + RB3 = global_led_2; + + global_temp = ReadTemp(); + + //potmeter + if (GODONE ==0 )//hvis A/D-conv er færdig + { + + global_potmeter_hi = ADRESH;//gem AD resultat + global_potmeter_lo = ADRESL; + GODONE = 1; //start ny konverering + } + + update_lcd(); } }