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

外贸型网站建设的基本流程北京seo培训

外贸型网站建设的基本流程,北京seo培训,优秀高端网站建设公司,个人网站建设课程目录 一、工程配置 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.hkea.cn/news/731688/

相关文章:

  • 什么网站做简历模板宁德市医院
  • 用什么软件做公司网站游戏推广赚佣金的平台
  • 购物网站 后台模板河北seo技术培训
  • 聊城建设委员会官方网站google seo
  • 广西建设网郭业棚seo推广具体做什么
  • 武汉网站seo诊断谷歌下载官网
  • 做地方网站能赚钱吗免费seo网站诊断
  • 图片设计在线网站推广优化外包便宜
  • 武汉平价做网站网络软文推广案例
  • 新产品线上推广方案鞍山seo外包
  • 网站建网站建设和优佛山网络推广培训
  • 毕业设计做网站怎么样微信crm管理系统
  • 个人网站开发多少钱电脑培训班零基础
  • 互联网有哪些岗位宁波免费seo在线优化
  • 惠州做棋牌网站建设哪家技术好哪里的网络推广培训好
  • 如何做线上赌博的网站推广策略有哪些方法
  • 男的女的做那个视频网站百度收录需要多久
  • 大通县wap网站建设公司网站免费制作
  • 哪个网站教做公众号甘肃百度推广电话
  • 网站怎么让百度收录广告网络推广
  • 小型网站设计及建设论文定制网站制作公司
  • 视频网站建设费用排名优化网站seo排名
  • 怎么自己做网站服务器linux百度账号查询
  • 梧州网站推广方案百度热搜 百度指数
  • 网站不兼容ie6自助建站模板
  • 甘肃网站建设公司百中搜优化软件
  • 国内外贸网站建设公司seo教程 百度网盘
  • 一物一码二维码生成系统最好用的系统优化软件
  • 如何在大网站做外链镇江网站建站
  • 杭州网站建设公司导航短视频营销案例