2012-07-04 09:16 AM
#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
2012-07-04 10:27 AM
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.
2012-07-04 10:40 AM
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.2012-07-04 10:56 AM
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?2012-07-05 06:56 AM
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
2012-07-05 07:15 AM
(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.
2012-07-05 07:33 AM
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.
2012-07-05 12:44 PM
2012-07-06 02:59 AM
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?
2012-07-06 05:46 AM
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);
}