|
//ZHI-HERN LOH //SERIAL INTERFACE FOR Mega128 //SERIAL.H /****USAGE Init_Serial() and sei MUST be called before first use! to output to USART1 (connected to PD[2..3]) 1.Check that OUT_RDY == 1 2.Call S_Out(OutStr) where OutStr contains a pointer to a sram string or call S_Outf(OutStr) where OutStr contains a pointer to a string in flash to read USART1 1.Check that IN_RDY == 1 2.Call S_In(InStr[]) the input buffer is written to InStr ****/ #include <string.h> #include <lcd.h> #include "xmodem.h" #include "sta013.h" #ifndef begin #define begin { #define end } #endif #define BUF_SIZE 64 //the following is a state variable for the //UART, Nmode-for normal I/O // Xmode-for Xmodem transfer unsigned char SERIAL_MODE; #define Nmode 0 #define Xmode 1 unsigned char SERIAL_OUT[BUF_SIZE];//RS232 output unsigned char SERIAL_IN[BUF_SIZE];//RS232 input unsigned char SERIAL_OUT_IDX;//index to serial out unsigned char SERIAL_IN_IDX;//index to serial in #define OUT_RDY SERIAL_OUT[0]==0 //serial port ready for output unsigned char IN_RDY;//serial port input ready to read //the following control the UART ISRs #define USART1_UDRIEN UCSR1B=UCSR1B|(1<<5) //Turn on UDR empty ISR #define USART1_UDRIDIS UCSR1B=UCSR1B&0xdf //Turn off UDR empty ISR #define USART1_RXCIEN UCSR1B=UCSR1B|0x80 //Turn on RXC ISR #define USART1_RXCIDIS UCSR1B=UCSR1B&0x7f //Turn off RXC ISR //Interrupt flags #define RXC UCSR1A&(1<<7)//UCSR1A.7 //rx complete flag #define UDRE UCSR1A&(1<<5)//UCSR1A.5 //UDR empty flag //FUNCTION PROTOTYPES //external prototypes void Init_Serial(void); void S_Out(unsigned char OutStr[]); void S_Outf(unsigned char flash OutStrf[]); void S_Set_Out_Error(unsigned char Error_Code); void S_In(unsigned char InStr[]); void S_Printf(unsigned char flash OutStrf[]); void S_Print(unsigned char OutStr[]); void pause(void); //internal prototypes void Serial_Out_Handler(void);//writes to UART void S_Printf(unsigned char flash OutStrf[]) begin while(OUT_RDY==0); S_Outf(OutStrf); end void S_Print(unsigned char OutStr[]) begin while(OUT_RDY==0); S_Out(OutStr); end void Init_Serial(void) begin UBRR1L = 16;//57.6 Kbps //UBRR1L = 8;//CK16Mhz 115.2Kbps BAUD //UBRR1L = 103;//CK 16MHz, 9600 BAUD //UBRR1L = 51;//CK 8MHz 9600 BAUD UBRR1H = 0; UCSR1C = 2+4;//set to asyn mode,8 bit data UCSR1B = 24;//TX,RX enable for UART1 SERIAL_IN_IDX=0; SERIAL_OUT_IDX=0; SERIAL_IN[0]=0; SERIAL_OUT[0]=0; SERIAL_MODE = Nmode;//set to normal mode for I/O IN_RDY = 0;//no <cr> detected yet USART1_RXCIEN;//turn on RXC ISR end void S_Outf(unsigned char flash OutStrf[]) begin unsigned char OutStr[BUF_SIZE]; strcpyf(OutStr,OutStrf); S_Out(OutStr); end void S_Out(unsigned char OutStr[]) begin SERIAL_OUT_IDX = 0; while(OutStr[SERIAL_OUT_IDX]!=0)//copy to output buffer begin SERIAL_OUT[SERIAL_OUT_IDX] = OutStr[SERIAL_OUT_IDX]; SERIAL_OUT_IDX++; if (SERIAL_OUT_IDX>BUF_SIZE) break; end SERIAL_OUT[SERIAL_OUT_IDX] = 0;//null terminate if (SERIAL_OUT_IDX == 0) //error, fcn given empty str,output ¥ begin S_Set_Out_Error(143);//Å end if (SERIAL_OUT_IDX > BUF_SIZE) begin//buffer overflow S_Set_Out_Error(144);//É //limit to BUF_SIZE characters SERIAL_OUT[BUF_SIZE] = 0;//null terminate end SERIAL_OUT_IDX = 0;//Start TX from element 0 //Turn on UDR empty ISR USART1_UDRIEN; end void S_Set_Out_Error(unsigned char Error_Code) begin SERIAL_OUT[0] = Error_Code; SERIAL_OUT[1] = 0; SERIAL_OUT_IDX = 1; end //reading UART, turn RXCIE off //copy SERIAL_IN to InStr //turn RXCIE on void S_In(unsigned char InStr[]) begin USART1_RXCIDIS;//turn off RXC ISR strcpy(InStr, SERIAL_IN); //Clear IN_RDY flag because message has been read IN_RDY = 0; //reset input buffer SERIAL_IN_IDX=0; USART1_RXCIEN;//turn on RXC ISR end //UART output ISR, reads from SERIAL_OUT[] interrupt [USART1_DRE] void UART_UDRE_interrupt(void) begin //if (SERIAL_MODE == Nmode) Serial_Out_Handler(); //Catch errors if (SERIAL_OUT[SERIAL_OUT_IDX] == 0) begin //TX complete turn this ISR off USART1_UDRIDIS; //Set ready for more input flag SERIAL_OUT[0]=0;//OUT_RDY=1 //DEBUG to see if this runs //PORTC = ~(0x01); end else begin UDR1 = SERIAL_OUT[SERIAL_OUT_IDX++]; end if (SERIAL_OUT[SERIAL_OUT_IDX] == 0) begin //TX complete turn this ISR off USART1_UDRIDIS; //PORTC = ~(UCSR1B);//get 10011000, UDRIE off, so correct //Set ready for more input flag SERIAL_OUT[0]=0;//OUT_RDY=1 //DEBUG to see if this runs //PORTC = ~(0x02); end end //UART input ISR, writes to SERIAL_IN[] interrupt [USART1_RXC] void UART_RXC_interrupt(void) begin unsigned char c; c = UDR1; if (IN_RDY!=1)//cr not detected yet begin //PORTC = PORTC^0x08; //write to buffer if it is not full and not a cr if (c=='\r') begin //PORTC = PORTC^0x01; SERIAL_IN[SERIAL_IN_IDX]=0;//null terminate //UDR1='*';//DEBUG IN_RDY = 1; end else begin //PORTC = PORTC^0x02; SERIAL_IN[SERIAL_IN_IDX] = c; SERIAL_IN_IDX++; UDR1 = c; end end //else dump the input //haven't checked for input overflow end void pause(void) begin unsigned char tmpstr[32]; while(OUT_RDY==0); S_Outf("paused"); while(IN_RDY==0); S_In(tmpstr); while(OUT_RDY==0); S_Outf("resumed\n\r"); end |
|