cancel
Showing results for 
Search instead for 
Did you mean: 

Cannot enable CAN bus

ee52bs
Associate II
Posted on July 04, 2012 at 18:16

#include ''ll_can.h'' 
#include ''rcc.h'' 
#include ''gpio.h'' 
#include ''nvic.h'' 
#include ''usb.h'' 
int can_init(int mode) 
{ 
rcc_clk_enable(RCC_GPIOB); //enable GPIO port B 
rcc_clk_enable(RCC_AFIO); //enable AFIO clock 
afio_remap(AFIO_REMAP_CAN_1); //remap to PB8 and PB9 
gpio_set_mode(GPIOB, 8, GPIO_INPUT_FLOATING); //set pin modes 
gpio_set_mode(GPIOB, 9, GPIO_AF_OUTPUT_PP); 
(RCC_BASE->APB1ENR) |= 1 << 
RCC_APB1ENR_CANEN
; //enable CAN clock 
(RCC_BASE->APB1RSTR) |= 1 << 
RCC_APB1ENR_CANRST
; //reset CAN peripheral 
return RCC_BASE->APB1ENR; 
//set up of baud rates, mode, filters etc. 
}

Hi, I am trying to setup the CAN bus in loopback mode on an Olimexino STM32 board (using an STM32F103RBT6), but when I print out the binary value of the APB1 enable register I get 100000000000000000000111 - i.e. the USB clock is enabled, and TIM2, 3 and 4 are enabled.I'd be grateful if anyone has any ideas to solve this? #can-bus #olimexino
14 REPLIES 14
Posted on July 04, 2012 at 19:27

I can't comment on the efficacy of you libraries, but you'll want to release the reset for the peripheral to work.

(RCC_BASE->APB1RSTR) |= 1 << 
RCC_APB1ENR_CANRST
; // assert reset CAN peripheral 
(RCC_BASE->APB1RSTR) &= ~(1 << 
RCC_APB1ENR_CANRST
); // release reset CAN peripheral 

You'll also need to set CAN_CTRL appropriately if you wish to transmit on the bus.
Tips, buy me a coffee, or three.. PayPal Venmo Up vote any posts that you find helpful, it shows what's working..
ee52bs
Associate II
Posted on July 04, 2012 at 19:40

Thanks for the tip!

I figured out the problems; firstly you can only write to that register in word mode by sending it a uint32 - so just setting one bit at a time doesn't do anything. Secondly you can't have the USB and CAN active at the same time, so you have to turn off USB, do the CAN stuff, then switch USB back on.

ee52bs
Associate II
Posted on July 04, 2012 at 19:56

yup, that's the ''set up of baud rate..'' comment at the end 🙂

After the clocks have been enabled I enable the NVIC interrupts, then set FIFO0 and 1 empty interrupt bits, TX MB empty interrupt bit, wake up interrupt and sleep interrupt bits in IER.

Then I set the MCR sleep bit to 0, and the INRQ bit to 1, set the bits for baud rate prescalar, time divisions and loopback mode in BTR, then clear the INRQ bit to go back to normal mode. Does that sound OK?

ee52bs
Associate II
Posted on July 05, 2012 at 15:56

So now I can actually initialise the bus, but I can't get out of init mode! When I clear INRQ in CAN_MCR the INAK bit in CAN_MSR does not clear. From looking around on the internet this appears to be the result of the hardware not detecting 11 recessive bits on the RX line. I think this can be caused by (a) thepin not being set up properly or (b) the baud rate not being set up properly so it doesn't count the right number of bits. I am pretty sure I have the pins set correctlysincethe readout of CAN_MSR shows bit 11 as 1, meaning that RX is high (recessive), and it goes to 0 if I change the pin modes.

Here is the code I use to set the BTR_SJW, BTR_TS1, BTR_TS2 and BTR_BRP bits - I am trying to get a baud rate of 250kHz, I used the equations on pg 645 of the manual to calculate the values:

//set resynch jump width to 1 
(CAN_CTRL->BTR) &= ~(1<<
BTR_SJW
[1]); 
(CAN_CTRL->BTR) |= 1<<
BTR_SJW
[0]; 
//set TS1 to 8 
(CAN_CTRL->BTR) |= 1<<
BTR_TS1
[3]; 
(CAN_CTRL->BTR) &= ~(1<<
BTR_TS1
[2]); 
(CAN_CTRL->BTR) &= ~(1<<
BTR_TS1
[1]); 
(CAN_CTRL->BTR) &= ~(1<<
BTR_TS1
[0]); 
//set TS2 to 4 
(CAN_CTRL->BTR) |= 1<<
BTR_TS2
[2]; 
(CAN_CTRL->BTR) &= ~(1<<
BTR_TS2
[2]); 
(CAN_CTRL->BTR) &= ~(1<<
BTR_TS2
[0]); 
//set BRP to 8 
(CAN_CTRL->BTR) &= ~(1<<
BTR_BRP
[9]); 
(CAN_CTRL->BTR) &= ~(1<<
BTR_BRP
[8]); 
(CAN_CTRL->BTR) &= ~(1<<
BTR_BRP
[7]); 
(CAN_CTRL->BTR) &= ~(1<<
BTR_BRP
[6]); 
(CAN_CTRL->BTR) &= ~(1<<
BTR_BRP
[5]); 
(CAN_CTRL->BTR) &= ~(1<<
BTR_BRP
[4]); 
(CAN_CTRL->BTR) |= 1<<
BTR_BRP
[3]; 
(CAN_CTRL->BTR) &= ~(1<<
BTR_BRP
[2]); 
(CAN_CTRL->BTR) &= ~(1<<
BTR_BRP
[1]); 
(CAN_CTRL->BTR) &= ~(1<<BTR_BRP[0]);

Thanks
Posted on July 05, 2012 at 16:15

(CAN_CTRL->BTR) |= 1<<
BTR_TS2
[2];
(CAN_CTRL->BTR) &= ~(1<<
BTR_TS2
[2]); // << SURELY BTR_TS2[1]
(CAN_CTRL->BTR) &= ~(1<<BTR_TS2[0]);

I'm not excited about register bit level minutia, is there a strong reason why you can't use the standard ST firmware libraries? And the examples contained there in.
Tips, buy me a coffee, or three.. PayPal Venmo Up vote any posts that you find helpful, it shows what's working..
ee52bs
Associate II
Posted on July 05, 2012 at 16:33

I'm using the Maple IDE which has its own versions of many of the libraries, but they haven't got a CAN library yet and a lot of the CAN stuff is unfinished (e.g. functions which are prototyped but with no actual bodies etc.) I did try including some libraries from the STM peripheral libraries package, and spent a week just trying to sort out multiple definition errors and scope errors. In the end it seemed easier just to copy the low level CAN stuff I needed to a new set of libraries and edit it as necessary.

hello
Associate II
Posted on July 05, 2012 at 21:44

The original post was too long to process during our migration. Please click on the provided URL to read the original post. https://st--c.eu10.content.force.com/sfc/dist/version/download/?oid=00Db0000000YtG6&ids=0680X000006I6bN&d=%2Fa%2F0X0000000brZ%2FBMnuVWzj6WHk684n.IWXtZr5Nd9sn1a3UP1pLEXQsas&asPdf=false
ee52bs
Associate II
Posted on July 06, 2012 at 11:59

Thanks, I'll check it against what I have already. I thought of another possible reason the hardware is not changing the INAK bit - it might be because there are interrupt conflicts between the USB and CAN bus. Does this sound likely?

hello
Associate II
Posted on July 06, 2012 at 14:46

i use ETH and CANinterruptbut it work fine for me still.

void NVIC_Configuration(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
/* Set the Vector Table base location at 0x08000000 */
NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x0);
/* 2 bit for pre-emption priority, 2 bits for subpriority */
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); 
/* Enable the Ethernet global Interrupt */
NVIC_InitStructure.NVIC_IRQChannel = ETH_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
/* Int for CAN */
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);
NVIC_InitStructure.NVIC_IRQChannel = CAN1_RX0_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
/*
NVIC_InitStructure.NVIC_IRQChannel = CAN1_RX0_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
*/ 
/* Enable the TIM2 gloabal Interrupt */
NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}