2020-11-16 11:48 PM
Hi everyone,
I have a problem with implementation CAN protocol on STM32F103C8.
I have a blue pill board connected through PA11 (CAN Rx) and PA12 (CAN Tx) to CJMCU-1051 transceiver ( relation between connection: CRX -> PA11, CTX -> PA12).
The CANL and CANH signals from the transceiver are connected to the CAN bus on which there are already two nodes and they communicate with each other with baudrate = 500kBps (4 frames run on the network):
So network is working.
And now my code.
Clocks are configuring to max speed - 72MHz (of course PCLK1, according to RM , is sets to 36MHz).
void RCC_Conf(void)
{
// RCC setting reset
RCC_DeInit();
// Turn on HSE
RCC_HSEConfig(RCC_HSE_ON);
// Wait up to HSE will be ready
HSEStartUpStatus = RCC_WaitForHSEStartUp();
if(HSEStartUpStatus == SUCCESS)
{
/*
* the introduction of delays is (waitstate) for higher clock rates
* is due to the maximum frequency with which it is performed
* communication with Flash memory can be 24 MHz
*/
FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);
// wait for flash memory
FLASH_SetLatency(FLASH_Latency_2);
// HCLK = SYSCLK
RCC_HCLKConfig(RCC_SYSCLK_Div1);
// PCLK2 = HCLK
RCC_PCLK2Config(RCC_HCLK_Div1);
// PCLK1 = HCLK/2
RCC_PCLK1Config(RCC_HCLK_Div2);
// PLLCLK = 8MHz * 9 = 72 MHz
RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9);
// Turn on PLL
RCC_PLLCmd(ENABLE);
// Wait up to PLL will be ready
while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET);
// Select PLL as source of clock
RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);
// Wait up to PLL will be the source of clock
while(RCC_GetSYSCLKSource() != 0x08);
// Turn on Włączenie clock signal supervision system
//RCC_ClockSecuritySystemCmd(ENABLE);
}
}
Configuration of SysTick
void SysTick_Conf (void)
{
SysTick_Config(F_PCLK2/8/1000);
SysTick->CTRL &= ~SysTick_CTRL_CLKSOURCE_Msk;
}
And finally CAN configuration:
void CAN_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
uint8_t ststus = 10;
/* Configure CAN1 IOs **********************************************/
/* GPIOA and AFIO clocks enable */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO | RCC_APB2Periph_GPIOA, ENABLE);
/* Configure CAN1 RX pin */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_Init(GPIOA, &GPIO_InitStructure)
/* Configure CAN1 TX pin */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
/* Configure CAN1 and CAN2 **************************************************/
/* CAN1 and Periph clocks enable */
RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1, ENABLE);
/* CAN1 and CAN2 register init */
CAN_DeInit(CAN1);
// CAN_DeInit(CAN2);
/* Struct init*/
CAN_StructInit(&CAN_InitStructure);
/* CAN1 and CAN2 cell init */
CAN_InitStructure.CAN_TTCM = DISABLE;
CAN_InitStructure.CAN_ABOM = DISABLE;
CAN_InitStructure.CAN_AWUM = ENABLE;//DISABLE;
CAN_InitStructure.CAN_NART = DISABLE;
CAN_InitStructure.CAN_RFLM = DISABLE;
CAN_InitStructure.CAN_TXFP = ENABLE;
CAN_InitStructure.CAN_Mode = CAN_Mode_Normal;
CAN_InitStructure.CAN_SJW = CAN_SJW_4tq;
CAN_InitStructure.CAN_BS1 = CAN_BS1_8tq;
CAN_InitStructure.CAN_BS2 = CAN_BS2_3tq;
/* 500KBps */
CAN_InitStructure.CAN_Prescaler =12;
/*Initializes the CAN1 and CAN2 */
ststus = CAN_Init(CAN1, &CAN_InitStructure);
// CAN_Init(CAN2, &CAN_InitStructure);
/* CAN1 filter init */
CAN_FilterInitStructure.CAN_FilterNumber = 1;
CAN_FilterInitStructure.CAN_FilterMode = CAN_FilterMode_IdMask;
CAN_FilterInitStructure.CAN_FilterScale = CAN_FilterScale_32bit;
CAN_FilterInitStructure.CAN_FilterIdHigh = 0x1;
CAN_FilterInitStructure.CAN_FilterIdLow = 0x0000;
CAN_FilterInitStructure.CAN_FilterMaskIdHigh = 0x0000;
CAN_FilterInitStructure.CAN_FilterMaskIdLow = 0x0000;
CAN_FilterInitStructure.CAN_FilterFIFOAssignment = 0;
CAN_FilterInitStructure.CAN_FilterActivation = ENABLE;
CAN_FilterInit(&CAN_FilterInitStructure);
TxMessage.StdId = 0x10;
TxMessage.ExtId = 0x00;
TxMessage.RTR = CAN_RTR_DATA;
TxMessage.IDE = CAN_ID_STD;
TxMessage.DLC = 4;
}
As answer from function
ststus = CAN_Init(CAN1, &CAN_InitStructure);
I got value equal to 1, so CAN protocol is correctly implemented and it is in normal mode. This situation is confirmed by values of registers:
In main program loop I want to send a frame every 1s, the source_time variable is a variable incremented in the SysTick interrupt and I want to send it by the bus
while (1)
{
if(flag_)
{
TxMessage.Data[0] = (uint8_t)(source_time >> 24);
TxMessage.Data[1] = (uint8_t)(source_time >> 16);
TxMessage.Data[2] = (uint8_t)(source_time >> 8);
TxMessage.Data[3] = (uint8_t)source_time;
temp1 = CAN_Transmit(CAN1, &TxMessage);
temp2 = CAN_GetLastErrorCode(CAN1);
TransmitStatus[0] = CAN_TransmitStatus(CAN1,0);
TransmitStatus[1] = CAN_TransmitStatus(CAN1,1);
TransmitStatus[2] = CAN_TransmitStatus(CAN1,2);
flag_ = 0;
}
}
The result is that transmission status is set to pending (the value is returned by the CAN_TransmitStatus function) for all FIFO banks, what is confirmed by registers:
After connection oscilloscope between microcontroller and transceiver I can notice that transceiver allow for transferring CRX frames (PA11 pin), o that I conclude that transceiver works properly:
Summing up, maybe someone has an idea why STM does not send a frame to the transceiver but is in pending mode all the time?