can.c

Go to the documentation of this file.
00001 /*
00002  * CAN Bus access for Sensor Control
00003  * initializes CAN Bus and provides recieving interrupt + sender routines
00004  *
00005  * (c) 2007 by Matthias Arndt <matthias.arndt@tu-clausthal.de>
00006  */
00008 #include "t89c51cc02.h"
00009 #include "datatypes.h"
00010 #include "can.h"
00011 #include "command.h"
00012 
00019 volatile BYTE idata can_data[8];
00020 
00029 void CAN_init()
00030 {
00031         BYTE num_channel,num_data;
00032 
00033         CANGCON |= MSK_CANGCON_GRES;/* reset CAN */ 
00034         /* reset all mailboxes */
00035         for (num_channel = 0; num_channel < 4; num_channel++)
00036         {
00037                 CAN_setchannel(num_channel);
00038 
00039                 CANCONCH = CH_DISABLE;
00040                 CANSTCH  = 0;
00041                 CANIDT1  = 0;
00042                 CANIDT2  = 0;
00043                 CANIDT3  = 0;
00044                 CANIDT4  = 0;
00045                 CANIDM1  = 0;
00046                 CANIDM2  = 0;
00047                 CANIDM3  = 0;
00048                 CANIDM4  = 0;
00049                 for (num_data = 0; num_data < 8; num_data++) CANMSG = 0;
00050         }
00051         /* setup bit timing for 250kbps as used on the robot with the Powercubes connected */
00052         CANBT1   =  BRP_250k  << 1;                  
00053         CANBT2  &= ~0x60;                            
00054         CANBT2  |=  SJW_250k  << 5;                  
00055         CANBT2  &= ~0x0E;                            
00056         CANBT2  |=  PRS_250k  << 1;                  
00057         CANBT3  &= ~0x70;                            
00058         CANBT3  |=  PHS2_250k << 4;                  
00059         CANBT3  &= ~0x0E;                            
00060         CANBT3  |=  PHS1_250k << 1;                  
00061         CANGCON |=  MSK_CANGCON_ENA;                 
00062 
00063         /* Channel 0 init */
00064         CAN_setchannel(0);                          /* CHNB=0x00; select channel 0 */
00065         CANSTCH  = 0x00;                             /* reset channel staus */               
00066         CANCONCH = CH_DISABLE;                       /* reset control and dlc register */            
00067 
00068         /* Channel 0: identifier = 11bits. CANIDT=0x400 */
00069 
00070         CANIDT1 = (BYTE) (((CAN_RECVID<<5) & 0xff00)>>8);
00071         CANIDT2 = (BYTE) (((CAN_RECVID<<5) & 0x00ff));
00072 
00073         /*
00074         CANIDT1 = 0x24;
00075         CANIDT2 &= ~0x80;
00076         CANIDT2 |=  0x60;
00077         */
00078 
00079         /* Channel 0: mask = 11bits. 0xFFF */
00080         CANIDM1 = 0xFF;
00081         CANIDM2 = 0xE0;
00082 
00083         CANIDM4 = 0;
00084 
00085         /* Channel 0 configuration */
00086         CANIDT4 &=~0x04;                             /* clear bit rtr in CANIDT4. */
00087         CANCONCH |= DLC_MAX;                         /* Reception 8 bytes.*/
00088         CANCONCH |= CH_RxENA;                        /* Reception enabled without buffer.*/
00089 
00090         /* Channel 1 init */
00091         CAN_setchannel(1);
00092         CANSTCH  = 0x00;                             /* reset channel status */               
00093         CANCONCH = CH_DISABLE;                       /* reset control and dlc register */            
00094 
00095         /* Channel 1: identifier = 11bits. CANIDT=0x401 */
00096         CANIDT1 = (BYTE) (((CAN_SENDID<<5) & 0xff00)>>8);
00097         CANIDT2 = (BYTE) (((CAN_SENDID<<5) & 0x00ff));
00098         
00099         CANIDM1 = 0xFF;
00100         CANIDM2 = 0xE0;
00101 
00102         CANIDM4 = 0;
00103 
00104         CANSTCH &= !(MSK_CANSTCH_TxOk);
00105 
00106         /* interrupt configuration */
00107         CANIE=0x01;                                /* IECH0=1 */
00108         CANGIE |= MSK_CANGIE_ENTX;                   /* Can_Tx IT enable */
00109         CANGIE |= MSK_CANGIE_ENRX;                   /* Can_Rx IT enable */
00110         ECAN = 1;                                    /* CAN IT enable */
00111         
00112 }
00113 
00119 void CAN_interrupt(void) interrupt 7 using 1
00120 {
00121         bit tmpbit;
00122         BYTE save_canpage;
00123         BYTE i,nr_bytes;                                      /* can_data index, nr of bytes recieved */
00124 
00125         /* CAUTION can interrupt function modify CANPAGE. Save CANPAGE at beginning
00126            and restore it at ending */
00127         save_canpage = CANPAGE;                      /* save current context */
00128 
00129         /* echo received data on channel 0 reception */
00130         CAN_setchannel(0);                          /* CHNB=0x00; select channel 0 */
00131         if(CANSTCH&MSK_CANSTCH_RxOk)        
00132         {
00133                 /* if we did recieve something on Channel 0 - we process it here */
00134                 nr_bytes = (CANCONCH & 0x0f);
00135 
00136                 for (i=0; i<nr_bytes; i++) can_data[i] = CANMSG; /* save receive data */
00137                 
00138                 /* check for possible commands*/
00139                 switch(can_data[0])
00140                 {
00141                 case COMMAND_READ:
00142                         /* request reading of a given sensor
00143                          * Frame length: 2 bytes
00144                          * Frame struct: COMMAND_READ <sensor>
00145                          */
00146                         if(nr_bytes!=2)
00147                         {
00148                                 CAN_SendNAK(COMMAND_READ);
00149                         } else {
00150                                 Command_SetRead(can_data[1]);
00151                                 CAN_SendACK(COMMAND_READ);
00152                         }
00153                         break;
00154 
00155                 case COMMAND_MONITOR:
00156                         /* request monitoring of a given sensor
00157                          * Frame length: 5 bytes
00158                          * Frame struct: COMMAND_MONITOR <sensor> <boundary> <direction>
00159                          * <boundary> is encoded into 2 bytes, high byte first (Big Endian)
00160                          */
00161                         if(nr_bytes!=5)
00162                         {
00163                                 CAN_SendNAK(COMMAND_MONITOR);
00164                         } else {
00165                                 tmpbit=0;
00166                                 if(can_data[4]!=0)
00167                                         tmpbit=1;
00168                                 Command_EnableMonitor(can_data[1],can_data[2]*256+can_data[3],tmpbit);
00169                                 CAN_SendACK(COMMAND_MONITOR);
00170                         }
00171                         break;
00172 
00173                 case COMMAND_STOPMONITOR:
00174                         /* stop monitoring of a given sensor
00175                          * Frame length: 2 bytes
00176                          * Frame struct: COMMAND_STOPMONITOR <sensor>
00177                          */
00178                         if(nr_bytes!=2)
00179                         {
00180                                 CAN_SendNAK(COMMAND_STOPMONITOR);
00181                         } else {
00182                                 Command_DisableMonitor(can_data[1]);
00183                                 CAN_SendACK(COMMAND_STOPMONITOR);
00184                         }
00185                         break;
00186 
00187                 case COMMAND_MONITORSTATUS:
00188                         /* report status of active monitors */
00189                         can_data[0]='m';
00190                         can_data[1]= (BYTE) ((monitor & 0xFF000000) >> 24);
00191                         can_data[2]= (BYTE) ((monitor & 0x00FF0000) >> 16);
00192                         can_data[3]= (BYTE) ((monitor & 0x0000FF00) >> 8);
00193                         can_data[4]= (BYTE) (monitor & 0x000000FF);
00194                         CAN_SendMsg(5); /* send status package */
00195                         break;
00196                         
00197                 case COMMAND_RECALLMONITOR:
00198                         /* schedule a reload of the monitor settings from the EEPROM contents */
00199                         read_eeprom_config=1;
00200                         CAN_SendACK(COMMAND_RECALLMONITOR);
00201                         break;
00202 
00203                 case COMMAND_STOPALLMONITORS:
00204                         /* stop all monitoring processes */
00205                         monitor=0;
00206                         CAN_SendACK(COMMAND_STOPALLMONITORS);
00207                         break;
00208 
00209                 case COMMAND_REPORT:
00210                         /* start of reporting: 
00211                          * Frame length: 2 bytes
00212                          * Frame struct: COMMAND_REPORT <boundary> 
00213                          */
00214                         if(nr_bytes!=2)
00215                         {
00216                                 CAN_SendNAK(COMMAND_REPORT);
00217                         } else {
00218                                 Command_EnableReport(can_data[1]);
00219                                 CAN_SendACK(COMMAND_REPORT);
00220                         }
00221                         break;
00222 
00223                 case COMMAND_STOPREPORT:
00224                         /* stop of reporting */
00225                         Command_DisableReport();
00226                         CAN_SendACK(COMMAND_STOPREPORT);
00227                         break;
00228                 
00229                 case COMMAND_TIMECHECK_ENABLE:
00230                         /* enable checking of timing constraints */
00231                         Command_TimecheckEnable();
00232                         CAN_SendACK(COMMAND_TIMECHECK_ENABLE);
00233                         break;
00234 
00235                 case COMMAND_TIMECHECK_DISABLE:
00236                         /* disable checking of timing constraints */
00237                         Command_TimecheckDisable();
00238                         CAN_SendACK(COMMAND_TIMECHECK_DISABLE);
00239                         break;
00240 
00241                 case COMMAND_TIMECHECKSTATUS:
00242                         /* report status of timing constraints */
00243                         can_data[0]='t';
00244                         if(Command_CheckTime())
00245                         {
00246                                 can_data[1]=0x01;
00247                         } else {
00248                                 can_data[1]=0x00;
00249                         }
00250                         CAN_SendMsg(2); /* send status package */
00251                         break;
00252 
00253                 case COMMAND_EEPROM_SAVEMONITOR:
00254                         /* save current monitoring parameters to EEPROM */
00255                         write_eeprom_config=1;
00256                         CAN_SendACK(COMMAND_EEPROM_SAVEMONITOR);
00257                         break;
00258         
00259                 case COMMAND_EEPROM_CLEAR:
00260                         /* TODO: clear EEPROM configuration */
00261                         CAN_SendNAK(COMMAND_EEPROM_CLEAR);
00262                         break;
00263 
00264                 case COMMAND_RESET:
00265                         /* disables all report and monitor functions */
00266                         Command_DisableReport();
00267                         Command_ClearRead();
00268                         Command_ClearMonitor();
00269                         CAN_SendACK(COMMAND_RESET);
00270                         break;
00271                 default:
00272                         /* unrecognized commands are ignored */
00273                         /* CAN_SendNAK(can_data[0]); */
00274                         break;
00275                 }               
00276         }
00277 
00278         CAN_setchannel(0);                           /* CHNB=0x00; select channel 0 */
00279         CANCONCH = CH_DISABLE;                       /* reset channel 0 configuration */            
00280         CANCONCH |= DLC_MAX;                         /* receive 8 bytes */
00281         CANCONCH |= CH_RxENA;                        /* reception enable */
00282         CAN_enablechannel(0);                          /* channel 0 enable */
00283         CANSTCH=0x00;                                /* reset channel 0 status */
00284 
00285         CANPAGE= save_canpage;                       /* restore saved context */ 
00286 
00287         CANGIT = 0x00;                               /* reset all flags */ 
00288 }
00289 
00296 void CAN_SendACK(BYTE cmd)
00297 {
00298                 CAN_setchannel(1);                       /* CHNB=0x00; select channel 1 */
00299                 while(!(CANSTCH&MSK_CANSTCH_TxOk));      /* wait for last transmission to finish */
00300                 /* Channel 1 configuration */
00301                 CANCONCH = CH_DISABLE;                    /* reset channel 1 configuration */            
00302                 CANMSG = cmd;
00303                 CANMSG = CAN_ACK;                       /* answer is ASCII ACK 0x06*/
00304                 
00305                 CANCONCH |= 2;              
00306         
00307                 CANCONCH |= CH_TxENA;                     /* emission enabled */
00308                 CAN_enablechannel(1);                       /* channel 1 enable */
00309                 CANSTCH=0x00; 
00310 }
00311 
00319 void CAN_SendNAK(BYTE cmd)
00320 {
00321                 CAN_setchannel(1);                       /* CHNB=0x00; select channel 1 */
00322                 while(!(CANSTCH&MSK_CANSTCH_TxOk));      /* wait for last transmission to finish */
00323                 /* Channel 1 configuration */
00324                 CANCONCH = CH_DISABLE;                    /* reset channel 1 configuration */            
00325                 CANMSG = cmd;
00326                 CANMSG = CAN_NAK;                       /* answer is ASCII ACK 0x06*/
00327                 
00328                 CANCONCH |= 2;              
00329         
00330                 CANCONCH |= CH_TxENA;                     /* emission enabled */
00331                 CAN_enablechannel(1);                       /* channel 1 enable */
00332                 CANSTCH=0x00; 
00333 }
00334 
00335 
00344 void CAN_SendMsg(BYTE length)
00345 {
00346         BYTE i;
00347         CAN_setchannel(1);                       /* CHNB=0x00; select channel 1 */
00348         while(!(CANSTCH&MSK_CANSTCH_TxOk));      /* wait for last transmission to finish */
00349         /* Channel 1 configuration */
00350         CANCONCH = CH_DISABLE;                    /* reset channel 1 configuration */            
00351         
00352         ECAN=0; /* to make sure the internal data buffer is not overwritten, we disable the CAN IRQ */
00353         for(i=0;i<length;i++)
00354                 CANMSG = can_data[i];                   
00355 
00356         CANCONCH |= length;              
00357         ECAN=1;        
00358 
00359         CANCONCH |= CH_TxENA;                     /* emission enabled */
00360         CAN_enablechannel(1);                       /* channel 1 enable */
00361         CANSTCH=0x00; 
00362 }

Generated on Wed Oct 24 12:57:24 2007 for SensorControl by  doxygen 1.4.6