/* 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 TRISA4 = 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; CKP = 1; #else SCL_DIR = I2C_OUTPUT; SDA_DIR = I2C_OUTPUT; SDA = 0; SCL = 0; #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); //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=%d ", 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; } //sæt status på dioder ud fra styre variablerne 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(); } }