void uart_recv_int_handler() { #ifdef __USE18F26J50 if (DataRdy1USART()) { uc_ptr->buffer[uc_ptr->buflen] = Read1USART(); #else #ifdef __USE18F46J50 if (DataRdy1USART()) { uc_ptr->buffer[uc_ptr->buflen] = Read1USART(); #else if (DataRdyUSART()) { uc_ptr->buffer[uc_ptr->buflen] = ReadUSART(); #endif #endif uc_ptr->buflen++; // check if a message should be sent if (uc_ptr->buflen == MAXUARTBUF) { ToMainLow_sendmsg(uc_ptr->buflen, MSGT_UART_DATA, (void *) uc_ptr->buffer); uc_ptr->buflen = 0; } ToMainLow_sendmsg(uc_ptr->buflen, MSGT_UART_DATA, (void *) uc_ptr->buffer); } #ifdef __USE18F26J50 if (USART1_Status.OVERRUN_ERROR == 1) { #else #ifdef __USE18F46J50 if (USART1_Status.OVERRUN_ERROR == 1) { #else if (USART_Status.OVERRUN_ERROR == 1) { #endif #endif // we've overrun the USART and must reset // send an error message for this RCSTAbits.CREN = 0; RCSTAbits.CREN = 1; ToMainLow_sendmsg(0, MSGT_OVERRUN, (void *) 0); } } void uart_trans_int_handler() { unsigned char msgbuffer[MSGLEN+1]; unsigned char msgtype; signed char length; unsigned char start; length = SensorData_recvmsg(start, MSGLEN, &msgtype, (void *) msgbuffer); //unsigned char msg[6]; //msg[0] = 0x0; // i = i << 1; if (msgtest[0] == 0xFF) { msgtest[0] = 0x0; } msgtest[0]++; msgtest[1] = 0xA; msgtest[2] = 0x00; msgtest[3] = msgtest[0]; msgtest[4] = 0xFF; msgtest[5] = 0x0; // if (length == 0) { // PIE1bits.TX1IE = 0x0; // } TXREG1 = msgtest[index]; //i++; index++; //FromMainHigh_recvmsg() if (index == 6) { index = 0; msgtest[0] = msgtest[0] - 0x5; PIE1bits.TX1IE = 0x0; } } void init_uart_recv(uart_comm *uc) { uc_ptr = uc; uc_ptr->buflen = 0; } void uart_send(int length, unsigned char *msg_buffer) { int i = 0; for (i; i < length; i++) { //TXREG1 = msg_buffer[i]; uc_ptr->buffer[i] = msg_buffer[i]; } PIE1bits.TX1IE = 0x0; }
void main(void) { char c; signed char length; unsigned char msgtype; unsigned char last_reg_recvd; uart_comm uc; i2c_comm ic; unsigned char msgbuffer[MSGLEN + 1]; unsigned char i; uart_thread_struct uthread_data; // info for uart_lthread timer1_thread_struct t1thread_data; // info for timer1_lthread timer0_thread_struct t0thread_data; // info for timer0_lthread #ifdef __USE18F2680 OSCCON = 0xFC; // see datasheet // We have enough room below the Max Freq to enable the PLL for this chip OSCTUNEbits.PLLEN = 1; // 4x the clock speed in the previous line #else #ifdef __USE18F45J10 OSCCON = 0x82; // see datasheeet OSCTUNEbits.PLLEN = 0; // Makes the clock exceed the PIC's rated speed if the PLL is on #else #ifdef __USE18F26J50 OSCCON = 0xE0; // see datasheeet OSCTUNEbits.PLLEN = 1; #else #ifdef __USE18F46J50 OSCCON = 0xE0; //see datasheet OSCTUNEbits.PLLEN = 1; //Initialize TRISEbits.TRISE0 = 0x0; LATEbits.LE0 = 0x0; LATEbits.LE0 = 0x1; TRISCbits.TRISC7 = 0x1; // input RX TRISCbits.TRISC6 = 0x0; // output TX SPBRGH1 = 0x00; SPBRG1 = 0xcf; TXSTA1bits.BRGH = 1; BAUDCON1bits.BRG16 = 1; TXSTA1bits.SYNC = 0; RCSTA1bits.SPEN = 0x1; TXSTA1bits.TXEN = 0x1; #else Something is messed up. The PIC selected is not supported or the preprocessor directives are wrong. #endif #endif #endif #endif // initialize my uart recv handling code init_uart_recv(&uc); // initialize the i2c code init_i2c(&ic); // init the timer1 lthread init_timer1_lthread(&t1thread_data); // initialize message queues before enabling any interrupts init_queues(); #ifndef __USE18F26J50 // set direction for PORTB to output TRISB = 0x0; LATB = 0x0; #endif // how to set up PORTA for input (for the V4 board with the PIC2680) /* PORTA = 0x0; // clear the port LATA = 0x0; // clear the output latch ADCON1 = 0x0F; // turn off the A2D function on these pins // Only for 40-pin version of this chip CMCON = 0x07; // turn the comparator off TRISA = 0x0F; // set RA3-RA0 to inputs */ //Initialize the ADC module ADC_Init(); // initialize Timers OpenTimer0(TIMER_INT_ON & T0_16BIT & T0_SOURCE_INT & T0_PS_1_64); #ifdef __USE18F26J50 // MTJ added second argument for OpenTimer1() OpenTimer1(TIMER_INT_ON & T1_SOURCE_FOSC_4 & T1_PS_1_8 & T1_16BIT_RW & T1_OSC1EN_OFF & T1_SYNC_EXT_OFF,0x0); #else #ifdef __USE18F46J50 OpenTimer1(TIMER_INT_ON & T1_SOURCE_FOSC_4 & T1_PS_1_8 & T1_16BIT_RW & T1_OSC1EN_OFF & T1_SYNC_EXT_OFF,0x0); #else OpenTimer1(TIMER_INT_ON & T1_PS_1_8 & T1_16BIT_RW & T1_SOURCE_INT & T1_OSC1EN_OFF & T1_SYNC_EXT_OFF); #endif #endif // Decide on the priority of the enabled peripheral interrupts // 0 is low, 1 is high // Timer1 interrupt IPR1bits.TMR1IP = 0; // USART RX interrupt IPR1bits.RCIP = 0; // I2C interrupt IPR1bits.SSPIP = 1; // configure the hardware i2c device as a slave (0x9E -> 0x4F) or (0x9A -> 0x4D) #if 1 // Note that the temperature sensor Address bits (A0, A1, A2) are also the // least significant bits of LATB -- take care when changing them // They *are* changed in the timer interrupt handlers if those timers are // enabled. They are just there to make the lights blink and can be // disabled. i2c_configure_slave(0x9E); #else // If I want to test the temperature sensor from the ARM, I just make // sure this PIC does not have the same address and configure the // temperature sensor address bits and then just stay in an infinite loop i2c_configure_slave(0x9A); #ifdef __USE18F2680 LATBbits.LATB1 = 1; LATBbits.LATB0 = 1; LATBbits.LATB2 = 1; #endif for (;;); #endif // must specifically enable the I2C interrupts PIE1bits.SSPIE = 1; // configure the hardware USART device #ifdef __USE18F26J50 Open1USART(USART_TX_INT_OFF & USART_RX_INT_ON & USART_ASYNCH_MODE & USART_EIGHT_BIT & USART_CONT_RX & USART_BRGH_LOW, 0x19); #else #ifdef __USE18F46J50 Open1USART(USART_TX_INT_OFF & USART_RX_INT_ON & USART_ASYNCH_MODE & USART_EIGHT_BIT & USART_CONT_RX & USART_BRGH_LOW, 0x19); #else OpenUSART(USART_TX_INT_OFF & USART_RX_INT_ON & USART_ASYNCH_MODE & USART_EIGHT_BIT & USART_CONT_RX & USART_BRGH_LOW, 0x19); #endif #endif // Peripheral interrupts can have their priority set to high or low // enable high-priority interrupts and low-priority interrupts enable_interrupts(); /* Junk to force an I2C interrupt in the simulator (if you wanted to) PIR1bits.SSPIF = 1; _asm goto 0x08 _endasm; */ // printf() is available, but is not advisable. It goes to the UART pin // on the PIC and then you must hook something up to that to view it. // It is also slow and is blocking, so it will perturb your code's operation // Here is how it looks: printf("Hello\r\n"); // loop forever // This loop is responsible for "handing off" messages to the subroutines // that should get them. Although the subroutines are not threads, but // they can be equated with the tasks in your task diagram if you // structure them properly. while (1) { // Call a routine that blocks until either on the incoming // messages queues has a message (this may put the processor into // an idle mode) block_on_To_msgqueues(); // At this point, one or both of the queues has a message. It // makes sense to check the high-priority messages first -- in fact, // you may only want to check the low-priority messages when there // is not a high priority message. That is a design decision and // I haven't done it here. length = ToMainHigh_recvmsg(MSGLEN, &msgtype, (void *) msgbuffer); if (length < 0) { // no message, check the error code to see if it is concern if (length != MSGQUEUE_EMPTY) { // This case be handled by your code. } } else { switch (msgtype) { case MSGT_TIMER0: { DEBUG_ON(TIMER0_MSG_RCV); timer0_lthread(&t0thread_data, msgtype, length, msgbuffer); DEBUG_OFF(TIMER0_MSG_RCV); break; }; case MSGT_I2C_DATA: case MSGT_I2C_DBG: { // Here is where you could handle debugging, if you wanted // keep track of the first byte received for later use (if desired) last_reg_recvd = msgbuffer[0]; break; }; case MSGT_I2C_RQST: { // Generally, this is *NOT* how I recommend you handle an I2C slave request // I recommend that you handle it completely inside the i2c interrupt handler // by reading the data from a queue (i.e., you would not send a message, as is done // now, from the i2c interrupt handler to main to ask for data). // // The last byte received is the "register" that is trying to be read // The response is dependent on the register. switch (last_reg_recvd) { case 0xaa: { length = 2; msgbuffer[0] = 0x55; msgbuffer[1] = 0xAA; break; } case 0xa8: { length = 1; msgbuffer[0] = 0x3A; break; } case 0xa9: { length = 1; msgbuffer[0] = 0xA3; break; } }; start_i2c_slave_reply(length, msgbuffer); break; }; default: { // Your code should handle this error break; }; }; } // Check the low priority queue length = ToMainLow_recvmsg(MSGLEN, &msgtype, (void *) msgbuffer); if (length < 0) { // no message, check the error code to see if it is concern if (length != MSGQUEUE_EMPTY) { // Your code should handle this situation } } else { switch (msgtype) { case MSGT_TIMER1: { timer1_lthread(&t1thread_data, msgtype, length, msgbuffer); break; }; case MSGT_OVERRUN: case MSGT_UART_DATA: { SensorData_recvmsg(MSGLEN, &msgtype, (void *) msgbuffer); unsigned int *msgval; msgval = (unsigned int *) msgbuffer; unsigned int val = *msgval; uart_lthread(&uthread_data, msgtype, length, &val); //unsigned char *msgbuf = msgbuffer; //unsigned int* newval = (unsigned int *) msgbuf; //*newval is the ADC result in hex format //uart_lthread(&uthread_data, msgtype, length, msgbuffer); break; }; default: { // Your code should handle this error break; }; }; } } }