前言
继续之前的测试,在之前的代码上,增加新的函数,实现接收数据功能
环境
软件环境:STM32cubeIDE 1.7.0
硬件环境:正点原子探索者开发板-STM32F407ZGT6
HAL库版本:stm32cube_fw_f4_v1262
了解知识点(学习思路)
(1)空闲函数中断,解决效率接收问题,就是收的时候,有时候可能不定长,那么当有数据过来的时候进行接收,收完等一段时间,还没数据继续来,进入中断处理回调。
串口空闲中断,对应事件标志为IDLE
检测到空闲线路时,该位由硬件置 1。如果 USART_CR1 寄存器中 IDLEIE = 1,则会生成中断
该位由软件序列清零(读入 USART_SR 寄存器,然后读入 USART_DR 寄存器)
利用串口空闲中断,可以用如下流程实现DMA控制的任意长数据接收:
原文链接:https://blog.csdn.net/wxc971231/article/details/83044189
https://blog.csdn.net/xuzhexing/article/details/107926788
(2)回调函数,中断函数会自动调用的函数,相应的我们需要实现相应功能。
void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart);//发送完成回调函数
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart);//接收完成回调函数
void USAR_UART_IDLECallback(UART_HandleTypeDef *huart);//空闲中断回到函数
void USER_UART_IRQHandler(UART_HandleTypeDef *huart); //串口中断服务函数
void UART4_IRQHandler(void);串口中断函数
测试细节
(1)有关配置细节可以查看之前文章,本文也是在此基础上继续实验的。
软件STM32cubeIDE下使用STM32F4xx配置uart4+DMA发送数据到串口助手-基础样例
(2)使能接收中断方式“空闲中断”与设定接收到存下的数组
并且我们可以通过__HAL_UART_ENABLE_IT函数查看一共可以使用哪几种中断
/** @brief Enable the specified UART interrupt.
* @param __HANDLE__ specifies the UART Handle.
* UART Handle selects the USARTx or UARTy peripheral
* (USART,UART availability and x,y values depending on device).
* @param __INTERRUPT__ specifies the UART interrupt source to enable.
* This parameter can be one of the following values:
* @arg UART_IT_CTS: CTS change interrupt
* @arg UART_IT_LBD: LIN Break detection interrupt
* @arg UART_IT_TXE: Transmit Data Register empty interrupt
* @arg UART_IT_TC: Transmission complete interrupt
* @arg UART_IT_RXNE: Receive Data register not empty interrupt
* @arg UART_IT_IDLE: Idle line detection interrupt
* @arg UART_IT_PE: Parity Error interrupt
* @arg UART_IT_ERR: Error interrupt(Frame error, noise error, overrun error)
* @retval None
*/
//以下为翻译内容
/** @brief启用指定的UART中断。
* @param __HANDLE__指定UART句柄。
* UART句柄选择USARTx或UARTy外设
* (USART,UART可用性和x,y值取决于设备)。
* @param __INTERRUPT__指定要启用的UART中断源。
*该参数可以为以下值之一:
* UART_IT_CTS: CTS更改中断
* UART_IT_LBD: LIN中断检测中断
* UART_IT_TXE:发送数据寄存器空中断
* UART_IT_TC:传输完全中断
* UART_IT_RXNE:接收数据寄存器不是空中断
* UART_IT_IDLE:空闲线路检测中断
* UART_IT_ERR:奇偶校验中断
* arguart_it_err:错误中断(帧错误,噪声错误,溢出错误)
*/
#define __HAL_UART_ENABLE_IT(__HANDLE__, __INTERRUPT__) ((((__INTERRUPT__) >> 28U) == UART_CR1_REG_INDEX)? ((__HANDLE__)->Instance->CR1 |= ((__INTERRUPT__) & UART_IT_MASK)): \
(((__INTERRUPT__) >> 28U) == UART_CR2_REG_INDEX)? ((__HANDLE__)->Instance->CR2 |= ((__INTERRUPT__) & UART_IT_MASK)): \
((__HANDLE__)->Instance->CR3 |= ((__INTERRUPT__) & UART_IT_MASK)))
(3)回调函数是要实现的功能 需要我们自己实现,因为使用F4开发板,如下是回调函数部分,另外需要关注中断函数,如下图,第一个HAL_UART_TxCpltCallback是每次发送成功回调,第二个HAL_UART_RxCpltCallback因为使用了空闲中断,那么回调的是空闲中断函数,不会自动回调到这里。
既然是回调,或者说检验回调的一个方法就是,HAL库会为我们“虚写”一个函数名相同的函数等我们重写,比如HAL_UART_RxCpltCallback函数,在下面Search中可以看到到在文件stm32f4xx_hal_uart.c中也有个一。
中断服务函数也要注意加上。如果不分文件它在如下文件下。分文件需要找下。
(4)回调函数具体内容测试如下,测试发现在接收接收回到”USAR_UART_IDLECallback“函数内 ,如果将接收数据直接通过DMA函数HAL_UART_Transmit_DMA方式直接发送。
1)发送固定数据没问题,可以发出去,串口助手能收到 2)如果发送收到数据,会有数据不全问题
改变发送函数,阻塞方式HAL_UART_Transmit发送可以发送(虽然成功了),但是理论上,中断内尽量不用延时较高的方式发送,就是中断
/* USER CODE BEGIN 0 */
void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)//发送完成回调函数
{
HAL_GPIO_TogglePin(GPIOF, GPIO_PIN_9);
}
//在暂时没用上,采用DMA空闲串口中断模式 貌似不会回调到这里
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)//接收完成回调函数
{
// HAL_GPIO_TogglePin(GPIOF, GPIO_PIN_10);
}
/* USER CODE END 0 */
void USAR_UART_IDLECallback(UART_HandleTypeDef *huart)
{
//(1)
HAL_UART_DMAStop(&huart4); //停止本次DMA传输 需要使用DMA发送则需要关掉 如果使用的阻塞方式HAL_UART_Transmit发送请使用本行
//(2)
//uint8_t data_length = __HAL_DMA_GET_COUNTER(&hdma_uart4_rx); //计算接收到的数据长度
// printf("Receive Data(length = %d): ",data_length);
//(3)测试发现 不发指定数据没有问题
// HAL_UART_Transmit_DMA(&huart4,(uint8_t*)"hello world!!",13); //测试函数:将接收到的数据打印出去 DMA模式下请不要停止,别使用函数HAL_UART_DMAStop(&huart4);
//(4)如果发收到数据,会有缺失情况
// HAL_UART_Transmit_DMA(&huart4,UART4_ReceBuf,UART4_Buf_LEN); //测试函数:将接收到的数据打印出去 DMA模式下请不要停止,别使用函数HAL_UART_DMAStop(&huart4);
//(5)收到数据后阻塞发出
HAL_UART_Transmit(&huart4,(uint8_t*)UART4_ReceBuf,UART4_Buf_LEN,0x200);//阻塞方式发送 使用时需要关闭DMA模式 阻塞发送没有问题,收啥 发啥
printf("\r\n"); //就是HAL_UART_Transmit 发送函数, 只不过在下班映射了。
// HAL_Delay(10);
memset(UART4_ReceBuf,0,UART4_Buf_LEN); //清零接收缓冲区
// data_length = 0;
HAL_UART_Receive_DMA(&huart4, (uint8_t*)UART4_ReceBuf, UART4_Buf_LEN); //重启开始DMA传输 每次255字节数据
//原子F4开发板点灯,看看跑没跑到着
HAL_GPIO_TogglePin(GPIOF, GPIO_PIN_10);
}
void USER_UART_IRQHandler(UART_HandleTypeDef *huart)
{
if( huart->Instance == UART4)
{
if(RESET != __HAL_UART_GET_FLAG(&huart4, UART_FLAG_IDLE)) //判断是否是空闲中断
{
__HAL_UART_CLEAR_IDLEFLAG(&huart4); //清楚空闲中断标志(否则会一直不断进入中断)
printf("\r\nUART4 Idle IQR Detected\r\n");
USAR_UART_IDLECallback(huart); //调用中断处理函数
}
}
}
代码链接
https://download.csdn.net/download/qq_22146161/68947909
总结
学习之路,魔鬼在细节中,任重道远吧~~
版权声明:本文为CSDN博主「好奇龙猫」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_22146161/article/details/122094860
暂无评论