Hi Everyone, I have 3 controllers, all using SILABS C8051F040 SOC. They perfrom various functions on there own and communicate via CAN. They are working well together (I fixed one major problem I will detail further down). The transmission of data is handled by configuring message boxes on the fly and transmitting them and works well. The reception is handled by an interupt routine activated by a message that passes the arbritation filters. When the interupt routine is called, it calls a function I named cancieve(). Here is a sample of the beggining of one conrollers cancieve function
xdata unsigned int rx_buff[4]; xdata union { float floater; unsigned long int longinter; unsigned char string[4]; unsigned long int mscounter; unsigned int interger[2]; } float_char; unsigned char org_msgnum; unsigned char PRI_LEV; org_msgnum= CAN_sep_ident(CAN_receive_data (msg_number, rx_buff), &PRI_LEV); if ((PRI_LEV==7)&&(org_msgnum==5)) { exc_noCAN_cntr=0; //reset exciter no value counter float_char.interger[0]=rx_buff[0]; float_char.interger[1]=rx_buff[1]; EXC_STATUS1=float_char.string[0]; EXC_STATUS2=float_char.string[1]; return; }
bdata unsigned char EXC_STATUS3; sbit I_LEAD_OV =EXC_STATUS3^0; //current lead over voltage sbit RECIRC_DIODE_OT=EXC_STATUS3^1; //re-circulating diode over temp sbit ABORT_RES_OT =EXC_STATUS3^2; //dump resistor over temp sbit ABORT_IGBT_OT =EXC_STATUS3^3; sbit AMB_TEMP_OT =EXC_STATUS3^5; sbit SHNTFLT_SOFT =EXC_STATUS3^6; sbit SYS_HEARTBEET =EXC_STATUS3^7;
volatile unsigned char bdata EXC_STATUS3; sbit I_LEAD_OV =EXC_STATUS3^0; //current lead over voltage sbit RECIRC_DIODE_OT=EXC_STATUS3^1; //re-circulating diode over temp sbit ABORT_RES_OT =EXC_STATUS3^2; //dump resistor over temp sbit ABORT_IGBT_OT =EXC_STATUS3^3; sbit AMB_TEMP_OT =EXC_STATUS3^5; sbit SHNTFLT_SOFT =EXC_STATUS3^6; sbit SYS_HEARTBEET =EXC_STATUS3^7;
I never had to declare anything as volatile before and am still looking into what it really means. volatile means that the value of a variable may change for a reason not apparent to the code generator given a local view of the code in a particular place. That is, if the compiler is generating code for the source: j = i; j = i; it's clear that this particular code snippet does not change i from one line to the next, and thus you might naturally expect that there is no point in reading i twice. One line could be optimized out -- if this one bit of code is the only thing to consider. However, i is some memory location, and that memory location could change for reasons that don't show up in those two lines of code. The usual example is a hardware register. The hardware itself is active, and might change between lines. In that case, the compiler needs to generate an actual bus transaction on each read rather than using a value in a register. With some hardware, the point of doing a read or write is sometimes not to move a value, but just to generate a bus transaction and toggle some bits. Other cases where 'i' might change would be an interrupt handler, or a preemptive threaded system where two threads share memory. Either might interrupt between those two lines of C and change the value of i, requiring the compiler always to read the memory location to be sure it has an up to date copy. Even though the compiler may "know" about the interrupt handler or the other thread because it's all software, in the face of separate compilation a compiler cannot always know where such relationships exist. It's up to the programmer to identify these cases for the compiler by using volatile In short, use volatile whereever you have a memory location shared with another active context in your hardware or software that can update it.
Thanks for the info Drew, Andy