完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
1、前言
HAL即硬件抽象层(英语:Hardware Abstraction Layer),实现了不同硬件的统一接口操作。这就极大的简化了程序员的移植工作,搭配STM32CubeMX,使用起来非常方便。 2、回调函数 HAL库使用了很多的回调机制,这样写能够更好的实现程序的分层处理,不影响程序的主体框架,方便后期修改移植。 3、HAL库中断接收函数使用 使用HAL_UART_Receive_IT函数前,需要使能串口的接收中断,并配置中断优先级。 /* Peripheral clock enable */ __HAL_RCC_USART2_CLK_ENABLE(); __HAL_RCC_GPIOA_CLK_ENABLE(); /**USART2 GPIO Configuration PA2 ------》 USART2_TX PA3 ------》 USART2_RX */ GPIO_InitStruct.Pin = GPIO_PIN_2|GPIO_PIN_3; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; GPIO_InitStruct.Alternate = GPIO_AF4_USART2; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); /* USART2 interrupt Init */ HAL_NVIC_SetPriority(USART2_IRQn, 1, 1); HAL_NVIC_EnableIRQ(USART2_IRQn); 在对应的串口中断函数中需要对应的中断处理 void USART2_IRQHandler(void) { /* USER CODE BEGIN USART2_IRQn 0 */ /* USER CODE END USART2_IRQn 0 */ HAL_UART_IRQHandler(&huart2); /* USER CODE BEGIN USART2_IRQn 1 */ /* USER CODE END USART2_IRQn 1 */ } 这时就可以使用 HAL_StatusTypeDef HAL_UART_Receive_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size) 函数接收了,该函数会打开接收中断接收数据,函数的第一个参数指定接收串口的结构体指针,第二个参数为接收数据指针,第三个参数为接收数据长度。该函数没有超时机制,必须要指定接收的数据长度,在数据没有达到接收长度时该函数会一直阻塞,这就要求接收的数据长度必须为已知,在接收不定长度数据时会不适用。 在使用串口接收Modbus-RTU数据时,需要接收不定长的数据帧,并且要求非阻塞接收。像在标准库中接收数据一样,这里可以通过HAL_UART_Receive_IT接收单个字节的数据,在接收回调函数中加入超时处理即可完成一帧数据的接收。接收流程如下: //数据接收结构体 struct M_Rev{ uint8_t revcnt; //接收计数 uint8_t revact; //开始标志 uint8_t oldcnt; //上次计数 uint32_t revtick; //接收计时 uint8_t revbuff[MODBUS_MAX_LEN]; //接收缓存 }Modbus_Rev; //接收回调函数 void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) { if(huart-》Instance == USART2) //判断串口 { if(Modbus_Rev.revcnt == 0) //帧第一个数据 { if(Modbus_Rev.revact == 1) //首次接收 { Modbus_Rev.revact = 2; } else //非首次接收 { Modbus_Rev.revbuff[0] = Modbus_Rev.revbuff[Modbus_Rev.oldcnt]; //上一次接收数据位置 } HAL_TIM_Base_Start_IT(&htim2); //开启定时器 HAL_GPIO_WritePin(GPIOB, GPIO_PIN_7, GPIO_PIN_SET); //开启指示灯 } Modbus_Rev.revcnt += 1; //接收计数 if(Modbus_Rev.revcnt 》= MODBUS_MAX_LEN) Modbus_Rev.revcnt = MODBUS_MAX_LEN - 1; Modbus_Rev.revtick = 0; //计时清0 HAL_UART_Receive_IT(huart, &(Modbus_Rev.revbuff[Modbus_Rev.revcnt]), 1); //接收下一次数据 } } //定时器回调函数 void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) { Modbus_Rev.revtick += 1; //计时增长 if(Modbus_Rev.revtick 》 MAX_TIM_CNT) //定时器溢出 { Modbus_Rev.revtick =0; //计时清0 } if(Modbus_Rev.revtick 》= MODBUS_T35) //接收超时 { if(Modbus_Rev.revact == 2) //首次接收 { Modbus_Rev.revact = 0; //关闭首次接收 } Modbus_ReciveData(Modbus_Rev.revbuff,Modbus_Rev.revcnt); //完成一帧接收,处理 Modbus_Rev.oldcnt = Modbus_Rev.revcnt; //保存接受位置 Modbus_Rev.revcnt = 0; //接收计数清0 HAL_TIM_Base_Stop_IT(&htim2); //关闭定时器 HAL_GPIO_WritePin(GPIOB, GPIO_PIN_7, GPIO_PIN_RESET); //关闭指示灯 } } 其中要注意的一点是,在第二帧接收时,由于接收的地址是上一帧的接收位置 + 1所以需要保存其位置,将其数值赋值到这一帧的第一个字节即可。 |
|
|
|
只有小组成员才能发言,加入小组>>
调试STM32H750的FMC总线读写PSRAM遇到的问题求解?
1781 浏览 1 评论
X-NUCLEO-IHM08M1板文档中输出电流为15Arms,15Arms是怎么得出来的呢?
1621 浏览 1 评论
1085 浏览 2 评论
STM32F030F4 HSI时钟温度测试过不去是怎么回事?
728 浏览 2 评论
ST25R3916能否对ISO15693的标签芯片进行分区域写密码?
1680 浏览 2 评论
1938浏览 9评论
STM32仿真器是选择ST-LINK还是选择J-LINK?各有什么优势啊?
732浏览 4评论
STM32F0_TIM2输出pwm2后OLED变暗或者系统重启是怎么回事?
570浏览 3评论
596浏览 3评论
stm32cubemx生成mdk-arm v4项目文件无法打开是什么原因导致的?
557浏览 3评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-12-24 11:07 , Processed in 1.718889 second(s), Total 45, Slave 40 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号