AnsweredAssumed Answered

USB CAN bus analyzer for vehicle

Question asked by kevin kh on Sep 19, 2017

 Dear community members,

I am working on (Controller Area Network) analyzer for monitoring CAN bus on vehicles (not for diagnostics, just to see simple message frames with identifiers, etc.) with stm32f103rb MCU  This is my code but I cant receive any frame in my Terminal usart, does anyone have any experience? I really appreciate it because of about 7 days stuck in and Im using (STM-P103 BOARDS) with KEIL IDE.

Thank you very much.

MAIN:

////--------------------------------------------------------------------------------------------------------------------///

#include "stm32f10x.h"
#include "USART.h"
#include "CAN.h"
#include <stdio.h>

unsigned int val_Tx = 0, val_Rx = 0; /* Globals used for display */

void Delay (uint32_t Time);
/*----------------------------------------------------------------------------
fputc
*----------------------------------------------------------------------------*/
int fputc(int ch, FILE *f) {
return (USART2_SendChar(ch));
}


/*----------------------------------------------------------------------------
initialize CAN interface
*----------------------------------------------------------------------------*/
void can_Init (void) {

CAN_setup (); /* setup CAN Controller */
CAN_wrFilter (33, STANDARD_FORMAT); /* Enable reception of msgs */

/* ! COMMENT LINE BELOW TO ENABLE DEVICE TO PARTICIPATE IN CAN NETWORK ! */
CAN_testmode(CAN_BTR_SILM | CAN_BTR_LBKM); // Loopback, Silent Mode (self-test)

CAN_start (); /* start CAN Controller */

CAN_waitReady (); /* wait til tx mbx is empty */
}

//*****************************************************************************
int main(void)
{
int i;
char str[50];
SystemInit();
USART2_Init();
USART2_SendString("\n\r-----------------------");
USART2_SendString("\n\r");
USART2_SendString("\n\r");
USART2_SendString("\");
USART2_SendString("\n\rTest CAN");


can_Init (); /* initialize CAN interface */

CAN_TxMsg.id = 33; /* initialize msg to send */
for (i = 0; i < 8; i++) CAN_TxMsg.data[i] =0;
CAN_TxMsg.len = 1;
CAN_TxMsg.format = STANDARD_FORMAT;
CAN_TxMsg.type = DATA_FRAME;

while (1) {

if (CAN_TxRdy) { /* tx msg on CAN Ctrl */
CAN_TxRdy = 0;

CAN_TxMsg.data[0] = val_Tx++; /* data[0] = ADC value */
CAN_wrMsg (&CAN_TxMsg); /* transmit message */
USART2_SendString("\r\nTransfer ");
sprintf(str,"%i ", CAN_TxMsg.data[0]);
USART2_SendString(str);
}

Delay (100); /* delay for 10ms */
// 0 Receive 11:49:09:845 Data frame Standard frame 00000130 5 05 f0 fc ff ff
// format; // 0 - STANDARD, 1- EXTENDED IDENTIFIER
//type; // 0 - DATA FRAME, 1 - REMOTE FRAME
if (CAN_RxRdy) { /* rx msg on CAN Ctrl */
USART2_SendString("\r\nReceive ");
if(CAN_RxMsg.type == 0)
{
USART2_SendString("DATA FRAME ");
}
else
{
USART2_SendString("REMOTE FRAME ");
}
if(CAN_RxMsg.format == 0)
{
USART2_SendString("STANDARD ");
}
else
{
USART2_SendString("EXTENDED IDENTIFIER ");
}
sprintf(str,"%x ", CAN_RxMsg.id);
USART2_SendString(str);

sprintf(str,"%x ", CAN_RxMsg.len);
USART2_SendString(str);
for (i=0;i<CAN_RxMsg.len ;i++)
{
sprintf(str,"%x ", CAN_RxMsg.data[i]);
USART2_SendString(str);
}

CAN_RxRdy = 0;
}
}
}

///----------------------------------------------------------------------------------------------------------//

CAN.C 

#include "STM32F10x.h"
#include "CAN.h"

/* CAN identifier type */
#define CAN_ID_STD ((uint32_t)0x00000000) /* Standard Id */
#define CAN_ID_EXT ((uint32_t)0x00000004) /* Extended Id */

/* CAN remote transmission request */
#define CAN_RTR_DATA ((uint32_t)0x00000000) /* Data frame */
#define CAN_RTR_REMOTE ((uint32_t)0x00000002) /* Remote frame */

CAN_msg CAN_TxMsg; /* CAN messge for sending */
CAN_msg CAN_RxMsg; /* CAN message for receiving */

unsigned int CAN_TxRdy = 0; /* CAN HW ready to transmit message */
unsigned int CAN_RxRdy = 0; /* CAN HW received a message */


/*----------------------------------------------------------------------------
setup CAN interface
*----------------------------------------------------------------------------*/
void CAN_setup (void) {
unsigned int brp;

RCC->APB1ENR |= ( 1UL << 25); /* enable clock for CAN */

/* Note: MCBSTM32 uses PB8 and PB9 for CAN */
RCC->APB2ENR |= ( 1UL << 0); /* enable clock for AF */
AFIO->MAPR &= 0xFFFF9FFF; /* reset CAN remap */
AFIO->MAPR |= 0x00004000; /* set CAN remap, use PB8, PB9 */

RCC->APB2ENR |= ( 1UL << 3); /* enable clock for GPIO B */
GPIOB->CRH &= ~(0x0F << 0);
GPIOB->CRH |= (0x08 << 0); /* CAN RX PB.8 input push pull */

GPIOB->CRH &= ~(0x0F << 4);
GPIOB->CRH |= (0x0B << 4); /* CAN TX PB.9 alt.output push pull */

NVIC_EnableIRQ(USB_HP_CAN1_TX_IRQn); /* enable CAN TX interrupt */
NVIC_EnableIRQ(USB_LP_CAN1_RX0_IRQn); /* enable CAN RX interrupt */

CAN1->MCR = (CAN_MCR_INRQ | /* initialisation request */
CAN_MCR_NART ); /* no automatic retransmission */
/* only FIFO 0, tx mailbox 0 used! */
CAN1->IER = (CAN_IER_FMPIE0 | /* enable FIFO 0 msg pending IRQ */
CAN_IER_TMEIE ); /* enable Transmit mbx empty IRQ */

/* Note: this calculations fit for PCLK1 = 36MHz */
brp = (36000000UL / 18) / 500000; /* baudrate is set to 500k bit/s */

/* set BTR register so that sample point is at about 72% bit time from bit start */
/* TSEG1 = 12, TSEG2 = 5, SJW = 4 => 1 CAN bit = 18 TQ, sample at 72% */
CAN1->BTR &= ~((( 0x03) << 24) | (( 0x07) << 20) | (( 0x0F) << 16) | ( 0x1FF));
CAN1->BTR |= ((((4-1) & 0x03) << 24) | (((5-1) & 0x07) << 20) | (((12-1) & 0x0F) << 16) | ((brp-1) & 0x1FF));
}


/*----------------------------------------------------------------------------
leave initialisation mode
*----------------------------------------------------------------------------*/
void CAN_start (void) {

CAN1->MCR &= ~CAN_MCR_INRQ; /* normal operating mode, reset INRQ*/
while (CAN1->MSR & CAN_MCR_INRQ);
}


/*----------------------------------------------------------------------------
set the testmode
*----------------------------------------------------------------------------*/
void CAN_testmode (unsigned int testmode) {

CAN1->BTR &= ~(CAN_BTR_SILM | CAN_BTR_LBKM); /* set testmode */
CAN1->BTR |= (testmode & (CAN_BTR_SILM | CAN_BTR_LBKM));
}

/*----------------------------------------------------------------------------
check if transmit mailbox is empty
*----------------------------------------------------------------------------*/
void CAN_waitReady (void) {

while ((CAN1->TSR & CAN_TSR_TME0) == 0); /* Transmit mailbox 0 is empty */
CAN_TxRdy = 1;
}


/*----------------------------------------------------------------------------
wite a message to CAN peripheral and transmit it
*----------------------------------------------------------------------------*/
void CAN_wrMsg (CAN_msg *msg) {

CAN1->sTxMailBox[0].TIR = 0; /* Reset TIR register */
/* Setup identifier information */
if (msg->format == STANDARD_FORMAT) { /* Standard ID */
CAN1->sTxMailBox[0].TIR |= (uint32_t)(msg->id << 21) | CAN_ID_STD;
} else { /* Extended ID */
CAN1->sTxMailBox[0].TIR |= (uint32_t)(msg->id << 3) | CAN_ID_EXT;
}
/* Setup type information */
if (msg->type == DATA_FRAME) { /* DATA FRAME */
CAN1->sTxMailBox[0].TIR |= CAN_RTR_DATA;
} else { /* REMOTE FRAME */
CAN1->sTxMailBox[0].TIR |= CAN_RTR_REMOTE;
}
/* Setup data bytes */
CAN1->sTxMailBox[0].TDLR = (((uint32_t)msg->data[3] << 24) |
((uint32_t)msg->data[2] << 16) |
((uint32_t)msg->data[1] << 8) |
((uint32_t)msg->data[0]) );
CAN1->sTxMailBox[0].TDHR = (((uint32_t)msg->data[7] << 24) |
((uint32_t)msg->data[6] << 16) |
((uint32_t)msg->data[5] << 8) |
((uint32_t)msg->data[4]) );
/* Setup length */
CAN1->sTxMailBox[0].TDTR &= ~CAN_TDT0R_DLC;
CAN1->sTxMailBox[0].TDTR |= (msg->len & CAN_TDT0R_DLC);

CAN1->IER |= CAN_IER_TMEIE; /* enable TME interrupt */
CAN1->sTxMailBox[0].TIR |= CAN_TI0R_TXRQ; /* transmit message */
}


/*----------------------------------------------------------------------------
read a message from CAN peripheral and release it
*----------------------------------------------------------------------------*/
void CAN_rdMsg (CAN_msg *msg) {
/* Read identifier information */
if ((CAN1->sFIFOMailBox[0].RIR & CAN_ID_EXT) == 0) {
msg->format = STANDARD_FORMAT;
msg->id = 0x000007FF & (CAN1->sFIFOMailBox[0].RIR >> 21);
} else {
msg->format = EXTENDED_FORMAT;
msg->id = 0x1FFFFFFF & (CAN1->sFIFOMailBox[0].RIR >> 3);
}
/* Read type information */
if ((CAN1->sFIFOMailBox[0].RIR & CAN_RTR_REMOTE) == 0) {
msg->type = DATA_FRAME;
} else {
msg->type = REMOTE_FRAME;
}
/* Read number of rec. bytes */
msg->len = (CAN1->sFIFOMailBox[0].RDTR ) & 0x0F;
/* Read data bytes */
msg->data[0] = (CAN1->sFIFOMailBox[0].RDLR ) & 0xFF;
msg->data[1] = (CAN1->sFIFOMailBox[0].RDLR >> 8) & 0xFF;
msg->data[2] = (CAN1->sFIFOMailBox[0].RDLR >> 16) & 0xFF;
msg->data[3] = (CAN1->sFIFOMailBox[0].RDLR >> 24) & 0xFF;

msg->data[4] = (CAN1->sFIFOMailBox[0].RDHR ) & 0xFF;
msg->data[5] = (CAN1->sFIFOMailBox[0].RDHR >> 8) & 0xFF;
msg->data[6] = (CAN1->sFIFOMailBox[0].RDHR >> 16) & 0xFF;
msg->data[7] = (CAN1->sFIFOMailBox[0].RDHR >> 24) & 0xFF;

CAN1->RF0R |= CAN_RF0R_RFOM0; /* Release FIFO 0 output mailbox */
}


/*----------------------------------------------------------------------------
CAN write message filter
*----------------------------------------------------------------------------*/
void CAN_wrFilter (unsigned int id, unsigned char format) {
static unsigned short CAN_filterIdx = 0;
unsigned int CAN_msgId = 0;

if (CAN_filterIdx > 13) { /* check if Filter Memory is full*/
return;
}
/* Setup identifier information */
if (format == STANDARD_FORMAT) { /* Standard ID */
CAN_msgId |= (uint32_t)(id << 21) | CAN_ID_STD;
} else { /* Extended ID */
CAN_msgId |= (uint32_t)(id << 3) | CAN_ID_EXT;
}

CAN1->FMR |= CAN_FMR_FINIT; /* set initMode for filter banks */
CAN1->FA1R &= ~(1UL << CAN_filterIdx); /* deactivate filter */

/* initialize filter */
CAN1->FS1R |= (unsigned int)(1 << CAN_filterIdx); /* set 32-bit scale configuration */
CAN1->FM1R |= (unsigned int)(1 << CAN_filterIdx); /* set 2 32-bit identifier list mode */

CAN1->sFilterRegister[CAN_filterIdx].FR1 = CAN_msgId; /* 32-bit identifier */
CAN1->sFilterRegister[CAN_filterIdx].FR2 = CAN_msgId; /* 32-bit identifier */

CAN1->FFA1R &= ~(unsigned int)(1 << CAN_filterIdx); /* assign filter to FIFO 0 */
CAN1->FA1R |= (unsigned int)(1 << CAN_filterIdx); /* activate filter */

CAN1->FMR &= ~CAN_FMR_FINIT; /* reset initMode for filterBanks*/

CAN_filterIdx += 1; /* increase filter index */
}


/*----------------------------------------------------------------------------
CAN transmit interrupt handler
*----------------------------------------------------------------------------*/
void USB_HP_CAN1_TX_IRQHandler (void) {

if (CAN1->TSR & CAN_TSR_RQCP0) { /* request completed mbx 0 */
CAN1->TSR |= CAN_TSR_RQCP0; /* reset request complete mbx 0 */
CAN1->IER &= ~CAN_IER_TMEIE; /* disable TME interrupt */

CAN_TxRdy = 1;
}
}


/*----------------------------------------------------------------------------
CAN receive interrupt handler
*----------------------------------------------------------------------------*/
void USB_LP_CAN1_RX0_IRQHandler (void) {

if (CAN1->RF0R & CAN_RF0R_FMP0) { /* message pending ? */
CAN_rdMsg (&CAN_RxMsg); /* read the message */

CAN_RxRdy = 1; /* set receive flag */
}
}

Outcomes