CAN_TxStatus_Pending报错问题

news2025/2/24 11:26:52

        最近用STM32F407最小电路板测试CAN通讯遇到点小问题:回环模式测试没有问题的基础上,两块相同的最小系统板之间也可以通讯。但把其中一块板子换成USB转CAN分析仪时(或者其他板子),怎么也调不通。

        思考良久,硬件测试正常,没找到问题。逼得没办法,将CANH和CANL接到滤波器(此时在两块STM32F407最小系统板之间正常收发信息),测试波特率,才找到根源:不知什么时候,将外部时钟的系统频率由336MHz调成了360MHz,结果就导致CAN一直发送失败...

详情如下:

CAN.h代码:

#ifndef __CAN1_H
#define __CAN1_H

#include "stm32f4xx.h"                  // Device header

void CAN1_Init(void);
void CAN1_SetMsg(CanTxMsg* Send_CAN1_Msg);
void CAN1_Send(CanTxMsg* TxMessage);
void CAN1_RX0_IRQHandler(void);

#endif

CAN.c代码

#include "CAN1.h"

//	CAN1_RX		PA11	
//	CAN1_TX		PA12		APB1总线	42MHz

extern CanRxMsg Recv_CAN1_Msg;
uint8_t t = 6;

void CAN1_Init(void)
{
	//开启CAN1和GPIO时钟
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE);
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1,ENABLE);
	//引脚复用为CAN1
	GPIO_PinAFConfig(GPIOA,GPIO_PinSource11,GPIO_AF_CAN1);
	GPIO_PinAFConfig(GPIOA,GPIO_PinSource12,GPIO_AF_CAN1);
	//配置GPIO引脚
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11 | GPIO_Pin_12;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
	GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
	GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA,&GPIO_InitStructure);
	
	//CAN1初始化配置
	CAN_InitTypeDef CAN_InitStructure;
	CAN_DeInit(CAN1);
	CAN_StructInit(&CAN_InitStructure);
	//CAN最大频率为1MHz。APB1频率为42MHz,波特率 = 42M/预分频/(1+BS1+BS2)
	//在本案例中,波特率 = 42M/6/(1+4+2) = 1M
	//如果想让波特率 = 500k,可以设置预分频为12,或者增加BS1和BS2的值
	CAN_InitStructure.CAN_Prescaler = 12;		//预分频,APB1总线42MHz
	CAN_InitStructure.CAN_BS1 = CAN_BS1_4tq;
	CAN_InitStructure.CAN_BS2 = CAN_BS2_2tq;
	CAN_InitStructure.CAN_SJW = CAN_SJW_2tq;
	CAN_InitStructure.CAN_Mode = CAN_Mode_Normal;		//CAN模式选择
//	CAN_InitStructure.CAN_Mode = CAN_Mode_LoopBack;	
	CAN_InitStructure.CAN_ABOM = ENABLE;			//自动离线
	CAN_InitStructure.CAN_AWUM = ENABLE;			//自动唤醒
	CAN_InitStructure.CAN_NART = DISABLE;			//禁止自动重发送,消息只发送一次
	CAN_InitStructure.CAN_RFLM = DISABLE;			//FIFO满了后,覆盖前一条
	CAN_InitStructure.CAN_TTCM = DISABLE;			//时间戳。不需要时间戳
	CAN_InitStructure.CAN_TXFP = DISABLE;			//发送FIFO优先级。按照请求的时间,不是标识符
	CAN_Init(CAN1,&CAN_InitStructure);
	
	//CAN过滤器配置
	CAN_FilterInitTypeDef CAN_FilterInitStructure;
	CAN_FilterInitStructure.CAN_FilterActivation = ENABLE;		//是否激活筛选器
	CAN_FilterInitStructure.CAN_FilterFIFOAssignment = CAN_Filter_FIFO0;
	//参考CAN 发送邮箱标识符寄存器 (CAN_TIxR),最低三位是功能码,所以需要左移3bit
	CAN_FilterInitStructure.CAN_FilterIdHigh = ((((uint32_t)0x199 << 3 )| CAN_ID_STD | CAN_RTR_DATA)&0xFFFF0000)>>16;
	CAN_FilterInitStructure.CAN_FilterIdLow = (((uint32_t)0x199 << 3 )| CAN_ID_STD | CAN_RTR_DATA)&0xFFFF;
	CAN_FilterInitStructure.CAN_FilterMaskIdHigh = 0x0000;
	CAN_FilterInitStructure.CAN_FilterMaskIdLow = 0x0000;
	CAN_FilterInitStructure.CAN_FilterMode = CAN_FilterMode_IdMask;		//工作在掩码模式
	CAN_FilterInitStructure.CAN_FilterNumber = 8;				//设置筛选器的编号,0~13
	CAN_FilterInitStructure.CAN_FilterScale = CAN_FilterScale_32bit;	//筛选器的尺寸
	CAN_FilterInit(&CAN_FilterInitStructure);
	
	//配置CAN中断
	CAN_ITConfig(CAN1,CAN_IT_FMP0,ENABLE);
	
	//中断配置
	NVIC_InitTypeDef NVIC_InitStructure;
	NVIC_InitStructure.NVIC_IRQChannel = CAN1_RX0_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
	NVIC_Init(&NVIC_InitStructure);
}

//设置要发送的数据
void CAN1_SetMsg(CanTxMsg* Send_CAN1_Msg)
{
	if(t>9)
		t = 6;
	Send_CAN1_Msg->ExtId = 0;		//此处采用标准报文格式,因此不用给ExtId赋值
	Send_CAN1_Msg->IDE = CAN_ID_STD;
	Send_CAN1_Msg->RTR = CAN_RTR_DATA;
	Send_CAN1_Msg->StdId = 0x199;	//设置标准ID为0x1314
	Send_CAN1_Msg->DLC = 8;
	for(uint8_t i = 0;i<8;i++)
	{
		Send_CAN1_Msg->Data[i] = t+i;
	}
	t++;
}

void CAN1_RX0_IRQHandler(void)
{
	if(CAN_GetITStatus(CAN1,CAN_IT_FMP0) == SET)
	{
		//接收数据后,系统会自动清除中断标志位。
		//如果没有接收函数,中断标志位一直保持为1,导致程序卡死
		CAN_Receive(CAN1,CAN_FIFO0,&Recv_CAN1_Msg);
	}
	//不用单独清除标志位。CAN_ClearITPendingBit函数没有CAN_IT_FMP0这个变量
//	CAN_ClearITPendingBit(CAN1,CAN_IT_FMP0);
}

main.c代码

#include "stm32f4xx.h"                  // Device header
#include "Delay.h"
#include "CAN1.h"

CanTxMsg Send_CAN1_Msg;
CanRxMsg Recv_CAN1_Msg;
uint8_t Mail_Box = 0;

int main(void)
{
	//NVIC为内核中断,函数在misc.c和misc.h文件中
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);
	
	CAN1_Init();
	CAN1_RX0_IRQHandler();
	
	while(1)
	{
		//设置要发送的数据
		CAN1_SetMsg(&Send_CAN1_Msg);
		//获取发送的邮箱号。如果没有空的邮箱,返回CAN_TxStatus_NoMailBox
		Mail_Box = CAN_Transmit(CAN1,&Send_CAN1_Msg);
		if(Mail_Box != CAN_TxStatus_NoMailBox)
		{
			//检测发送状态,一直等到发送成功
			while(CAN_TransmitStatus(CAN1,Mail_Box) != CAN_TxStatus_Ok);
			//此处延时是为了让CAN收发器将收到的数据转换为电平,传送到总线
			delay_ms(1000);
		}
		else 
			return 0;
		
		//此处延时只是单纯防止发送过快
		delay_ms(1000);
	}
}

起初,代码运行时出现的问题:每次运行,都会卡在

while(CAN_TransmitStatus(CAN1,Mail_Box) != CAN_TxStatus_Ok);这一行,经检测,CAN_TransmitStatus(CAN1,Mail_Box)函数的返回值是CAN_TxStatus_Pending,也就是发送不成功

于是怀疑是代码有问题。调成回环模式测试,正常,用两个相同的板子测试,也是正常的

但每次接到USB转CAN分析仪就卡住,差点以为是分析仪坏掉了。于是用STM32F107板子写了个代码测试,也会卡住。猜测是波特率对不上,导致发送错误,于是用示波器测试频率(方法:将CANH接到示波器探头,将CANL接到示波器地端。按自动检测按钮。注意需要把程序中的两个延时注释掉),果然和计算数值不对。按照上面的计算,波特率应该是500kHz,实测是541.6KHz。

查stm32f4xx.h文件,HSE_VALUE数值和实际晶振相同

于是逐个检查system_stm32f4xx.c文件中的各个参数,最终发现,PLL_N的数值不知什么时候被改成了360

(检查方法,双击选中,右键,点击Go To Definition Of "PLL_N",调到PLL_N定义处)

一时大意,搞得这么麻烦,吸取教训了...

(以上代码亲测有效,供大家参考。芯片是stm32f407zgt6,外部晶振8MHz)

整体接线

USB转CAN分析仪,通电后,红灯亮起,如果通讯成功,绿灯+红灯同时亮,如上图(红灯小,拍不出来)

USB转CAN分析仪的软件界面以及通讯结果:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1899099.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

只需几个演示就能对齐大模型,杨笛一团队提出的DITTO竟如此高效

人类的教育方式&#xff0c;对大模型而言也很适用。 养育孩子时&#xff0c;古往今来人们都会谈到一种重要方法&#xff1a;以身作则。也就是让自己成为孩子模仿学习的范例&#xff0c;而不是单纯地告诉他们应该怎么做。在训练大语言模型&#xff08;LLM&#xff09;时&#xf…

防勒索病毒袭击,及时定期备份势在必行——易备防勒索备份成功案例

上海某贸易有限公司是于 2010 年 6 月在上海成立的全日资企业&#xff0c;注册资金一亿日元。总公司位于日本东京&#xff0c;从事独立开发制造和销售使用纯天然的植物制成的化妆品、健康食品、日用小商品。 该公司使用用友优普 U8 供应链及电商系统&#xff0c;该系统部署于阿…

CV02_超强数据集:MSCOCO数据集的简单介绍

1.1 简介 MSCOCO数据集&#xff0c;全称为Microsoft Common Objects in Context&#xff0c;是由微软公司在2014年推出并维护的一个大规模的图像数据集&#xff0c;旨在推动计算机视觉领域的研究&#xff0c;尤其是目标识别、目标检测、实例分割、图像描述生成等任务。该数据集…

什么是OSPFv2 ?

什么是OSPF ? 开放式最短路径优先 OSPF&#xff08;Open Shortest Path First&#xff09;是IETF组织开发的一个基于链路状态的内部网关协议&#xff08;Interior Gateway Protocol&#xff09;。 目前针对IPv4协议使用的是OSPF Version 2&#xff08;RFC2328&#xff09;&a…

CAN总线(上)

CAN总线&#xff08;Controller Area Network Bus&#xff09;控制器局域网总线 CAN总线是由BOSCH公司开发的一种简洁易用、传输速度快、易扩展、可靠性高的串行通信总线&#xff0c;广泛应用于汽车、嵌入式、工业控制等领域 CAN总线特征&#xff1a; 两根通信线&#xff08;…

mars3d加载wms服务或者wmts服务注意事项

1.wms只支持4326、3857、4490的标准切片&#xff0c;其他坐标系不支持 Mars3D三维可视化平台 | 火星科技 2.wmts同理&#xff0c;Mars3D三维可视化平台 | 火星科技 3.对应级别tilematrix找到的瓦片tilerow&tilecol这两个参数使用常见报错无效参考&#xff1a; 【Mars3d】…

JAVA 八大warrp包装类

一、介绍 二、自动拆箱与手动拆箱 //jdk5前是手动装箱和拆箱//手动装箱 int -> Integerint n1 100;Integer integer new Integer(n1);//只要new就shibuInteger integer1 Integer.value0f(n1)//手动拆箱//Integer -> intint i integer.intValue(); ​//jdk5后&#xff…

源代码防泄漏之反向沙箱方案的经验分享

反向沙箱&#xff08;Reverse Sandbox&#xff09;是一种安全技术&#xff0c;主要用于检测和分析恶意软件的行为。与传统沙箱不同&#xff0c;反向沙箱的重点在于模拟恶意软件的预期运行环境&#xff0c;以诱导恶意软件展示其真实行为。这种技术可以帮助安全专家更深入地理解恶…

Leaflet【六】绘制交互图形、测量、经纬度展示

本文主要探讨了如何利用leaflet-draw插件在地图上绘制图形&#xff0c;以及通过leaflet-measure测量距离和面积&#xff0c;并将经纬度绘制到地图上。首先&#xff0c;我们使用leaflet-draw插件&#xff0c;该插件提供了一种简单而直观的方式来绘制各种形状&#xff08;如点、线…

【K8s】专题六(4):Kubernetes 稳定性之初始化容器

以下内容均来自个人笔记并重新梳理&#xff0c;如有错误欢迎指正&#xff01;如果对您有帮助&#xff0c;烦请点赞、关注、转发&#xff01;欢迎扫码关注个人公众号&#xff01; 目录 一、基本介绍 二、主要特点 三、资源清单&#xff08;示例&#xff09; 一、基本介绍 初…

C电池 和 D 电池的作用和类型详解及其之间的区别

C 和 D 电池是我们日常生活中必不可少的部件。它们通常用于高功率设备。例如手电筒和玩具。 D 型电池和 C 型电池是两种常见的电池类型。它们是一次性圆柱形电池。您可以在很多设备上使用它们。虽然它们有很多相似之处&#xff0c;但它们也有不同的特点。这些特点使它们适合某…

Redis 多数据源自定义配置 Spring Boot 升级版

文章目录 1.前言2.git 示例地址3.需求4.代码实现4.1 application.properties 配置文件4.2 获取 application.properties 中的 redis 配置4.2.1 Environment 对象来获取自定义 redis 配置 4.3 初始化 RedisTemplate 对象&#xff0c;并注册到 Spring IOC 容器4.3.1 初始化方法4.…

Python函数语法详解(与C++对比学习)【未完】

一、Python函数的形式 def function_name (参数, ...) -> return value_type:# 函数体return value# 看具体需求# 如果没有return语句&#xff0c;函数执行完毕后也会返回结果# 只是结果为None。return None可以简写为return 1. Python的返回值 在Python3中&#xff0c;提…

新手教师经常会遇到的问题

教育是塑造未来的关键力量&#xff0c;而教师则是这一过程中不可或缺的角色。然而&#xff0c;对于新手教师来说&#xff0c;步入教育行业往往伴随着一系列挑战。本文将探讨新手教师在职业生涯初期可能遇到的一些常见困难&#xff0c;并提供一些应对策略。 教学准备的挑战 新手…

improved-diffusion-main代码理解

目录 一、 TimestepEmbedSequential二、PyTorch之Checkpoint机制三、AttentionBlock四、use_scale_shift_norm 和nanoDiffusion-main相比&#xff0c;improved-diffusion-main代码是相似的&#xff0c;但有几个不是很好理解的地方记录一下。 一、 TimestepEmbedSequential 代码…

栈复用(覆盖栈上的有用数据)

栈复用&#xff08;覆盖栈上的有用数据&#xff09; 程序给的输入长度&#xff0c;不够溢出 到返回值&#xff0c;甚至都 不到bp位置 &#xff0c;这是要考虑覆盖之前函数(或当前函数)的栈上的有用数据&#xff0c;任何利用 程序后续函数调用 时要利用该位置上的数据&#xff…

机器人具身智能Embodied AI

强调智能体&#xff08;如机器人&#xff09;通过物理身体在物理世界中的实时感知、交互和学习来执行任务。 通过物理交互来完成任务的智能系统。它由“本体”&#xff08;即物理身体&#xff09;和“智能体”&#xff08;即智能核心&#xff09;耦合而成&#xff0c;能够在复…

《HIRI-ViT: Scaling Vision Transformer with High Resolution Inputs》解读

期刊&#xff1a;TPAMI 年份&#xff1a;2024 摘要 视觉Transformer(ViT)和卷积神经网络(CNN)的混合深度模型已经成为一类强大的视觉任务骨干。扩大这种混合主干网的输入分辨率自然会增强模型的能力&#xff0c;但不可避免地要承受二次扩展的沉重计算成本。相反&#xff0c;…

SQL索引事务

SQL索引事务 索引 创建主键约束(primary key),唯一约束(unique),外键约束(foreign key)时,会自动创建对应列的索引 1.1 查看索引 show index from 表名 现在这个表中没有索引,那么我们现在将这几个表删除之后创建新表 我们现在建立一个班级表一个学生表,并且学生表与班级表存…

高速PCB设计Tips

在进行原理图输入过程中&#xff0c;需要注意将设计分解为功能块&#xff0c;将所有相关组件放在同一页。例如&#xff0c;以太网相关的组件&#xff0c;通常运行在50MHz或更高频率&#xff0c;在原理图设计中应集中在同一页。清晰标记高速连接和电源连接。差分信号和单端阻抗控…