Hello, i'm fairly new in HCS12 an CAN programming and have a problem getting the MSCAN Module to work properly. The problem is that i try to write a little CANMonitor for the MC9S12DG256 in C (using ImageCraft ICC12 Version 6). For the first tests i adapted a code example from Steve Letkeman with interrupt driven CAN Receive and the MSCAN Module is working in Loopback Mode. But when i try to debug the program i see that the transmit an the recieve buffers differ. That means that the received data is not the same as the transmitted data. When i transmit the following: CANID0 = 0x2d; CANID1 = 0xf0; CANID2 = 0x00; CANID3 = 0x00; CANDATA0 = 0x01; CANDATA0 = 0x02; CANDATA0 = 0x03; CANDATA0 = 0x04; CANDATA0 = 0x05; CANDATALENGTH = 0x05; i get the following in the receive buffer: CANID0 = 0x2d; CANID1 = 0xf0; CANID2 = 0xEF; CANID3 = 0x8E; CANDATA0 = 0xF3; CANDATA0 = 0xC7; CANDATA0 = 0x00; CANDATA0 = 0xAF; CANDATA0 = 0x1D; CANDATALENGTH = 0x05; So the received data is partly correct - why? The CAN Initialisation is done by the following function: ========================================================= void CANInit(void){ CAN0CTL0 |= INITRQ; // set INITRQ, this will also set INITAK while (!(CAN0CTL1 & INITAK)); // wait for init mode to occur CAN0CTL1 = 0xA0; CAN0BTR0=0x28; // BRPR = 40, Sync = 1 CAN0BTR1=0x32; // TSEG1 = 3, TSEG2 = 4 CAN0IDAR0=0xFF; CAN0IDAR1=0xFF; CAN0IDAR2=0xFF; CAN0IDAR3=0xFF; CAN0IDAR4=0xFF; CAN0IDAR5=0xFF; CAN0IDAR6=0xFF; CAN0IDAR7=0xFF; CAN0IDMR0=0xFF; CAN0IDMR1=0xFF; CAN0IDMR2=0xFF; CAN0IDMR3=0xFF; CAN0IDMR4=0xFF; CAN0IDMR5=0xFF; CAN0IDMR6=0xFF; CAN0IDMR7=0xFF; CAN0IDAC = 0; CAN0CTL0 &= ~INITRQ; // clear INITRQ while (CAN0CTL1 & INITAK); CAN0RFLG = 0xFF; CAN0CTL1 = 0xA0; CAN0RIER = 1; } ======================================================= I had to redirect the interrupt vectors because of the monitor program: ======================================================= void interruptRedirect(void){ // CAN 0 Recieve Interrupt /////////////////////////// *((unsigned char *)0x3F8E) = 0x06; *((void (**)(void))0x3F8F) = CAN_Recieve; // CAN 0 Transmit Interrupt ////////////////////////// *((unsigned char *)0x3F8B) = 0x06; *((void (**)(void))0x3F8C) = CAN_Transmit; // CAN 0 Error Interrupt ////////////////////////// *((unsigned char *)0x3F91) = 0x06; *((void (**)(void))0x3F92) = CAN_Error; } ================================================= The ISR for CAN receive looks like this: ================================================= #pragma interrupt_handler CAN_Recieve void CAN_Recieve(void){ int i=0, x=0; // Find Empty MessageBuffer /////////////////////////// while(CANMess[i].messact != 0) i++; if (i > MAXCANMESSAGES){ if(DEBUGPRINT) printf("CAN Trancieve Error: No Free Buffer to store Message !"); CAN0RFLG |=1; // clear rec flag return; } // Set status of Message to Recieve Message /////////////////////////////////////////// CANMess[i].messact = 1; // Check for Number of Bytes in CAN Message /////////////////////////////////////////// CANMess[i].length = CAN0RXDLR & 0x0F; // Copy ID to Messagebuffer /////////////////////////// CANMess[i].id0 = CAN0RXIDR0; CANMess[i].id1 = CAN0RXIDR1; CANMess[i].id2 = CAN0RXIDR2; CANMess[i].id3 = CAN0RXIDR3; // Copy Data to Messagebuffer ///////////////////////////// for (x=0;x<CANMess[i].length;x++) CANMess[i].data[x] = *(CAN0RXDATA+x); CAN0RFLG |=1; // clear rec flag } ==================================================== And this is the main function: ==================================================== void main(void){ int i=0, j=0; unsigned char ch; unsigned char temp[5]; for(i=0;i<MAXCANMESSAGES;i++) CANMess[i].messact=0; interruptRedirect(); // Redirect Interrupts CANInit(); // Init MSCAN asm("cli"); // Enable global Interrupts temp[0] = 1; temp[1] = 2; temp[2] = 3; temp[3] = 4; temp[4] = 5; SendCANMessage(5,temp); while(1){ // Checking Messagebuffer for Entrys //////////////////////////////////// for(i=0;i<MAXCANMESSAGES;i++){ if(CANMess[i].messact == 1){ CANMess[i].messact = 0; SendCANMessage(5,temp); } } } } ============================================== The SendCANMessage looks like this: ============================================== void SendCANMessage(unsigned char NumBytes, unsigned char *BufPntr){ unsigned char NACAN,C; while(!CAN0TFLG); // wait for available buffer NACAN0TFLG; // get the next available CAN buffer CAN0TBSEL=NACAN; CAN0TXIDR0 = 0x2D; CAN0TXIDR1 = 0xF0; CAN0TXIDR2 = 0x00; CAN0TXIDR3 = 0x00; if (NumBytes>8) NumBytes=8; for (C=0;C<NumBytes;C++) *(CAN0TXDATA+C)=*BufPntr++; // store the data CAN0TXDLR=NumBytes; // set number of bytes to send NACAN0TBSEL; CAN0TFLG =NACAN; // transmit } =========================================================== I have tested the the program an 2 different MC9S12 but the result is the same - the tranmsitted message is not equal to the received. Have i missed something? Thanks in advance. Greets Daniel PS: I must apologize for my bad english. |
|
MC9S12DG256: CAN Problems
Started by ●January 17, 2005
Reply by ●January 17, 20052005-01-17
Hi, Your SendCANMessage routine is sending 11 bit RTR messages. Only ID bits and data length bits can be carried by RTR message. It's not possible to send any data byte when RTR is set. > void SendCANMessage(unsigned char NumBytes, unsigned char *BufPntr){ > > unsigned char NACAN,C; > while(!CAN0TFLG); // wait for available buffer > NACAN0TFLG; // get the next available CAN buffer > CAN0TBSEL=NACAN; > > CAN0TXIDR0 = 0x2D; > CAN0TXIDR1 = 0xF0; ^^ ID2:0=7, RTR=1, IDE=0. Check the "Standard Identifier Mapping" in MSCAN docs. > CAN0TXIDR2 = 0x00; > CAN0TXIDR3 = 0x00; BTW > CAN0RFLG |=1; // clear rec flag ^^^ this line can clear more than just CAN0RFLG RXF bit. If for example CSCIF is set it will be cleared too. Edward > Hello, > > i'm fairly new in HCS12 an CAN programming and have a problem getting > the MSCAN Module to work properly. The problem is that i try to write > a little CANMonitor for the MC9S12DG256 in C (using ImageCraft ICC12 > Version 6). For the first tests i adapted a code example from Steve > Letkeman with interrupt driven CAN Receive and the MSCAN Module is > working in Loopback Mode. But when i try to debug the program i see > that the transmit an the recieve buffers differ. That means that the > received data is not the same as the transmitted data. > > When i transmit the following: > CANID0 = 0x2d; > CANID1 = 0xf0; > CANID2 = 0x00; > CANID3 = 0x00; > CANDATA0 = 0x01; > CANDATA0 = 0x02; > CANDATA0 = 0x03; > CANDATA0 = 0x04; > CANDATA0 = 0x05; > CANDATALENGTH = 0x05; > > i get the following in the receive buffer: > CANID0 = 0x2d; > CANID1 = 0xf0; > CANID2 = 0xEF; > CANID3 = 0x8E; > CANDATA0 = 0xF3; > CANDATA0 = 0xC7; > CANDATA0 = 0x00; > CANDATA0 = 0xAF; > CANDATA0 = 0x1D; > CANDATALENGTH = 0x05; > > So the received data is partly correct - why? > > The CAN Initialisation is done by the following function: > > ========================================================= > void CANInit(void){ > > CAN0CTL0 |= INITRQ; // set INITRQ, this will also set INITAK > while (!(CAN0CTL1 & INITAK)); // wait for init mode to occur > > CAN0CTL1 = 0xA0; > > CAN0BTR0=0x28; // BRPR = 40, Sync = 1 > CAN0BTR1=0x32; // TSEG1 = 3, TSEG2 = 4 > > CAN0IDAR0=0xFF; > CAN0IDAR1=0xFF; > CAN0IDAR2=0xFF; > CAN0IDAR3=0xFF; > CAN0IDAR4=0xFF; > CAN0IDAR5=0xFF; > CAN0IDAR6=0xFF; > CAN0IDAR7=0xFF; > > CAN0IDMR0=0xFF; > CAN0IDMR1=0xFF; > CAN0IDMR2=0xFF; > CAN0IDMR3=0xFF; > CAN0IDMR4=0xFF; > CAN0IDMR5=0xFF; > CAN0IDMR6=0xFF; > CAN0IDMR7=0xFF; > > CAN0IDAC = 0; > CAN0CTL0 &= ~INITRQ; // clear INITRQ > while (CAN0CTL1 & INITAK); > > CAN0RFLG = 0xFF; > CAN0CTL1 = 0xA0; > > CAN0RIER = 1; > } > ======================================================= > > I had to redirect the interrupt vectors because of the monitor > program: > > ======================================================= > > void interruptRedirect(void){ > > // CAN 0 Recieve Interrupt > /////////////////////////// > *((unsigned char *)0x3F8E) = 0x06; > *((void (**)(void))0x3F8F) = CAN_Recieve; > > // CAN 0 Transmit Interrupt > ////////////////////////// > *((unsigned char *)0x3F8B) = 0x06; > *((void (**)(void))0x3F8C) = CAN_Transmit; > > // CAN 0 Error Interrupt > ////////////////////////// > *((unsigned char *)0x3F91) = 0x06; > *((void (**)(void))0x3F92) = CAN_Error; > } > > ================================================= > The ISR for CAN receive looks like this: > ================================================= > > #pragma interrupt_handler CAN_Recieve > void CAN_Recieve(void){ > > int i=0, x=0; > > // Find Empty MessageBuffer > /////////////////////////// > while(CANMess[i].messact != 0) i++; > if (i > MAXCANMESSAGES){ > if(DEBUGPRINT) printf("CAN Trancieve Error: No Free Buffer to store > Message !"); > CAN0RFLG |=1; // clear rec flag > return; > } > > // Set status of Message to Recieve Message > /////////////////////////////////////////// > CANMess[i].messact = 1; > > // Check for Number of Bytes in CAN Message > /////////////////////////////////////////// > CANMess[i].length = CAN0RXDLR & 0x0F; > > // Copy ID to Messagebuffer > /////////////////////////// > CANMess[i].id0 = CAN0RXIDR0; > CANMess[i].id1 = CAN0RXIDR1; > CANMess[i].id2 = CAN0RXIDR2; > CANMess[i].id3 = CAN0RXIDR3; > > // Copy Data to Messagebuffer > ///////////////////////////// > for (x=0;x<CANMess[i].length;x++) > CANMess[i].data[x] = *(CAN0RXDATA+x); > > CAN0RFLG |=1; // clear rec flag > } > > ==================================================== > And this is the main function: > ==================================================== > void main(void){ > > int i=0, j=0; > unsigned char ch; > unsigned char temp[5]; > > for(i=0;i<MAXCANMESSAGES;i++) CANMess[i].messact=0; > > interruptRedirect(); // Redirect Interrupts > CANInit(); // Init MSCAN > > asm("cli"); // Enable global Interrupts > > temp[0] = 1; > temp[1] = 2; > temp[2] = 3; > temp[3] = 4; > temp[4] = 5; > > SendCANMessage(5,temp); > while(1){ > // Checking Messagebuffer for Entrys > //////////////////////////////////// > for(i=0;i<MAXCANMESSAGES;i++){ > if(CANMess[i].messact == 1){ > CANMess[i].messact = 0; > > SendCANMessage(5,temp); > } > } > } > } > > ============================================== > The SendCANMessage looks like this: > ============================================== > void SendCANMessage(unsigned char NumBytes, unsigned char *BufPntr){ > > unsigned char NACAN,C; > while(!CAN0TFLG); // wait for available buffer > NACAN0TFLG; // get the next available CAN buffer > CAN0TBSEL=NACAN; > > CAN0TXIDR0 = 0x2D; > CAN0TXIDR1 = 0xF0; > CAN0TXIDR2 = 0x00; > CAN0TXIDR3 = 0x00; > > if (NumBytes>8) NumBytes=8; > for (C=0;C<NumBytes;C++) > *(CAN0TXDATA+C)=*BufPntr++; // store the data > > CAN0TXDLR=NumBytes; // set number of bytes to send > NACAN0TBSEL; > CAN0TFLG =NACAN; // transmit > } > > =========================================================== > > I have tested the the program an 2 different MC9S12 but the result is > the same - the tranmsitted message is not equal to the received. Have > i missed something? > > Thanks in advance. > Greets Daniel > > PS: I must apologize for my bad english. > > > Yahoo! Groups Links > > |