一、来由
近来,要用到RS485转CAN2.0B协议,其中要求8ms发一级CAN包,100ms又发另一组CAN包,500ms还想让led闪烁,表示程序正常运行。因为刚用STM32F042,不熟悉,只能找些例子来看,还好,感谢网友,也算把它调试出来了。其中用“HAL_Dalay(1)”延时1ms,计数,调试用用还行,但觉得不精准,应该用定时器控制。
网上找资料,找到:《STM32 Cubemx 配置定时器定时1mS》STM32 Cubemx 配置定时器定时1mS - osc_qimlgg8v的个人空间 - OSCHINA - 中文开源技术交流社区等文,照葫芦画瓢,画到最后,画不来(程序不理解、也无法实现功能),反复琢磨,最后成功了,也就想写出来,分享给大家,以少走弯路。
照着STM32 Cubemx 配置定时器定时1mS - osc_qimlgg8v的个人空间 - OSCHINA - 中文开源技术交流社区介绍,走到最后一段,不知道怎么做了:
最后使用定时器中断跟关闭定时器中断以及回调函数即可, 使用中断的时候注意要先开启中断
HAL_TIM_Base_Start_IT(&htim1); //使用定时器的时候调用这个函数启动 HAL_TIM_Base_Stop_IT(&htim1); //停止定时器的时候调用这个函数关闭 void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) { if(htim->Instance == TIM1) { //编写回调逻辑,即定时器1定时1MS后的逻辑 } }
定时器开中断好理解,定时器关中断也好理解,就是这个回调函数怎么用,不知道,文章到此结束了,相似内容的文章也有一些,但都是到此就结束了。不知道从何下手,无奈,只好自己想办法。
二、我的方法
CubeMX定义好各种引脚、参数后会创建出工程文件来,我的RS485是中断接收的, 我也是在stm32f0xx_it.c(见下图手写“1”处)中添了几条语句实现串口中断接收的(见下图手写“2”处),stm32f0xx_it.c中也有定时器中断(我用的是定时器1)(见下图手写“3”处),每次1ms中断就让几个相关的数加1。
当然,要在stm32f0xx_it.c中把这几用到的变量名定义一下,见下图涂蓝部分。
在main.c中引用刚才定义的变量,见下图涂蓝部分
现在,这几个变量每1ms就会增加1,在while(1){ }中用几个条件语句就实现了8ms发一级CAN包,100ms又发另一组CAN包,500ms还让led闪烁。注意,必须设置语句启动定时器,否则定时器是不会的。代码如下(简化过):
nt main(void)
{
/* USER CODE BEGIN 1 */
extern unsigned char RS485RxBuffer[32]; //接收数据
extern unsigned char aRxBuffer; //接收中断缓冲
extern unsigned char Uart2_Rx_Cnt; //接收缓冲计数
extern CAN_HandleTypeDef hcan; //和初始化中的保持一致
extern WWDG_HandleTypeDef hwwdg;
extern int Led_flash,RepeatSendPri,RepeatSendSec;
HAL_Init();
SystemClock_Config();
// CAN_HandleTypeDef hcan;
HAL_StatusTypeDef HAL_RetVal;
CAN_TxHeaderTypeDef Can_Tx;
CAN_RxHeaderTypeDef Can_Rx;
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_ADC_Init();
MX_CRC_Init();
MX_TIM1_Init();
MX_CAN_Init();
MX_USART2_UART_Init();
MX_WWDG_Init();
/* USER CODE BEGIN 2 */
__HAL_TIM_CLEAR_IT(&htim1 ,TIM_IT_UPDATE ); //清除TIM1中断挂起
HAL_TIM_Base_Start_IT(&htim1 ); //启动定时器TIM1中断
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
//以下初始数据准备
Uart2_Rx_Cnt = 0;
RepeatSendPri=0;
RepeatSendSec =0;
Led_flash = 0;
while (1)
{
HAL_WWDG_Refresh(&hwwdg); //复位看门狗
//定时器1ms中断计时(计数)
//以下每8ms发一组数据,CAN ID=0x0A发送
if(RepeatSendPri >= 8)
{
RepeatSendPri = 0 ; //置0,重新开始
//发之前先查询一下 邮箱是否满了,满了就等一下再发
while(HAL_CAN_GetTxMailboxesFreeLevel(&hcan) == 0 );
//向 Tx 邮箱中增加一个消息,并且激活对应的传输请求
HAL_RetVal = HAL_CAN_AddTxMessage(&hcan,&Can_Tx,CanTxdataPri,&pTxMailbox); //CAN ID=0x0A发送
}
//以下每100ms发一组数据,CAN ID=0x0B发送
if(RepeatSendSec >= 100)
{
RepeatSendSec =0; //置0,重新开始
//发之前先查询一下 邮箱是否满了,满了就等一下再发
while(HAL_CAN_GetTxMailboxesFreeLevel(&hcan) == 0 );
//向 Tx 邮箱中增加一个消息,并且激活对应的传输请求
HAL_RetVal = HAL_CAN_AddTxMessage(&hcan,&Can_Tx,CanTxdataSec,&pTxMailbox); //CAN ID=0x0B发送
}
//以下用于指示程序在运行,LED亮或灭中
if(Led_flash >=500)
{
Led_flash = 0; //置0,重新开始
LedFlash(); //使LED亮或灭,指示程序在运行
}
}
}
三、小结
感谢网友STM32 Cubemx 配置定时器定时1mS - osc_qimlgg8v的个人空间 - OSCHINA - 中文开源技术交流社区的分享,依照他的cubeMX配置是可行的,只是最后一段我不会用,改成了自己的,我也分享给用得着的朋友。