2019-04-29 10:54 AM
Hello ST community!
For some time now I've been trying to make the CANbus work and in the end I did but unfortunately only to some extend. Using 2 CAN SN65HVD230 modules, STM32F746IGT6 core, waveshare Open7XXI-C main board I managed to run slightly modified example file from https://www.waveshare.com/wiki/File:Open746I-C-Demo-HAL.7z (11.CAN). Until now everything's good, modules communicate with each other. The problem occurs when I try to transmit or receive some CAN data using PCANview with PEAK tool.
Now considering my target baudrate which is 500kb/s I've changed few can init settings based on http://www.bittiming.can-wiki.info website:
Clock Rate: 216 Mhz*,
Sample point: 87.5%,
SJW: 1,
kbit/s: 500,
* the 216 Mhz comes from HAL_PWREx_ActivateOverDrive(), which sets the clock to 216 Mhz.
resulting in:
Prescaler: 27,
Segment 1 time quanta: 13,
Segment 2 time quanta: 2.
Considering the above, this is how the code looks in can.c (CAN2 init is identical)
void MX_CAN1_Init(void){
hcan1.Instance = CAN1;
hcan1.Init.Prescaler = 27;
hcan1.Init.Mode = CAN_MODE_NORMAL;
hcan1.Init.SJW = CAN_SJW_1TQ;
hcan1.Init.BS1 = CAN_BS1_13TQ;
hcan1.Init.BS2 = CAN_BS2_2TQ;
hcan1.Init.TTCM = DISABLE;
hcan1.Init.ABOM = DISABLE;
hcan1.Init.AWUM = DISABLE;
hcan1.Init.NART = DISABLE;
hcan1.Init.RFLM = DISABLE;
hcan1.Init.TXFP = DISABLE;
HAL_CAN_Init(&hcan1);
}
The CAN1 filter is configured in the following code (no filter):
sFilterConfig.FilterNumber = 0;
sFilterConfig.FilterMode = CAN_FILTERMODE_IDMASK;
sFilterConfig.FilterScale = CAN_FILTERSCALE_32BIT;
sFilterConfig.FilterIdHigh = 0x0000;
sFilterConfig.FilterIdLow = 0x0000;
sFilterConfig.FilterMaskIdHigh = 0x0000;
sFilterConfig.FilterMaskIdLow = 0x0000;
sFilterConfig.FilterFIFOAssignment = 0;
sFilterConfig.FilterActivation = ENABLE;
sFilterConfig.BankNumber = 14;
HAL_CAN_ConfigFilter(&hcan1, &sFilterConfig);
When configuration is done as above and PCANview set to 500kbit/s the status instantly goes to BUSHEAVY and when I try to send some message I get BUS-OFF but the modules still communicate with each other, just not with the PEAK.
I'm 99% sure that I checked if the peripherals I use may have some influence and it's very unlikely. Both transceivers work. I have only two terminals, one per used transceiver.
I was already trying different time quanta settings, prescaler, PEAK baudrates and more with no result. Perhaps I'm just forgetting about something and the solution is very easy. Anyway, I'm attaching main.c code, and I know it's quite messy, but I'm in an early stage of development and still learning.
To be honest I recently moved from Arduino (mostly because of multiple peripherals malfunctions or conflicts resulting in attaching more arduinos to the same project) to STM and I'm in the middle of trying to move the code to the new platform, too.
Any help would be greatly appreciated, thank you!
2019-05-09 05:28 AM
Did you configure the pin-mux? Did you enable the clocks to the CAN peripherals?
2019-05-11 01:46 AM
Hi there,
Thank you for taking your time to help me.
You were right and indeed the clocks weren't enabled. Below you can find the HAL_CAN_MspInit function. Now regarding the GPIO_SPEED_HIGH which is defined as GPIO_SPEED_FREQ_VERY_HIGH ((uint32_t)0x00000003) (high speed) I'm wondering which speed exactly is being set.
After calling this function I still can't see any messages in PCAN view.
UPDATE#1:
After some digging I found out that the speed should be set to something in the range of 50-200Mhz, it's the fastest after all. I can't find the exact value though.
UPDATE#2:
When I connect another CAN node controlled by Arduino with a CAN shield (MCP25xx chips, https://botland.com.pl/en/arduino-shield-communication/11568-can-bus-shield-v20-shield-for-arduino.html) it frezees the stm HAL can.
UPDATE#3:
After enabling the software BUS-OFF management (hcan1.Init.ABOM = ENABLE) it no longer freezes and very, VERY rarely I can see that PEAK picks up some new messages. At least that's something. Nevertheless the messages IDs are wrong and in some places the data as well.
I'm not entirely sure but this may be connected to how the mailboxes are maintained by the software. Before even connecting the Arduino CANbus shield I had troubles with sending and/or reading more than 3 different IDs.
UPDATE#4:
I was wrong before and this is getting even weirder. I still can't see messages from stm32 HAL CAN. But in some way the CAN node(s) from stm32 are affecting what I send from Arduino CANbus shield. This results in receiving some new messages with slightly changed ID carrying the same data as messages sent originally by Arduino. From what I can see they show up at completely random time. It's hard to explain really.
For example if 0x65 is the original message ID that is being sent from Arduino PCANview also shows 0x525 and 0x565 IDs with the same content. Meanwhile the only messages I send from HAL CAN are with IDs: 0x460, 0x470, 0x480 which, of course, don't show up (please refer to the attached image, messages with high counts are original).
I'm almost certain that is has something to do with bit timing..
static int CAN1_CLK_ENABLED=0;
void HAL_CAN_MspInit(CAN_HandleTypeDef* hcan)
{
GPIO_InitTypeDef GPIO_InitStruct;
if(hcan->Instance==CAN1)
{
/* USER CODE BEGIN CAN1_MspInit 0 */
/* USER CODE END CAN1_MspInit 0 */
/* Peripheral clock enable */
CAN1_CLK_ENABLED++;
if(CAN1_CLK_ENABLED==1){
__CAN1_CLK_ENABLE();
}
/**CAN1 GPIO Configuration
PA11 ------> CAN1_RX
PA12 ------> CAN1_TX
*/
GPIO_InitStruct.Pin = GPIO_PIN_11|GPIO_PIN_12;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF9_CAN1;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
/* USER CODE BEGIN CAN1_MspInit 1 */
/* USER CODE END CAN1_MspInit 1 */
}
else if(hcan->Instance==CAN2)
{
/* USER CODE BEGIN CAN2_MspInit 0 */
/* USER CODE END CAN2_MspInit 0 */
/* Peripheral clock enable */
__CAN2_CLK_ENABLE();
CAN1_CLK_ENABLED++;
if(CAN1_CLK_ENABLED==1){
__CAN1_CLK_ENABLE();
}
/**CAN2 GPIO Configuration
PB12 ------> CAN2_RX
PB13 ------> CAN2_TX
*/
GPIO_InitStruct.Pin = GPIO_PIN_12|GPIO_PIN_13;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF9_CAN2;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
/* USER CODE BEGIN CAN2_MspInit 1 */
/* USER CODE END CAN2_MspInit 1 */
}
}
2019-05-13 05:33 AM
STARK,
I've found your problem. The issue is here:
hcan1.Init.Prescaler = 27;
The source of the CAN clock is PCLK1, not the system clock. So, it is 216 MHz, divided by RCC_ClkInitStruct.APB1CLKDivider (typically 4, but you should check your setup). Thus, your CAN clock is currently 125 kbps, not 500.
Regards,
Bill
2019-05-13 06:43 AM
Hello there Bill,
I was considering the PCLK1, I've changed the Prescaler before thinking about 54 MHz setting. But it was before making sure that clocks were enabled.
I'll look into it ASAP and share the results. Thanks for all the help!
UPDATE #1:
Looking at below code the CAN clock was set to 54 MHz:
HAL_PWREx_ActivateOverDrive();
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;
HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_6);
****
#define RCC_HCLK_DIV4 RCC_CFGR_PPRE1_DIV4
#define RCC_CFGR_PPRE1_DIV4 ((uint32_t)0x00001400) /*!< HCLK divided by 4 */
I've just changed the MX_CAN1_Init accordingly:
void MX_CAN1_Init(void)
{
hcan1.Instance = CAN1;
hcan1.Init.Prescaler = 6;
hcan1.Init.Mode = CAN_MODE_NORMAL;
hcan1.Init.SJW = CAN_SJW_1TQ;
hcan1.Init.BS1 = CAN_BS1_15TQ;
hcan1.Init.BS2 = CAN_BS2_2TQ;
hcan1.Init.TTCM = DISABLE;
hcan1.Init.ABOM = ENABLE;
hcan1.Init.AWUM = DISABLE;
hcan1.Init.NART = DISABLE;
hcan1.Init.RFLM = DISABLE;
hcan1.Init.TXFP = DISABLE;
HAL_CAN_Init(&hcan1);
}
and the previous issue still remains.
2019-06-14 03:56 AM
Hello again,
Lately I was busy so couldn't really come back. The issue still remains as mentioned above but I think I'm one step closer to the solution.
Here's what I have now:
First, the code slightly changed:
I've made a function for sending CAN messages for better transparency, same for receiving.
void canF1(int frameID, char frameType, char frameDLC, unsigned char frameMessage[]){
hcan2.pTxMsg->RTR = CAN_RTR_DATA;
hcan2.pTxMsg->IDE = frameType; // 0 for standard, 4 for extended
hcan2.pTxMsg->DLC = frameDLC; // 1-8 DLC bytes
hcan2.pTxMsg->StdId = frameID; // frame identifier
hcan2.pTxMsg->Data[0] = frameMessage[0];
hcan2.pTxMsg->Data[1] = frameMessage[1];
hcan2.pTxMsg->Data[2] = frameMessage[2];
hcan2.pTxMsg->Data[3] = frameMessage[3];
hcan2.pTxMsg->Data[4] = frameMessage[4];
hcan2.pTxMsg->Data[5] = frameMessage[5];
hcan2.pTxMsg->Data[6] = frameMessage[6];
hcan2.pTxMsg->Data[7] = frameMessage[7];
if(HAL_CAN_Transmit(&hcan2, 1) != HAL_OK){
/* Transmition Error */
}
}
canF1(0x460, 0, 8, highVoltageOnOff);
canF1(0x470, 0, 8, faultInfoBMS);
canF1(0x480, 0, 8, regenBMS);
canF1(0x530, 0, 7, chargerEDN33);
canF1(0x172, 0, 8, absVmu);
canF1(0x618, 0, 7, chargerEDN33);
canF1(0x050, 0, 8, highVoltageOnOff);
canF1(0x060, 0, 8, faultInfoBMS);
canF1(0x070, 0, 8, regenBMS);
canDisplayFrames(0x460, 70);
canDisplayFrames(0x470, 100);
canDisplayFrames(0x480, 130);
canDisplayFrames(0x530, 160);
canDisplayFrames(0x172, 190);
canDisplayFrames(0x618, 220);
canDisplayFrames(0x050, 250);
canDisplayFrames(0x060, 280);
canDisplayFrames(0x070, 310);
The canDisplayFrames() is for both receiving CAN data and displaying it on the LCD. Now interesting part is that when I turn the stm on three and only three frames are being sent and displayed. That is with IDs: 0x460, 0x470 and 0x480. Then, after connecting the PEAK CAN all of the remaining frames are displayed (on LCD) but the rateat which the first three are beign received slows down. On the PCAN-View there's still nothing and the bus is heavy. When I disconnect the PEAK it returns to the original state: I receive only three frames.