当前位置: 首页 > news >正文

科技风格设计网站360优化大师最新版下载

科技风格设计网站,360优化大师最新版下载,外包公司简介,本地建设网站 ubuntu目录 一、工程配置 1、时钟、DEBUG、USART6、GPIO、CodeGenerator 2、CAN1 3、NVIC 二、软件设计 1、KEYLED 2、can.h 3、can.c (1)CAN1中断初始化 (2)RNG初始化和随机数产生 (3) 筛选器组设置…

目录

一、工程配置

1、时钟、DEBUG、USART6、GPIO、CodeGenerator

2、CAN1 

3、NVIC

二、软件设计

1、KEYLED

2、can.h

3、can.c

(1)CAN1中断初始化

(2)RNG初始化和随机数产生

(3) 筛选器组设置

(4)发送消息

(5)中断方式接收消息

4、main.c

三、下载与运行


        在实际的CAN通信中,使用轮询方式发送消息,使用中断方式接收消息更加实用和普遍。本实例设计一个CAN通信,使用中断方式接收消息,并且测试在两个FIFO上使用不同的筛选器。

        本实例仍然使用使用旺宝红龙开发板STM32F407ZGT6 KIT V1.0。需要参考本文作者的其他文章:

        参考文章1: 细说STM32F407单片机轮询方式CAN通信_stm32f407can波特率配置表-CSDN博客  https://wenchm.blog.csdn.net/article/details/144852504

        参考文章2:细说STM32F407单片机CAN基础知识及其HAL驱动程序-CSDN博客  https://wenchm.blog.csdn.net/article/details/144769950

        示例仍然引用KEYLED文件夹中的文件。

        示例的功能和使用流程如下:

        示例工程中,使用开发板上的S2键,按下S2键后,发送一个随机数的数据帧。并用LED1显示工作状态,输出到串口助手上。按下S6键,开发板复位。示例的功能还包括:

  • 使用CAN1的回环模式自发自收。
  • 开启FIFO0的接收中断,开启FIFO1的接收中断。
  • 为FIFO0设置筛选器,只接收标识符ID为奇数的消息;为FIFO1设置筛选器,接收所有消息。
  • 使用随机数生成器(Random Number Generator,RNG),在发送消息时,用随机数作为帧的数据。
[S2]KeyUp  = Send a Data Frame    LED1 ON

一、工程配置

        CAN接口原理图同参考文件1。 

1、时钟、DEBUG、USART6、GPIO、CodeGenerator

        与参考 文件1的设置相同或近似。

        这里,设置HCLK=168MHz,PCLK1=42MHz,PCLK2=84MHz。

2、CAN1 

         CAN1模块的参数设置与参考文件1相似。

 

3、NVIC

        使用CAN1模块的接收中断,打开CAN1 RX0中断和CAN1 RX1中断,两个中断的抢占优先级都设置为1,一个CAN模块有4个中断,RX0中断是FIFO0的中断,RX1中断是FIFO1的中断,每个中断有几个中断事件和对应的回调函数,详见参考文章2。

 

二、软件设计

1、KEYLED

        本例的项目中要使用KEYLED,其中的keyled.c和keyled.h的使用方法与参考文章1相同。

2、can.h

/* USER CODE BEGIN Prototypes */
HAL_StatusTypeDef CAN_SetFilters();
void CAN_TestPoll(uint8_t msgID,uint8_t frameType);
/* USER CODE END Prototypes */

3、can.c

/* USER CODE BEGIN 0 */
#include "rng.h"
#include <stdio.h>
/* USER CODE END 0 */
/* USER CODE BEGIN 1 */
//设置筛选器,需要在完成CAN初始化之后调用此函数
HAL_StatusTypeDef CAN_SetFilters()
{CAN_FilterTypeDef canFilter;//1. 设置FIFO0的筛选器canFilter.FilterBank = 0;						//筛选器组编号canFilter.FilterMode = CAN_FILTERMODE_IDMASK;	//ID掩码模式canFilter.FilterScale = CAN_FILTERSCALE_32BIT;	//32位长度//只接收stdID为奇数的帧canFilter.FilterIdHigh = 0x0020;				//CAN_FxR1寄存器的高16位canFilter.FilterIdLow = 0x0000;					//CAN_FxR1寄存器的低16位canFilter.FilterMaskIdHigh = 0x0020;			//CAN_FxR2寄存器的高16位canFilter.FilterMaskIdLow = 0x0000;				//CAN_FxR2寄存器的低16位canFilter.FilterFIFOAssignment = CAN_RX_FIFO0;	//应用于FIFO0canFilter.FilterActivation = ENABLE;			//使用筛选器canFilter.SlaveStartFilterBank = 14;			//从CAN控制器筛选器起始的BankHAL_StatusTypeDef result=HAL_CAN_ConfigFilter(&hcan1, &canFilter);//2. 设置FIFO1的筛选器canFilter.FilterBank = 1;						//筛选器组编号//接收所有帧canFilter.FilterIdHigh = 0x0000;				//CAN_FxR1寄存器的高16位canFilter.FilterIdLow = 0x0000;					//CAN_FxR1寄存器的低16位canFilter.FilterMaskIdHigh = 0x0000;			//CAN_FxR2寄存器的高16位,所有位任意canFilter.FilterMaskIdLow = 0x0000;				//CAN_FxR2寄存器的低16位,所有位任意canFilter.FilterFIFOAssignment = CAN_RX_FIFO1;	//应用于FIFO 1result=HAL_CAN_ConfigFilter(&hcan1, &canFilter);return result;
}void CAN_SendMsg(uint8_t msgID,uint8_t frameType)
{CAN_TxHeaderTypeDef TxHeader;TxHeader.StdId = msgID;			//stdIDTxHeader.RTR = frameType;		//数据帧,CAN_RTR_DATATxHeader.IDE = CAN_ID_STD;		//标准格式TxHeader.DLC =4;   				//数据长度TxHeader.TransmitGlobalTime = DISABLE;uint32_t rand;HAL_RNG_GenerateRandomNumber(&hrng, &rand);	//产生32位随机数uint8_t TxData[8];				//最多8个字节TxData[3] = rand & 0x000000FF;TxData[2] = (rand & 0x0000FF00)>>8;TxData[1] = (rand & 0x00FF0000)>>16;TxData[0] = (rand & 0xFF000000)>>24;while(HAL_CAN_GetTxMailboxesFreeLevel(&hcan1) < 1) {} //等待有可用的发送邮箱printf("Send MsgID= %X\r\n",msgID);uint32_t TxMailbox;		//临时变量,用于返回使用的邮箱编号/* 发送到邮箱,由CAN模块负责发送到CAN总线 */if(HAL_CAN_AddTxMessage(&hcan1,&TxHeader,TxData,&TxMailbox) != HAL_OK)printf("Send to mailbox error.\r\n");
}//读取和显示FIFO0或FIFO1的消息
//参数FIFO_num是FIFO编号,CAN_RX_FIFO0或CAN_RX_FIFO1
void CAN_ReadMsg(uint32_t FIFO_num)
{CAN_RxHeaderTypeDef RxHeader;uint8_t RxData[8];	//接收数据缓存区,8个字节if(FIFO_num==CAN_RX_FIFO0){printf("Msg received by FIFO0.\r\n");if(HAL_CAN_GetRxMessage(&hcan1,CAN_RX_FIFO0,&RxHeader,RxData) != HAL_OK){printf("Read FIFO0 error.\r\n");return;}}else{printf("Msg received by FIFO1.\r\n");if(HAL_CAN_GetRxMessage(&hcan1, CAN_RX_FIFO1, &RxHeader, RxData) != HAL_OK){printf("Read FIFO1 error.\r\n");return;}}//显示接收到的消息printf("StdID= %lX\r\n",RxHeader.StdId);printf("RTR(0=Data,2=Remote)= %lX\r\n",RxHeader.RTR);printf("IDE(0=Std,4=Ext)= %lX\r\n",RxHeader.IDE);printf("FilterMatchIndex= %lX\r\n",RxHeader.FilterMatchIndex);printf("DLC(Data length)= %lX\r\n",RxHeader.DLC);for (uint8_t i=0; i<4; i++){printf("Data[0]= %X\r\n",RxData[0]);printf("Data[1]= %X\r\n",RxData[1]);printf("Data[2]= %X\r\n",RxData[2]);printf("Data[3]= %X\r\n",RxData[3]);}printf("** Reselect menu or reset **\r\n");
}
//FIFO0接收到新消息事件中断回调函数
void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan)
{CAN_ReadMsg(CAN_RX_FIFO0);
}//FIFO1接收到新消息事件中断回调函数
void HAL_CAN_RxFifo1MsgPendingCallback(CAN_HandleTypeDef *hcan)
{CAN_ReadMsg(CAN_RX_FIFO1);
}
/* USER CODE END 1 */

(1)CAN1中断初始化

        函数MX_CAN1_Init()的代码与参考文章1完全相同,函数HAL_CAN_MspInit()中与参考文章1比较,增加了两个中断的初始化设置,开启了CAN1_RX0和CAN1_RX1中断:

    /* CAN1 interrupt Init */HAL_NVIC_SetPriority(CAN1_RX0_IRQn, 1, 0);HAL_NVIC_EnableIRQ(CAN1_RX0_IRQn);HAL_NVIC_SetPriority(CAN1_RX1_IRQn, 1, 0);HAL_NVIC_EnableIRQ(CAN1_RX1_IRQn);

(2)RNG初始化和随机数产生

        RNG是MCU的一个内部单元,其初始化很简单,就是定义了RNG模块的外设对象变量,开启其时钟。相关代码如下:

#include "rng.h"
RNG_HandleTypeDef hrng;void MX_RNG_Init(void)
{hrng.Instance = RNG;if (HAL_RNG_Init(&hrng) != HAL_OK){Error_Handler();}
}void HAL_RNG_MspInit(RNG_HandleTypeDef* rngHandle)
{if(rngHandle->Instance==RNG){/* RNG clock enable */__HAL_RCC_RNG_CLK_ENABLE();}
}void HAL_RNG_MspDeInit(RNG_HandleTypeDef* rngHandle)
{if(rngHandle->Instance==RNG){/* Peripheral clock disable */__HAL_RCC_RNG_CLK_DISABLE();}
}

         可以使用轮询方式或中断方式产生32位的随机数,分别对应两个函数。

HAL_RNG_GenerateRandomNumber()    //轮询方式产生随机数。
HAL_RNG_GetRandomNumber_IT()      //中断方式产生随机数。

        HAL_RNG_GenerateRandomNumber()的函数原型如下:

HAL_StatusTypeDef HAL_RNG_GenerateRandomNumber(RNG_HandleTypeDef *hrng,uint32_t*random32bit)

        RNG由时钟树中的时钟信号由PCLK1 42MHz驱动,典型值是42MHz,这个时钟频率不能太低,在本例中,这个时钟频率是42MHz。产生两个连续随机数的最小间隔是42个PLL42CLK周期。

(3) 筛选器组设置

        在文件can.h中,自定义的函数CAN_SetFilters()用于对FIFO0和FIFO1进行筛选器设置。详细代码在can.c中实现。

        为FIFO0设置的筛选器是只接收标识符ID为奇数的消息,为FIFO1设置的筛选器是可以接收任何消息。注意,可以为一个FIFO设置多个筛选器,但是一个筛选器只能用于一个FIFO,所以,这两个筛选器的FilterBank必须不同。结构体CAN_FilterTypeDef各成员变量的意义以及筛选器的设置原理详见参考文章1。

(4)发送消息

        在main.c中调用函数CAN_SendMsg()发送数据帧,这个自定义函数的实现代码与参考文章1不同,并在can.c中实现这个函数的代码。

        在其实现的程序中还调用函数HAL_RNG_GenerateRandomNumber(),产生一个32位随机数,然后分解为4字节存入发送数据缓冲区。程序仍然是用函数HAL_CAN_AddTxMessage()将需要发送的消息写入发送邮箱,由CAN模块自动将消息发送到CAN总线上。函数CAN_SendMsg()只管发送消息,接收消息由中断去处理。

(5)中断方式接收消息

        由于开启了CAN1的RX0中断和RX1中断,在文件stm32f4xx_it.c中自动生成了这两个中断的ISR框架。

        CAN1_RX0是FIFO0接收消息、满或上溢时产生的中断,接收消息中断事件对应的回调函数是HAL_CAN_RxFifo0MsgPendingCallback()。同样的,FIFO1接收消息中断事件对应的回调函数是HAL_CAN_RxFifo1MsgPendingCallback()。CAN1_RX0和CAN1_RX1中断事件与回调函数的对应关系详见参考文章1。所以,要使用中断方式处理FIFO0和FIFO1接收的消息,只需重新实现这两个回调函数即可。在文件can.c中重新实现这两个回调函数。

//FIFO0接收到新消息事件中断回调函数
void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan)
{CAN_ReadMsg(CAN_RX_FIFO0);
}//FIFO1接收到新消息事件中断回调函数
void HAL_CAN_RxFifo1MsgPendingCallback(CAN_HandleTypeDef *hcan)
{CAN_ReadMsg(CAN_RX_FIFO1);
}

        两个回调函数都调用了同一个函数CAN_ReadMsg(),只是传递了相应的FIFO编号。函数CAN_ReadMsg()负责读取FIFO0或FIFO1的消息并显示。读取FIFO里面收到的消息仍然使用函数HAL_CAN_GetRxMessage(),消息头结构体CAN_RxHeaderTypeDef的意义见参考文章1。这里显示了一个成员变量FilterMatchIndex的值,这是接收消息的FIFO内接收了消息的筛选器的序号,是在一个FIFO内的筛选器的序号,而不是筛选器的FilterBank属性值。

4、main.c

/* USER CODE BEGIN Includes */
#include "keyled.h"
#include <stdio.h>
/* USER CODE END Includes */
/* USER CODE BEGIN 2 */printf("Demo18_2_CAN:CAN Interrupt.\r\n");printf("Test mode:Loopback.\r\n");if (CAN_SetFilters() == HAL_OK)   	//设置筛选器printf("ID Filter: Only Odd IDs.\r\n");if (HAL_CAN_Start(&hcan1) == HAL_OK)  //启动CAN1模块printf("CAN is started.\r\n");printf("[S2]KeyUp  = Send a Data Frame.\r\n");//必须开启FIFO接收到消息中断事件,否则不会响应中断事件__HAL_CAN_ENABLE_IT(&hcan1, CAN_IT_RX_FIFO0_MSG_PENDING);__HAL_CAN_ENABLE_IT(&hcan1, CAN_IT_RX_FIFO1_MSG_PENDING);//HAL_CAN_ActivateNotification(&hcan1, CAN_IT_RX_FIFO0_MSG_PENDING);//HAL_CAN_ActivateNotification(&hcan1, CAN_IT_RX_FIFO1_MSG_PENDING);// MCU output low level LED light is onLED1_OFF();/* USER CODE END 2 */

        在外设初始化部分,函数MX_RNG_Init()用于RNG的初始化,函数MX_CAN1_Init()用于CAN1模块的初始化。

        函数CAN_SetFilters()用于设置FIFO0和FIFO1的筛选器组,与参考文章1的同名函数代码不同。这里要使用中断方式进行消息接收,还需要开启FIFO0和FIFO1的接收新消息的中断事件,即

__HAL_CAN_ENABLE_IT(&hcan1,CAN_IT_RX_FIFO0_MSG_PENDING);
__HAL_CAN_ENABLE_IT(&hcan1,CAN_IT_RX_FIFO1_MSG_PENDING);

        其中的两个宏分别是FIFO0和FIFO1接收新消息的中断事件使能控制位的宏定义,也作为中断事件类型宏定义,详见参考文章2。

        主程序的while()循环中调用自定义函数CAN_SendMsg()以轮询方式发送一个数据帧,接收数据帧在中断里处理。

  /* USER CODE BEGIN WHILE */uint8_t msgID=1;while (1){/* USER CODE END WHILE *//* USER CODE BEGIN 3 */KEYS curKey = ScanPressedKey(KEY_WAIT_ALWAYS);if (curKey==KEY_UP){CAN_SendMsg(msgID++, CAN_RTR_DATA);LED1_ON();}elseLED1_OFF();HAL_Delay(500);	//延时,消除按键抖动}/* USER CODE END 3 */
/* USER CODE BEGIN 4 */
//串口打印
int __io_putchar(int ch)
{HAL_UART_Transmit(&huart6,(uint8_t*)&ch,1,0xFFFF);return ch;
}
/* USER CODE END 4 */

三、下载与运行

        下载后在串口助手上先显示菜单,或者按下S6复位键也显示菜单。

        每次按下KeyUp键可以发送一个标准格式数据帧,msgID加1,msgID作为数据帧的标识符ID。

        运行时会发现,msgID为奇数时,是由FIFO0接收消息,msgID为偶数时,是由FIFO1接收消息。因为在设置筛选器组时,设置FIFO0只能接收标识符ID为奇数的消息,FIFO1可以接收任意标识符ID的消息。当标识符ID为偶数时,只能由FIFO1接收,当标识符ID为奇数时,两个FIFO都可以接收,但是由FIFO0优先接收。

        不管是哪个FIFO接收的消息,显示的FilterMatchIndex的值都是0,因为它们都只有一个筛选器。

 

http://www.dt0577.cn/news/41037.html

相关文章:

  • 上海做设计公司网站微信seo
  • 漂亮网站seo优化外链平台
  • 网站广东省备案系统市场营销推广策划
  • 网站的建设与管理广告投放数据分析
  • 网站测试的必要性网站流量统计分析的维度包括
  • 永康哪有做网站的公司网络优化工程师吃香吗
  • 秦皇岛网站定制哪家好搜索引擎网站优化和推广方案
  • 合肥建设网络赌博网站百度ai搜索引擎
  • 个人网站用主机做服务器品牌网站设计
  • 备案期间网站要关闭吗app推广接单平台
  • 河北省住房和城市建设厅网站新东方在线教育平台官网
  • 企业网站建设制作多少钱引擎网站推广法
  • wordpress图片多北京seo主管
  • 宿松网站建设公司小学生一分钟新闻播报
  • icp网站备案号查询今日头条新闻军事
  • 湖南医院响应式网站建设企业河北关键词seo排名
  • 找百度做的网站可以过户怎样在百度上发布作品
  • 关于内网站建设的请示成都百度推广
  • 哈尔滨快速建站专业定制北京seo优化外包
  • 互动力 网站建设百度客服24小时人工电话
  • 怎么在百度做网站种子搜索在线 引擎
  • 含山县查询建设工程的网站百度app首页
  • 宝鸡手机网站开发seo关键词优化指南
  • 做数据表格的网站seo销售代表招聘
  • 软件开发一个月多少钱嘉兴新站seo外包
  • 什么网站做禽苗好的网站正安县网站seo优化排名
  • 用wordpress复制一个网站百度代理服务器
  • php框架做网站广州网络推广
  • 和嗲囡囡和做的网站无锡百度竞价推广
  • 做线上网站需要钱吗网络推广有效果吗