2020-07-15 06:44 AM
Hello Everybody,
I'm building a device who need to transfer a bunch of datas on a CAN bus at 250bauds.
When I get the datas from my buffer to create the messages, it seem that some are mission (I'm sniffing the CAN bus with a can-bus shield from seedstudio).
I receive only 18 messages when I'm supposed to receive 60.
The problem is: when I'm in debug mode and I pause before every HAL_CAN_AddTxMessage, everything work like a charm, no message are lost.
But when I'm burst transmitting (waiting for the mailboxes to be all free before sending again), messages are lost.
I would like to know why. It's like some messages are erased/pushed out during the process.
Here are my lines about how to send messages:
while (HAL_CAN_GetTxMailboxesFreeLevel(&hcan) != 3){
}
while (HAL_CAN_AddTxMessage(&hcan, &TxHeader, TxData, &TxMailbox) != HAL_OK)
{
}
Thank you.
2020-07-15 06:53 AM
>>The problem is: when I'm in debug mode and I pause before every HAL_CAN_AddTxMessage, everything work like a charm, no message are lost.
Perhaps use telemetry/instrumentation instead of single stepping and breaking real time operation. Monitor errors, and register level status, etc.
The code fragment looks unhelpful. Perhap consider the scope of the data buffers, and how it reacts / advances to the next message, or responds to errors etc. Really have little feel of the mechanics here, other than you look to be cramming data with little regard.
2020-07-15 07:03 AM
According to the comments in the driver source code https://github.com/STMicroelectronics/STM32CubeF4/blob/master/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_can.c you should wait until at least one Tx mailbox is free, i.e.
while (HAL_CAN_GetTxMailboxesFreeLevel(&hcan) < 1);
hth
KnarfB
2020-07-15 08:31 AM
Mu full code look like that:
void HAL_SPI_RxCpltCallback(SPI_HandleTypeDef *spi){
HAL_GPIO_WritePin(CS_IMU_GPIO_Port, CS_IMU_Pin, SET);
//On découpe la liste des bytes obtenus par capteur sur 3 axes à chaque fois (3*2 bytes)
//On ajoute un préfixe pour déterminer si c'est l'accéléromètre ou le gyroscope qui a fourni la donnée
uint8_t decoupeur[8] = {0};
uint8_t canstate = 0;
uint8_t Inclinaxel = 0;
//Selecteur only serve to know where we are in the buffer. IMU_message_quantity know how full the buffer is.
//Decoupeur is the payload holder. The first byte contain 0 or 1 as a prefix to be interpreted in a PC later.
while (selecteur < IMU_message_quantity){
if (switcher == 0){
decoupeur[0] = 0; //Gyroscope
}
else{
decoupeur[0] = 1; //Accelerometre
}
for (uint8_t i= 1; i < 7 ; i++){
decoupeur[i] =spiDATA[selecteur];
selecteur++;
}
while (HAL_CAN_GetTxMailboxesFreeLevel(&hcan) < 1){
}
while (HAL_CAN_AddTxMessage(&hcan, &TxHeader, decoupeur, &TxMailbox) != HAL_OK)
{
}
if (canstate == 0){
//Si erreur ou si Mailboxes pleines
//HAL_Delay(1);
selecteur = selecteur - 6;
if (switcher == 0){
switcher = 1;
}
else {
switcher = 0;
}
}
else { // Si la mise en mailbox fonctionne, on bouge le switcher
if (Inclinaxel < 2){
switcher = 0;
Inclinaxel++;
}
else if (Inclinaxel < 5){
switcher = 1;
Inclinaxel++;
}
else{
switcher = 0;
Inclinaxel = 0;
}
}
}
//Selector back to 0 when all the datas are sended
selecteur = 0;
}
I checked on oscilloscope: all my frames transit in an interval of 26,61ms.
After counting number of bytes in a full frame with 7 bytes payloads: 103 bits transmitted.
With a CAN baud rate of 250kbaud/s, I find theoretically that my 60 messages must have been transmitted in 24,7ms.
Between 26,61 and 24,7, I imagine that it's the CAN-BUS shield from Seedstudio who can't just manage all the frames to show them in console.
I'm still pretty new to can bus implementation so maybe it's a trivial question: could it be a problem that my sample point (obtained with CANCalculator from mikroelectronica) is at 88,9% ? Everywhere I've read about can bus, they spoke about a sample point at 75%. My parameters are makred as "Good" in the calculator, but "Optimal" values are between 73% and 61%.
Thank you.