<STM32>STM32CubeMX-CAN通信(扫描读取数据方式)(5)

news2024/11/9 5:03:41

<STM32>STM32CubeMX-CAN通信(扫描读取数据方式)(5)
本节主要讲解CAN通信的功能,主要采用扫面检测接收数据的方式;
CAN的详细解说可参考《STM32F4XXX中文参考手册》,资料有详细的讲解和说明,文档可跟作者联系索取,或百度搜索也可。

本系列教程同类文章包括以下:
1、<STM32>STM32CubeMX-基础工程创建及LED灯控制 (1)
2、<STM32>STM32CubeMX-工程创建及定时器控制LED灯闪烁(2)
3、<STM32>STM32CubeMX-串口收发通信(结束标识“\r\n”)(3)
4、<STM32>STM32CubeMX-ADC采集(软件触发单通道)(4)

话不多说,开始写代码吧。。

一、打开STM32CubeMX选择对应的芯片型号,后进入开发界面
1、双击“STM32CubeMX”软件打开,打开后如下图所示,选择红色框1;
在这里插入图片描述
选择后可能会更新,等待更新完成即可,如下图:
在这里插入图片描述
2、选择开发芯片,作者本例程的芯片是STM32F407ZET6,读者根据自己使用的开发板芯片选择即可。操作如下:
按照下图步骤:
步骤1:输入开发使用的芯片型号,作者这里输入:STM32F407ZE,就会在步骤2显示芯片的具体型号;
步骤2:选择具体使用的芯片型号,选中后会高亮;
步骤3:点击“Start Project”,开始进入工程图形配置界面。
在这里插入图片描述

二、图形界面配置
由于采集的ADC数据需要查看,所以本例程采用的是通过串口输出采集的数据,输出到电脑端的串口调试助手。
所以除了基本的时钟、晶振等一些配置,还包含串口配置和ADC配置。
1、配置晶振
步骤1:选择“Pinout&Configuration”;
步骤2:选择“System Core”;
步骤3:选择“RCC”;
步骤4、5:选项下拉选择“Crystal/Ceramic Resonator”
下拉选项说明:
Crystal/Ceramic Resonator:晶体/陶瓷晶振,一般使用的都是这个
BYPASS Clock Source:旁路时钟源
在这里插入图片描述

2、配置DEBUG和SYS
步骤1:选择“Pinout&Configuration”;
步骤2:选择“System Core”;
步骤3:选择“SYS”;
步骤4:选择“Serial Wire”;
此选项是下载调试的方式选择,有很多种,包括SWD、JTAG等方式。
步骤5:选择“Sys Tick”;
此选项是HAL时基的选择,有滴答定时器,和其它定时器1、2、3、4、5…,这里选择SysTick滴答定时器。
在这里插入图片描述
3、配置调试输出串口1
步骤1:选择“Pinout&Configuration”;
步骤2:选择“Connectivity”;
步骤3:选择“USART1”;
步骤4:选择“Asynchronous”;
此下拉选项有多种选择,分别如下:
Asynchronous:异步通信
Synchronous:同步通信
Single Wire(Half-Duplex):半双工
Multiprocessor Communication:多处理器通信
lrDA:红外数据
LIN:局域网互联
SmartCard:智能卡
步骤5:选择“NVIC Settings”->然后勾选中断使能。
选项卡“Parameter Settings”是设置串口的参数
Basic Parameters->Baud Rate:设置波特率,默认115200,可不修改;
Basic Parameters->Word Length:字长,默认“8Bits”,默认即可;
Basic Parameters->Parity:奇偶校验,默认选择"None"无校验;默认即可;
Basic Parameters->Stop Bits:停止位,默认1,默认即可;
Advanced Parameters->Data Direction:数据方向,默认“Receive and Transmit”可接收发送,默认即可;
Advanced Parameters->Over Sampling:过采样长度,默认“16 Samples”16个采样,默认即可;
选项卡“NVIC Settings”是设置中断使能-勾选对应的中断信号源即可,本工程只勾选“USART1 global interrupt”;
选项卡“DMA Settings”是设置串口DMA通道的,可添加DMA,在本工程,不使用。
其它选项卡无需设置。
在这里插入图片描述
4、配置CAN1,使用CAN1,即PA11和PA12引脚
步骤1:选择“Pinout&Configuration”;
步骤2:选择“Connectivity”;
步骤3:选择“CAN1”;
步骤4:勾选"Activated"。
步骤5:CAN参数配置,
选项卡“Parameter Settings”是设置ADC的参数
(1)Bit Timings Parameters->Prescaler :分频系数,这里根据CAN的主频(由时钟树配置得到42Mhz),此处输入42;
(2)Bit Timings Parameters->Time Quanta in Bit Segment 1:位段 1 中的时间量,此处选择“2 Times”;
(3)Bit Timings Parameters->Time Quanta in Bit Segment 2:位段 2 中的时间量,此处选择“5 Times”;
(4)Bit Timings Parameters->ReSynchronization Jump Width:重新同步跳转宽度,此处默认选择“1 Times”即可;
以上四个参数可得到CAN通信的波特率:主频/(2+1+5)/42 =125KHz
其余参数默认即可…
选项卡“NVIC Settings”是设置中断使能,本工程全选;
其它选项卡无需设置。

步骤6:选择PA11和PA12,左击然后选择CAN_TX和CAN_RX。如下图所示。
在这里插入图片描述

三、配置系统时钟
步骤1:选择“Clock&Configuration”;
步骤2:外部高速晶振的大小,作者用的开发板上,外部高速晶振大小时8MHz,读者根据自己使用的开发板上的晶振大小输入对应的值即可;
步骤3:选择器选择下面园点,即选中外部晶振作为输入源;如果电路没外部晶振,可选择上面圆点,选择芯片内部高速晶振作为输入,本工程选外部输入;
步骤4:选择“PLLCLK”,就是选择倍频器PLL作为输入时钟源,如果没外部高速晶振,则选择HSI(第一个圆点);
步骤5:直接输入“168”,作为系统的主频大小。
以上修改完成后 回车,如果右提示,选择确认即可。

参考下图选择,高亮的位置都可以修改,修改后的值如下图所示:
在这里插入图片描述
四、工程输出配置
1、项目文件配置
步骤1:选择“Project Manager”
步骤2:选择“Project”
步骤3:输入工程名称,作者这里输入“CAN1”,表示CAN1功能的工程,一般名称体现工程的作用,可以自定义;
步骤4:点击“Browse”,选择工程存放的路径,不要包含中文;
步骤5:下拉选择“MDK-ARM”,表示用的IDE是keil;可以根据自己使用的编程软件选择,这里作者选用“MDK-ARM”;后面的“V5.27”则是软件的版本号;
步骤6:芯片的HAL库固件包,勾选后面,会自动选择,一般会自动更新到最新版本;
在这里插入图片描述

2、代码生成配置
步骤7:选择“Code Generator”;
步骤8:STM32Cube MCU packages and embedded software packs,STM32Cube MCU 软件包和嵌入式软件包选择,本工程选中第一条;
第一条:Copy all used libraries into the project folder:将所有使用的库复制到项目文件夹中;
第二条:Copy only the necessary library files:只复制必要的库文件;
第三条:Add necessary library files as reference in the toolchain project configuration file:在工具链项目配置文件中添加必要的库文件作为参考;
建议选中第一条,将所以的包含,避免后续开发出现遗漏的文件,方便后续功能增加,就是工程代码量会大一些;

步骤9:Generated files,生成文件,本工程选中,第一、三、四,三个选项;
第一条:Generate pripheral initalization as a pair of ‘.c/.h’ files per peripheral:将外围设备初始化生成为每个外围设备的一对“.c/.h”文件
第二条:Backup previously generated files when re-generating,重新生成时备份以前生成的文件
第三条:Keep User Code when re-generating,重新生成时保留用户代码
第四条:Delete previously generated files when not re-generated ,不重新生成时删除以前生成的文件
步骤10:点击“GENERATE CODE”
在这里插入图片描述
点击生成后弹出提示框,点击“Open Project”,即可打开工程。
在这里插入图片描述

打开后就是界面如下:
在这里插入图片描述

五、代码补充
1、补充串口代码
串口是为了方便测试查看ADC的采集数据,重定向了printf函数,具体操作如下:
打开“usart.c”文件,
在文件头文件引用的“/* USER CODE BEGIN 0 /” 和“ / USER CODE END 1 */ ”之间添加如下代码:

#include "stdio.h"

添加后如下图:
在这里插入图片描述

在末尾的“/* USER CODE BEGIN 1 /” 和“ / USER CODE END 1 */ ”之间添加如下代码:

#if 1
//#pragma import(__use_no_semihosting)             
//标准库需要的支持函数                 
struct __FILE 
{ 
	int handle; 
}; 

FILE __stdout;       
//定义_sys_exit()以避免使用半主机模式    
void _sys_exit(int x) 
{ 
	x = x; 
} 
//重定义fputc函数 
int fputc(int ch, FILE *f)
{ 	
	while((USART1->SR&0X40)==0);//循环发送,直到发送完毕   
	USART1->DR=(uint8_t)ch;      
	return ch;
}
#endif

在这里插入图片描述
2、补充CAN1配置代码
打开can.c
补充CAN的初始化函数,补充后代码如下:

void MX_CAN1_Init(void)
{

  /* USER CODE BEGIN CAN1_Init 0 */
	CAN_FilterTypeDef   CAN1_FilerConf;
  /* USER CODE END CAN1_Init 0 */

  /* USER CODE BEGIN CAN1_Init 1 */

  /* USER CODE END CAN1_Init 1 */
  hcan1.Instance = CAN1;
  hcan1.Init.Prescaler = 42;
  hcan1.Init.Mode = CAN_MODE_NORMAL;
  hcan1.Init.SyncJumpWidth = CAN_SJW_1TQ;
  hcan1.Init.TimeSeg1 = CAN_BS1_2TQ;
  hcan1.Init.TimeSeg2 = CAN_BS2_5TQ;
  hcan1.Init.TimeTriggeredMode = DISABLE;
  hcan1.Init.AutoBusOff = DISABLE;
  hcan1.Init.AutoWakeUp = DISABLE;
  hcan1.Init.AutoRetransmission = DISABLE;
  hcan1.Init.ReceiveFifoLocked = DISABLE;
  hcan1.Init.TransmitFifoPriority = DISABLE;
  if (HAL_CAN_Init(&hcan1) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN CAN1_Init 2 */
	CAN1_FilerConf.FilterIdHigh = 0; //过滤掉不是发送给本机的数据帧//32位ID
	CAN1_FilerConf.FilterIdLow = 0; //确保收到的是标准数据帧
	CAN1_FilerConf.FilterMaskIdHigh = 0;//32位MASK
	CAN1_FilerConf.FilterMaskIdLow = 0;//0xFFFF;
	CAN1_FilerConf.FilterFIFOAssignment = CAN_FILTER_FIFO0;//过滤器0关联到FIFO0
	CAN1_FilerConf.FilterBank = 0;//过滤器0
	CAN1_FilerConf.FilterMode = CAN_FILTERMODE_IDMASK;//屏蔽位模式
	CAN1_FilerConf.FilterScale = CAN_FILTERSCALE_32BIT;
	CAN1_FilerConf.FilterActivation = ENABLE;
	CAN1_FilerConf.SlaveStartFilterBank = 14;
	
    if (HAL_CAN_ConfigFilter(&hcan1,&CAN1_FilerConf) != HAL_OK)
    {
        Error_Handler();
    }
  
  
	HAL_CAN_Start(&hcan1);
   if(HAL_CAN_ActivateNotification(&hcan1,CAN_IT_RX_FIFO0_MSG_PENDING)!=HAL_OK)
	{   
    }
  /* USER CODE END CAN1_Init 2 */

}

,在末尾的“/* USER CODE BEGIN 1 /” 和“ / USER CODE END 1 */ ”之间添加如下代码:

void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan)
{
    CAN_RxHeaderTypeDef rxMsg;
	uint8_t revData[8];
	
	if(hcan->Instance==CAN1)
	{
	   if(HAL_CAN_GetRxMessage(hcan,CAN_RX_FIFO0,&rxMsg,revData)==HAL_OK)
	   {
		   //数据解析
		   printf("接收数据如下:\r\n");
		   printf("标准ID:0x%08x\r\n",rxMsg.StdId);
		   printf("拓展ID:0x%08x\r\n",rxMsg.ExtId);
		   printf("数据为:0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x \r\n",revData[0],revData[1],revData[2],revData[3],revData[4],revData[5],revData[6],revData[7]);
	   }
	}
}
/**************************************************************************************************
 * @brief  :CAN发送数据
* @param  :
			id:地址  
			ide:数据帧类型     CAN_ID_EXT:拓展帧    CAN_ID_STD:标准帧
			pMsg:发送的数据内容 
			len:数据长度
 * @retval :成功:0   失败:1.
 * @note   :none.
 **************************************************************************************************/
uint8_t API_CanSendMsg(uint32_t id,uint8_t ide,uint8_t *pMsg,uint8_t len)
{
	CAN_TxHeaderTypeDef pHeader;
	uint32_t 			pTxMailbox;
	uint8_t 			result = 0;
	CAN_HandleTypeDef	*pCanHandler;
	HAL_StatusTypeDef CanStatus;

	
	if(ide==CAN_ID_STD)
	{
		pHeader.StdId = id;//标准ID
		pHeader.IDE = CAN_ID_STD;
	}
	else
	{
		pHeader.ExtId = id; 
		pHeader.IDE = CAN_ID_EXT;
	}	
	pHeader.RTR = CAN_RTR_DATA;
	pHeader.DLC = len>8?8:len;
	pHeader.TransmitGlobalTime = DISABLE;

	pCanHandler = &hcan1;

	
	
	CanStatus =  HAL_CAN_AddTxMessage(pCanHandler, &pHeader, pMsg, &pTxMailbox);
	
	if(CanStatus !=HAL_OK)
	{
		result = 1;
	}
		
	return result;
}

添加后如下图:
在这里插入图片描述

打开can.h,在末尾的“/* USER CODE BEGIN Prototypes /” 和“ / USER CODE END Prototypes */ ”之间添加如下代码:

uint8_t API_CanSendMsg(uint32_t id,uint8_t ide,uint8_t *pMsg,uint8_t len); //函数声明

添加后如下图:
在这里插入图片描述

3、添加主函数代码
打开“main.h”文件
在文件头文件引用的“/* USER CODE BEGIN Includes /” 和“ / USER CODE END Includes */ ”之间添加如下代码:

#include "stdio.h"

添加后如下图:
在这里插入图片描述
打开main.c文件
主函数main添加相应代码,添加后内容如下:

int main(void)
{
  /* USER CODE BEGIN 1 */
	uint8_t SendData1[8]={0X01,0X02,0X03,0X04,0X05,0X06,0X07,0X08};
	uint8_t SendData2[8]={0X01,0X01,0X03,0X03,0X0f,0X0f,0X0e,0X0e};
  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_CAN1_Init();
  MX_USART1_UART_Init();
  /* USER CODE BEGIN 2 */

  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
	  API_CanSendMsg(0x123321EE,CAN_ID_STD,SendData1,8);//发送标准数据帧
	  HAL_Delay(1000);									//延时1000ms
	  API_CanSendMsg(0x123321EE,CAN_ID_EXT,SendData2,8);//发送拓展数据帧
	  printf("Send Data ...... \n");
  }
  /* USER CODE END 3 */
}

添加后如下图:
在这里插入图片描述

以上代码添加完成,接下来编译运行测试。

六、编译测试
1、编译,点击在这里插入图片描述编辑,确认编译无错,如果有错误,根据错误提示修改即可;
在这里插入图片描述
2、选择下载方式,作者用的是STlink下载器,SWD的方式;配置参考下图选择;
在这里插入图片描述
在这里插入图片描述
3、将下载器链接开发板,然后点击在这里插入图片描述下载代码;
4、打开串口调试助手,选择开发板的串口号,配置串口参数和STM32配置的参数一致,然后点击“打开串口”,查看输出的内容;输入如下图所示:

5、将电路板的CAN接口连接CAN调试模块盒子,配置号CAN波特率和STM32代码一致(本工程为125KHz),打开CAN。可以看到接收输入如下图所示,可发送数据,查看串口助手输出。

七、总结
实验通过串口的输出和CAN调试软件可以看出,CAN通信收发数据正常。

以上是STM32F407ZET6开发板,验证STM32CubeMX创建CAN通信的整个流程。如有不足、遗漏之处可联系作者修改。
如有不明白,交流的地方也可联系作者。

联系方式QQ759521350

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

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

相关文章

CDH 之 Kerberos 安全认证和 Sentry 权限控制管理(一)

一、Kerberos 和 Sentry 概述 1.1 什么是 Kerberos Kerberos是一种计算机网络授权协议,用来在非安全网络中,对个人通信以安全的手段进行身份认证。这个词又指麻省理工学院为这个协议开发的一套计算机软件。软件设计上采用客户端/服务器结构,…

java微服务商城高并发秒杀项目--011.授权规则和系统规则

授权规则在shop-order-server中新建RequestOriginParserDefinition.java,定义请求来源如何获取Component public class RequestOriginParserDefinition implements RequestOriginParser {Overridepublic String parseOrigin(HttpServletRequest request) {/*** 定义从请求的什么…

文本分类论文阅读

1.ChineseBERT: Chinese Pretraining Enhanced by Glyph and Pinyin Information(ACL2021) 字形嵌入根据汉字的不同字体获得,能够从视觉特征中捕捉汉字语义,拼音嵌入表征汉字的发音,解决了汉语中非常普遍的异义异义现…

四、vue基础-指令(一)、vscode代码片段

一、vscode代码片段 我们在前面联系Vue的过程中,有些代码片段是需要经常写的,我们再VSCode中我们可以生成一个代码片段,方便我们快速生成。VSCode中的代码片段有固定的格式,所以我们一般会借助于一个在线工具来完成。 具体步骤如…

01_什么是Uboot

目录 U-Boot简介 获取Uboot U-Boot初次编译 U-Boot烧写与启动 U-Boot简介 Linux系统要启动就必须需要一个bootloader程序(裸机程序),也就说芯片上电以后先运行一段bootloader程序。这段bootloader程序会先初始化DDR等外设,然后将Linux镜像从flash(NAND,NOR FLASH,SD,EMMC等…

【防止恶意用户注册】-- 手机在网状态 API 的防欺诈应用解析

简介 手机在网状态 API 支持传入手机号码,查询手机号在网状态,返回在网、在网不可用、不在网(销号/未启用/停机)等多种状态,查询手机号在网状态之后,可以根据具体的业务需求来进行不同的处理。 本文主要介…

EA的使用---文档的生成

EA中文档的自动生成 1.找到如下界面 2.选择第一个 3.设置存储的位置 4.点击Generate 5.查看生成的文档

ViT Vision Transformer进行猫狗分类

文章目录依赖准备数据集合残差结构PatchEmbed模块Attention模块MLPBlockVisionTransformer结构模型定义定义一个模型训练VISION TRANSFORMER简称ViT,是2020年提出的一种先进的视觉注意力模型,利用transformer及自注意力机制,通过一个标准图像…

【C++STL精讲】string的模拟实现

文章目录💐专栏导读💐文章导读🌷定义string类🌷构造函数🌷拷贝构造函数🌷赋值重载🌷析构函数🌷[]操作符重载🌷比较运算符重载🌷c_str、size、capacity&#x…

模板学堂|DataEase图表样式解析

DataEase开源数据可视化分析平台于2022年6月正式发布模板市场(https://dataease.io/templates/)。模板市场旨在为DataEase用户提供专业、美观、拿来即用的仪表板模板,方便用户根据自身的业务需求和使用场景选择对应的仪表板模板,并…

「VS」Visual Studio 常用小技巧

目录指定代码不编译设置选中项目为启动项代码区显示行号新建垂直文档组生成后将dll复制到指定目录指定代码不编译 说明:在项目开发时,有时候已经将代码加入到项目中,但有不想要编译时可以一下操作。 文件处右键→属性→常规→从生成中排除→选…

快速解决CentOS中yum下载慢的问题(更换成阿里云)

目录1、备份自带的YUM源2、下载新的yum源3、清除旧的 yum 缓存4、更新yum缓存4、查看更换的阿里云镜像的仓库是否生效。为了下载速度快,每次都要做好镜像的更改,既然次数多,懒得每次还来查资料,就自己写一篇博客加强自己的记忆。 …

Docker环境安装

Docker环境安装Docker简介Docker工作原理Docker的应用场景Docker 的优点CentOS Docker 安装与配置Docker 安装Docker 配置Docker容器概念Docker容器操作拉取镜像删除镜像容器相关命令创建并启动容器停止和恢复容器删除容器Docker简介 Docker 是一个开源的应用容器引擎&#xf…

4年外包上岸,我只能说这类公司能不去就不去

我大学学的是计算机专业,毕业的时候,对于找工作比较迷茫,也不知道当时怎么想的,一头就扎进了一家外包公司,一干就是4年。现在终于跳槽到了互联网公司了,我想说的是,但凡有点机会,千万…

ChatGPT背后的AI背景、技术门道和商业应用(万字长文,建议收藏)

作者:京东科技 李俊兵 各位看官好,我是球神(江湖代号)。 自去年11月30日ChatGPT问世以来,迅速爆火出圈。 起初我依然以为这是和当年Transformer, Bert一样的“热点”模型,但是当一篇篇文章/报告不断推送…

计算机网络面试八股文攻略(二)—— TCP 与 UDP

一、基础概念 TCP 与 UDP 是活跃于 运输层 的数据传输协议 TCP:传输控制协议 (Transmission Control Protocol)–提供面向连接的,可靠的数据传输服务。具体来说就是一种要建立双端连接才能发送数据,能确保传输可靠的…

Hive DDL和DML

目录 一 DDL 1.1 数据库 1.1.1 创建数据库 1.1.2 查询数据库 1.1.3 修改数据库 1.1.4 删除数据库 1.1.5 切换当前数据库 1.2 表 1.2.1 创建表 1.2.2 查看表 1.2.3 修改表 3.2.4 删除表 3.2.5 清空表 二 DML 2.1 Load 2.2 Insert 2.2.1 将查询结果插入表中 2…

C++程序设计函数部分(定义+实例)

目录 1、内联函数 2、默认形参值函数 3、重载函数 4、系统函数 1、内联函数 (1)定义 在函数前面加上 inline 申明 eg: inline double CalArea(double radius) { return 3.14*radius*radius; } void main() { double r(3.0); dou…

后缀数组的应用:[Leetcode] 321.拼接最大数(困难)

题目描述 给定长度分别为 m 和 n 的两个数组&#xff0c;其元素由 0-9 构成&#xff0c;表示两个自然数各位上的数字。现在从这两个数组中选出 k (k < m n) 个数字拼接成一个新的数&#xff0c;要求从同一个数组中取出的数字保持其在原数组中的相对顺序。 求满足该条件的…

ChatGPT 究竟在做什么?它为何能做到这些?(1)

ChatGPT能够自动生成一些表面上看起来像人类写出的文字的东西&#xff0c;是一件很厉害且出乎大家意料的事。那么&#xff0c;它是如何做到的呢&#xff1f;又是为何能做到呢&#xff1f;我在这里想大致介绍一下ChatGPT的内部机理&#xff0c;然后探讨一下为什么它能很好地生成…