软件STM32cubeIDE下使用STM32F4xx配置uart4+DMA接收数据+空闲串口函数-基础样例

前言

继续之前的测试,在之前的代码上,增加新的函数,实现接收数据功能

环境

软件环境: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

生成海报
点赞 0

好奇龙猫

我还没有学会写个人说明!

暂无评论

发表评论

相关推荐

STM32学习笔记2

GPIO GPIO:General Purpose Input & Output 是通用输入输出端口的简称,简单来说就是软件可控制的引脚, STM32芯片的GPIO引脚与外部设备连接起来,从而实现与外部通讯、控制以

stm32f407用oled实时显示日期和时间

这里我用的rtc时钟是非常好用的,先借鉴一下正点原子的理论知识。 STM32F4 的 RTC,是一个独立的 BCD 定时器/计数器。RTC 提供一个日历时钟(包含年月日时分秒信息)、两个