野火电子论坛

 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 20660|回复: 10

STM32F103 串口DMA 请教

[复制链接]
发表于 2021-9-6 10:42:10 | 显示全部楼层 |阅读模式
在STM32F103 DMA串口接收中,关于串口的接收配置是 这样的
  1. /**
  2.   * [url=home.php?mod=space&uid=41770]@brief[/url]  USART GPIO 配置,工作参数配置
  3.   * @param  无
  4.   * @retval 无
  5.   */
  6. void USART_Config(void)
  7. {
  8.         GPIO_InitTypeDef GPIO_InitStructure;
  9.         USART_InitTypeDef USART_InitStructure;
  10.     NVIC_InitTypeDef NVIC_InitStruct;
  11.         // 打开串口GPIO的时钟
  12.         DEBUG_USART_GPIO_APBxClkCmd(DEBUG_USART_GPIO_CLK, ENABLE);
  13.        
  14.         // 打开串口外设的时钟
  15.         DEBUG_USART_APBxClkCmd(DEBUG_USART_CLK, ENABLE);
  16.        
  17.         NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
  18.         NVIC_InitStruct.NVIC_IRQChannel = DEBUG_USART_IRQ;
  19.         NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
  20.         NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 1;
  21.         NVIC_InitStruct.NVIC_IRQChannelSubPriority = 3;
  22.         NVIC_Init(&NVIC_InitStruct);

  23.         // 将USART Tx的GPIO配置为推挽复用模式
  24.         GPIO_InitStructure.GPIO_Pin = DEBUG_USART_TX_GPIO_PIN;
  25.         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
  26.         GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  27.         GPIO_Init(DEBUG_USART_TX_GPIO_PORT, &GPIO_InitStructure);

  28.   // 将USART Rx的GPIO配置为浮空输入模式
  29.         GPIO_InitStructure.GPIO_Pin = DEBUG_USART_RX_GPIO_PIN;
  30.         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
  31.         GPIO_Init(DEBUG_USART_RX_GPIO_PORT, &GPIO_InitStructure);
  32.        
  33.         // 配置串口的工作参数
  34.         // 配置波特率
  35.         USART_InitStructure.USART_BaudRate = DEBUG_USART_BAUDRATE;
  36.         // 配置 针数据字长
  37.         USART_InitStructure.USART_WordLength = USART_WordLength_8b;
  38.         // 配置停止位
  39.         USART_InitStructure.USART_StopBits = USART_StopBits_1;
  40.         // 配置校验位
  41.         USART_InitStructure.USART_Parity = USART_Parity_No ;
  42.         // 配置硬件流控制
  43.         USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
  44.         // 配置工作模式,收发一起
  45.         USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
  46.         // 完成串口的初始化配置
  47.         USART_Init(DEBUG_USARTx, &USART_InitStructure);       
  48.         //使能空闲中断
  49.         USART_ITConfig(DEBUG_USARTx,USART_IT_IDLE,ENABLE);
  50.         // 使能串口
  51.         USART_Cmd(DEBUG_USARTx, ENABLE);            
  52. }
复制代码
这上面的关键是开启了串口接收 空闲中断

  1. /**
  2.   * @brief  串口空闲中断.
  3.   * @param  无
  4.   * @retval 无
  5.   */
  6. void DEBUG_USART_IRQHandler(void)
  7. {
  8.         uint16_t t;
  9.         if(USART_GetITStatus(DEBUG_USARTx,USART_IT_IDLE) == SET)          //检查中断是否发生
  10.         {       
  11.                 DMA_Cmd(USART_TX_DMA_CHANNEL,DISABLE);                         //关闭DMA传输

  12.                 t = DMA_GetCurrDataCounter(USART_TX_DMA_CHANNEL);              //获取剩余的数据数量
  13.                
  14.         Usart_SendArray(DEBUG_USARTx,ReceiveBuff,RECEIVEBUFF_SIZE-t);       //向电脑返回数据(接收数据数量 = SENDBUFF_SIZE - 剩余未传输的数据数量)
  15.                
  16.                 DMA_SetCurrDataCounter(USART_TX_DMA_CHANNEL,RECEIVEBUFF_SIZE);    //重新设置传输的数据数量

  17.                 DMA_Cmd(USART_TX_DMA_CHANNEL,ENABLE);                          //开启DMA传输
  18.                
  19.                 USART_ReceiveData(DEBUG_USARTx);                              //读取一次数据,不然会一直进中断
  20.                 USART_ClearFlag(DEBUG_USARTx,USART_FLAG_IDLE);                //清除串口空闲中断标志位
  21.         }
  22.        
  23. }
复制代码
串口接收空闲中断是这样写的
这里有的疑问是,如果同时有多个中断来了,那么是不是就无法响应串口接收空闲中断了?在这里只是说如果有串口接收空闲中断,才通过DMA的方式读取一次数据,如果不进中断是不是不能读取了?这样的话,和通过串口中断读取数据有什么区别吗 ?
回复

使用道具 举报

 楼主| 发表于 2021-9-6 12:34:54 | 显示全部楼层
如果被别的中断抢了,是不是就没法通过DMA读取数据了呢?
回复 支持 反对

使用道具 举报

发表于 2021-9-6 14:04:00 | 显示全部楼层
这个要多参考F1编程手册,还有你自己的中断优先级的设置
回复 支持 反对

使用道具 举报

发表于 2021-9-6 14:39:05 | 显示全部楼层
你可以在中断的时候只设置一个标志位,然后在主程序中再去读取数据。
回复 支持 反对

使用道具 举报

发表于 2021-9-9 20:39:10 | 显示全部楼层
空闲中断是,假设现在无中断了,那么我将dma中的数据就拿来了
回复 支持 反对

使用道具 举报

 楼主| 发表于 2021-9-10 14:08:37 | 显示全部楼层
ID-fHtdZc 发表于 2021-9-6 14:04
这个要多参考F1编程手册,还有你自己的中断优先级的设置

这么说没用啊,如果通过中断的话,那其他优先级高的中断就把这个中断打断了,也就不会进空闲中断了
回复 支持 反对

使用道具 举报

 楼主| 发表于 2021-9-10 14:09:34 | 显示全部楼层
ZERO_ 发表于 2021-9-9 20:39
空闲中断是,假设现在无中断了,那么我将dma中的数据就拿来了

你说错了吧,空闲中断是串口接收中断结束后产生的,如果连串口接收中断都进不去何谈空闲中断
回复 支持 反对

使用道具 举报

 楼主| 发表于 2021-9-10 14:10:02 | 显示全部楼层
hansome 发表于 2021-9-6 14:39
你可以在中断的时候只设置一个标志位,然后在主程序中再去读取数据。

那现在的问题就是,中断都进不去了
回复 支持 反对

使用道具 举报

发表于 2021-9-11 09:15:27 | 显示全部楼层
中断应该不会无法响应的吧,除非中断优先级影响到了。
我的理解是,空闲中断+DMA的方式里面,空闲中断只是用来响应一帧数据接收结束,产生了空闲中断就说明接收完一帧数据,可以开始处理数据或者准备接收下一帧
数据接收过程不需要程序去读取,因为DMA会把usart->DR里的内容搬到程序定义的缓冲区内
回复 支持 反对

使用道具 举报

 楼主| 发表于 2021-9-13 07:20:05 | 显示全部楼层
瞎眼灯 发表于 2021-9-11 09:15
中断应该不会无法响应的吧,除非中断优先级影响到了。
我的理解是,空闲中断+DMA的方式里面,空闲中断只是 ...

因为没有了中断,所以什么时候才能知道接收到了数据呢?
回复 支持 反对

使用道具 举报

发表于 2021-9-14 18:02:58 | 显示全部楼层
黄河入海流 发表于 2021-9-13 07:20
因为没有了中断,所以什么时候才能知道接收到了数据呢?

就是靠空闲中断去识别的,如果没有空闲中断产生就说明没跑起来或者不正常
可以检查下串口IO和DMA的初始化配置、然后检查下PCB上的晶振大小和程序预定义的HSE大小是不是对应的,这个会影响实际的串口波特率导致串口通信不正常
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

联系站长|手机版|野火电子官网|野火淘宝店铺|野火电子论坛 ( 粤ICP备14069197号 ) 大学生ARM嵌入式2群

GMT+8, 2024-11-24 12:25 , Processed in 0.041918 second(s), 23 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表