Bor*_*nak 2 c embedded hal can-bus stm32
我开始在 STM32F103xx MCU 中对 CAN 外设环回模式的 HAL 驱动程序进行基本使用。根据MCU的用户手册,当传输完全完成并且数据在CAN总线上可用时,CAN_TSR寄存器的TME、RQCP和TXOK位被硬件置1,表明相应的邮箱已变空,并且传输成功。
当我调试以下程序时,CAN_TSR 寄存器中没有发生上述任何更改。我只能看到 TME 位被设置,这意味着提供了一个邮箱用于传输,但从未传输。
我的这段代码导致程序中出现不定式循环:
while(HAL_CAN_IsTxMessagePending(&hcan, TxMailbox));
Run Code Online (Sandbox Code Playgroud)
您能解释一下我的问题是什么以及我应该做什么吗?感谢您的想法。
这是完整的代码:
#include "main.h"
CAN_HandleTypeDef hcan;
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_CAN_Init(void);
/* USER CODE BEGIN PFP */
void Can_TX(void);
/* USER CODE END PFP */
int main(void)
{
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* Configure the system clock */
SystemClock_Config();
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_CAN_Init();
/* USER CODE BEGIN 2 */
LCD1602_Begin4BIT(RS_GPIO_Port, RS_Pin, E_Pin, D4_GPIO_Port, D4_Pin, D5_Pin, D6_Pin, D7_Pin);
LCD1602_print("Sending...");
Can_TX();
/* USER CODE END 2 */
/* Infinite loop */
while (1)
{
for (int i = 0; i <= 1000; i++);
}
}
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
}
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK)
{
Error_Handler();
}
}
static void MX_CAN_Init(void)
{
hcan.Instance = CAN1;
hcan.Init.Prescaler = 1;
hcan.Init.Mode = CAN_MODE_LOOPBACK;
hcan.Init.SyncJumpWidth = CAN_SJW_1TQ;
hcan.Init.TimeSeg1 = CAN_BS1_13TQ;
hcan.Init.TimeSeg2 = CAN_BS2_2TQ;
hcan.Init.TimeTriggeredMode = DISABLE;
hcan.Init.AutoBusOff = DISABLE;
hcan.Init.AutoWakeUp = DISABLE;
hcan.Init.AutoRetransmission = ENABLE;
hcan.Init.ReceiveFifoLocked = DISABLE;
hcan.Init.TransmitFifoPriority = DISABLE;
if (HAL_CAN_Init(&hcan) != HAL_OK)
{
Error_Handler();
}
}
static void MX_GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
__HAL_RCC_GPIOA_CLK_ENABLE();
HAL_GPIO_WritePin(GPIOA, RS_Pin|E_Pin|D4_Pin|D5_Pin|D6_Pin|D7_Pin, GPIO_PIN_RESET);
GPIO_InitStruct.Pin = RS_Pin|E_Pin|D4_Pin|D5_Pin|D6_Pin|D7_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
}
void Can_TX(void)
{
CAN_TxHeaderTypeDef TxHeader;
uint8_t our_message[5] = {'H','E','L','L','O'};
uint32_t TxMailbox;
TxHeader.DLC = 1;
TxHeader.StdId = 0x65D;
TxHeader.IDE = CAN_ID_STD;
TxHeader.RTR = CAN_RTR_DATA;
HAL_CAN_AddTxMessage(&hcan, &TxHeader, our_message, &TxMailbox);
if(HAL_CAN_AddTxMessage(&hcan, &TxHeader, our_message, &TxMailbox) != HAL_OK)
{
Error_Handler();
}
while(HAL_CAN_IsTxMessagePending(&hcan, TxMailbox));
LCD1602_print("Message is sent");
}
void Error_Handler(void) { }
Run Code Online (Sandbox Code Playgroud)
小智 6
我可能有其他有用的信息,关于正确的位计时设置如何解决我的问题,并使我的发送消息没有错误地离开邮箱。
我想用环回功能测试我的 CAN 外设,但是消息被困在邮箱中。
仔细阅读文档后,我首先发现我忘记了HelpingHand 的建议,事实上HAL_CAN_Start(),标志 INRQ 仍然打开。(它是由 设定的。)HAL_CAN_Init
修改后,我在接收端没有看到任何消息,并且不确定它是否已正确发送。调查原因,我注意到RQCPx设置为1,意味着无论成功还是错误,传输请求都已完成,TXOKx为0和TERRx1时,意味着存在传输错误。(错误状态寄存器LEC)的(最后一个错误代码CAN_ESR)位设置为 101,或者根据文档,位显性错误。
我不太明白这意味着什么,可能会欢迎澄清,以便更好地理解如何使邮件正确离开邮箱,但在 st 社区偶然发现这个帖子,我明白使用随机计时设置不会有好的结果。(现在看来很明显)。
因此,使用CAN 位时间计算,我找到了正确的设置。为此,我需要我的APB1 peripheral clocks频率和所需的波特率(对我来说,这些是 24MHz 和 125kbps)。我使用了该工具推荐的首选值sample point和SJW推荐值,分别是 87.5% 和 1。然后生成下表:
https: //i.stack.imgur.com/ENshf.png
然后填充位时序参数的 STM32CubeIDE 字段非常简单: https://i.stack.imgur.com/V1q61.png
tada,它TXOKx位于 1 和TERRx0 处。
作为奖励,这里有一小段代码可以检索LEC我编写的内容。它并不打算在功能齐全的应用程序中使用,它只是用于测试。
//adds a message to transmit and obtains "allocated" TxMailbox
HAL_CAN_AddTxMessage(hcan, &TxHeader, TxData, &TxMailbox);
//waiting for message to leave
while(HAL_CAN_IsTxMessagePending(&hcan1, TxMailbox));
//waiting for transmission request to be completed by checking RQCPx
while( !(hcan->Instance->TSR & ( 0x1 << (7 * ( TxMailbox - 1 )))));
//checking if there is an error at TERRx, may be done with TXOKx as well (i think)
if ((hcan->Instance->TSR & ( 0x8 << (7 * ( TxMailbox - 1 ))))){
//error is described in ESR at LEC last error code
uint8_t error_code = ( hcan->Instance->ESR & 0x70 ) >> 4;
//000: No Error
//001: Stuff Error
//010: Form Error
//011: Acknowledgment Error
//100: Bit recessive Error
//101: Bit dominant Error
//110: CRC Error
//111: Set by software
while (1);
}
Run Code Online (Sandbox Code Playgroud)
我希望我的回答与主题无关,并且根据 Stack Overflow 政策可以被视为可接受的第一贡献。
| 归档时间: |
|
| 查看次数: |
7616 次 |
| 最近记录: |