stm32 - 用CAN总线对STM32微控制器编程的问题
问题描述
我是 STM32 微控制器和 CAN 总线通信协议的新手,我正在编写 STM32F103xx 微控制器。我想使用 CAN 总线将数据传输到同一系列的另一个微控制器。
我设置了所有必要的设置,但是在调试代码时它卡在传输挂起函数中并且不传输。我希望传输数据,但事实并非如此。
我不相信我的硬件有问题。
PS:我已经尝试过 CAN 处理程序的正常模式和 LOOPBACK 模式,但它们都不起作用。
int main(void)
{
HAL_Init();
SystemClock_Config();
uint32_t BUTTON_0;
uint32_t BUTTON_1;
uint8_t Data_0[5] = "aaaaa";
uint8_t Data_1[5] = "ZZZZZ";
MX_GPIO_Init();
MX_CAN_Init();
if(HAL_CAN_Init(&hcan) != HAL_OK){
Error_Handler();
}
if(HAL_CAN_Start(&hcan) != HAL_OK){
Error_Handler();
}
while (1)
{
TxHeader.DLC = 5;
TxHeader.StdId = 0x65D;
TxHeader.IDE = CAN_ID_STD;
TxHeader.RTR = CAN_RTR_DATA;
BUTTON_0 = HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0);
BUTTON_1 = HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_1);
if (BUTTON_0 == 0U){
if (HAL_CAN_AddTxMessage(&hcan, &TxHeader, Data_0, &TxMailbox) != HAL_OK ){
Error_Handler();
}
}
if (BUTTON_1 == 0U){
if (HAL_CAN_AddTxMessage(&hcan, &TxHeader, Data_1, &TxMailbox) != HAL_OK){
Error_Handler();
}
}
while (HAL_CAN_IsTxMessagePending(&hcan, TxMailbox));
if (BUTTON_0 && BUTTON_1 == 0U){
printf("Please Press a Button");
}
}
}
解决方案
您正在使用 STM32CubeF1 HAL 库(可能通过 STM32CubeMX)。请查看相应的 用户手册 - 第 9.2.1 节推荐以下程序:
- 通过执行以下命令初始化 CAN 低级资源
HAL_CAN_MspInit()
:
- 使用启用 CAN 接口时钟
__HAL_RCC_CANx_CLK_ENABLE()
- 配置 CAN 引脚
- 启用 CAN GPIO 的时钟
- 将 CAN 引脚配置为备用功能开漏
- 如果使用中断 [...]
HAL_CAN_Init()
使用函数初始化 CAN 外设。此函数诉诸HAL_CAN_MspInit()
低级初始化。- 使用以下配置函数配置接收过滤器:
HAL_CAN_ConfigFilter()
HAL_CAN_Start()
使用函数启动 CAN 模块。在这个级别,节点在总线上处于活动状态:它接收消息,并且可以发送消息。- 要管理消息传输,可以使用以下 Tx 控制功能:
HAL_CAN_AddTxMessage()
请求传输新消息。- [...]
HAL_CAN_IsTxMessagePending()
检查 Tx 邮箱中是否有消息待处理。- [...]
- 当 CAN Rx FIFO 接收到消息时,可以使用该
HAL_CAN_GetRxMessage()
函数检索它。函数 HAL_CAN_GetRxFifoFillLevel() 允许知道有多少 Rx 消息存储在 Rx Fifo 中。- 调用该
HAL_CAN_Stop()
函数会停止 CAN 模块。- 去初始化是通过
HAL_CAN_DeInit()
函数来实现的。[...]
轮询模式操作/传输:
- 使用 . 监控 Tx 邮箱的可用性,直到至少有一个 Tx 邮箱空闲
HAL_CAN_GetTxMailboxesFreeLevel()
。- 然后使用 请求传输消息
HAL_CAN_AddTxMessage()
。
您的代码示例没有显示从中调用的子函数,main()
因此您必须检查自己:-)
- CAN/GPIO 时钟在分配相应寄存器之前已启用。
- GPIO 引脚按照推荐配置。
另一个想法 - 是不是你必须HAL_CAN_GetTxMailboxesFreeLevel()
在启动 CAN 后检查,甚至在添加第一条消息进行传输之前?
步骤 (2.)、(4.)、(5.) 已由您的代码处理,步骤 (3.)、(6.)、(7.)、(8.) 与您的代码无关问题(但仅限于接收/ deinit)。
如果您不想自己完成所有手动工作,也可以使用以下工具之一作为起点。这两种工具都远非完美(我们的一些 StackOverflow 同行根本不同意推荐它们),但它们通常已经提供了包含您需要的大多数相关步骤的基本结构:
固件示例集合(有关详细信息,请参阅其 应用说明 )。
代码生成器 STM32CubeMX
推荐阅读
- azure-devops - Azure DevOps - 帮助/服务台管理系统
- gradle - 我可以做一些判断来在不同的操作系统平台上设置目录前缀吗?
- javascript - Javascript 是否有时间复杂度为 O(log n) 的过滤函数?
- iphone - Where is the Unique Device Identifier (UDID) for an Iphone?
- .net-core - 在 .Net Core OPC UA 客户端上使用基于事件的 MonitoredItem 处理 Sinumerik 警报
- python - CDK ApiMapping 键可能只包含字母、数字和...错误之一
- python - 在另一个文件中使用引发异常的属性
- oracle-adf - JBO-25014:另一个用户使用主键 oracle.jbo.Key[x] 更改了行
- python - Tkinter - 使用循环创建的条目,我如何与单个条目进行交互?
- r - 如何更改选项卡集面板的格式