I am trying to read messages from CAN bus with LPC11C14 uC. I get interrupt when message is transmitted by other CAN device, but the value of LPC_CAN->INT == (1<<15), so I only get interrupt status but dont get message number. I am not sure whether I need to setup something to actually receive message.
definitions
#define IS_BIT_ENABLED(a,b) (((a) & (1U<<(b)))==(1U<<(b))?1:0) #define INT_STATUS 15 #define INT_MSG_NUM_MASK 0x3F #define NO_ERROR_MASK (_BV(0)|_BV(1)|_BV(2)) #define STAT_RX0K 4 #define STAT_EWARN 6 #define STAT_BOFF 7
Here is my interrupt routine
uint32_t stat, canint, msg_no; canint = LPC_CAN->INT; if ( IS_BIT_ENABLED(canint, INT_STATUS) ) { stat = LPC_CAN->STAT; if (IS_BIT_ENABLED(stat, STAT_EWARN)) return; if (IS_BIT_ENABLED(stat, STAT_BOFF)) return; if (IS_BIT_ENABLED(stat, STAT_RX0K)) { if ( (stat & NO_ERROR_MASK) != 0) return; while (IS_BIT_ENABLED(canint, INT_STATUS)); msg_no = canint & INT_MSG_NUM_MASK; if ( (msg_no >= 0x01) && (msg_no <= 0x20) ) { LPC_CAN->STAT &= ~STAT_RX0K; processMessage (msg_no); } } }
and initialisation
LPC_SYSCON->SYSAHBCLKCTRL |= (1<<17); LPC_SYSCON->PRESETCTRL |= (1<<3); LPC_CAN->CNTL |= (1<<0); //init LPC_CAN->CLKDIV = 0x5; //clock divider by 6 48Mhz/6 = 8Mhz LPC_CAN->CNTL |= (1<<6); //configuration change enabled LPC_CAN->BT = 0x2301; //500kBit/s LPC_CAN->BRPE = 0x0; LPC_CAN->CNTL &= ~(1<<6); //configuration change disabled LPC_CAN->CNTL &= ~(1<<0); //init done while (LPC_CAN->CNTL & (1<<0)); NVIC_EnableIRQ (CAN_IRQn); LPC_CAN->CNTL |= (1<<1) | (1<<2) | (1<<3) | (1<<5); //Interrupt enable, Status change int, Error int, disable retransmit
Do I need to "clean" the filter to receive actual msg from the buffer ? I didnt setup filter at all so I would expect that I should see all of the messages on the bus.
Ok, I got interrupt and message num in message buffer, but I cant extract the data. I have set up the message filter to accept all messages:
LPC_CAN->IF2_CMDMSK = WR|MASK|ARB|CTRL|DATAA|DATAB; LPC_CAN->IF2_MCTRL = 0; LPC_CAN->IF2_MSK1 = 0; LPC_CAN->IF2_MSK2 = 0; LPC_CAN->IF2_ARB1 = 0; LPC_CAN->IF2_ARB2 = (1UL << 15); LPC_CAN->IF2_MCTRL = UMSK|RXIE|EOB|DLC; LPC_CAN->IF2_DA1 = 0; LPC_CAN->IF2_DA2 = 0; LPC_CAN->IF2_DB1 = 0; LPC_CAN->IF2_DB2 = 0; LPC_CAN->IF2_CMDREQ = 5; while (LPC_CAN->IF2_CMDREQ & CMDREQ_BUSY);
And now the processMessage function is called, but all the data from buffer is 0.
void canBus::processMessage (uint8_t a_msgNo) { uint32_t msgId; can_msg msg; while (LPC_CAN->IF2_CMDREQ & CMDREQ_BUSY); LPC_CAN->IF2_CMDMSK = WR_RD|MASK|ARB|CTRL|INTPND|TREQ|DATAA|DATAB; LPC_CAN->IF2_CMDREQ = a_msgNo; while (LPC_CAN->IF2_CMDREQ & CMDREQ_BUSY); if (IS_BIT_ENABLED(LPC_CAN->IF2_ARB2, MSG_EXTENDED)) { msgId = (LPC_CAN->IF2_ARB1 | ((LPC_CAN->IF2_ARB2&0x5fff)<<16)); } else { msgId = (LPC_CAN->IF2_ARB2 & ID_STD_MASK) >> 2; } msg.ident = msgId; msg.len = MIN((LPC_CAN->IF2_MCTRL & 0x0f), 8); msg.num = a_msgNo; }
and also msg.len is equal to 8, even though my actual message have only 2 bytes. Any idea ?