STM32F0 DMA串口接收数据

简介: STM32F0 DMA串口接收数据

4edc953e2c684bbe819ffa954c899c08.png

作者:良知犹存

转载授权以及围观->欢迎添加WxId:Allen-Iverson-me-LYN

DMA,全称Direct Memory Access,即直接存储器访问。DMA传输将数据从一个地址空间复制到另一个地址空间,提供在外设和存储器之间或者存储器和存储器之间的高速数据传输。当CPU初始化这个传输动作,传输动作本身是由DMA控制器来实现和完成的。DMA传输方式无需CPU直接控制传输,也没有中断处理方式那样保留现场和恢复现场过程,通过硬件为RAM和IO设备开辟一条直接传输数据的通道,使得CPU的效率大大提高。

主要特点:

•DMA上多达7个可独立配置的通道(请求)

•每个通道都连接到专用的硬件DMA请求,软件触发为

每个频道也都支持。该配置由软件完成。

•DMA通道的请求之间的优先级是软件可编程的(4

级别由非常高,高,中,低)或硬件组成(在相等的情况下)

(请求1的优先级高于请求2的优先级,依此类推)

•独立的源和目标传输大小(字节,半字,字),模拟

包装和拆箱。源/目标地址必须与数据对齐

尺寸。

•支持循环缓冲区管理

•3个事件标志(DMA半传输,DMA传输完成和DMA传输错误)

在每个通道的单个中断请求中进行逻辑或运算

•内存到内存的传输

•外围到内存和内存到外围,以及外围到外围

转移

•访问闪存,SRAM,APB和AHB外设作为源和目标

•可编程的数据传输数量:最多65535

DMA通道对应的外设情况(F0系列):

4edc953e2c684bbe819ffa954c899c08.png4edc953e2c684bbe819ffa954c899c08.png

   很多博文会讲解里面的详细定义,对于每一处寄存器的详细操作指导,所以我就不会去多写了。

   我只想表达,DMA是一种可以快速相关外设数据交互的一种方法,我们学习哪里用它,怎么用它,至于细节学习,大家去网上所搜DMA相信息即可。    

   之前讲过DMA的数据发送,现在补充上DMA的接收数据部分。

 利用DMA接收串口数据的配置,大致分为:1.初始化串口并开启DMAR接收功能,配置DMA的外设到内存的数据接收功能,2.等待串口中断提示,并进行处理数据,3.清空DMA,重新等待数据

01 配置串口与DMA

其中USART2->CR3寄存器的第6 bit用来设置DMA的接收配置,此处比较重要我们设置为USART_CR3_DMAR。 USART2->CR1寄存器中开启帧信息接收完成之后的中断,USART_CR1_IDLEIE,这处可以帮助我们节省CPU的不必要开支,开启此处中断类型,我们只需要在每帧信息接收完成之后,usart才触发中断,我们再解析。其余为正常的usart配置。

4edc953e2c684bbe819ffa954c899c08.png

GPIOD->MODER |=   GPIO_MODER_MODER5_1|  //USART2_TX
                  GPIO_MODER_MODER6_1;  //USART2_RX  
  /* set baudrate */
  USART2->BRR = USART_Baudrate;//115200
  USART2->CR3 |= USART_CR3_DMAT|USART_CR3_DMAR;//USART_CR3_OVRDIS;// 不需要覆写
  /*enable usart2 and enable tx*/
  USART2->CR1 |= USART_CR1_UE | USART_CR1_TE | USART_CR1_RE | USART_CR1_IDLEIE;

配置DMA:

   首先根据上方的映射表,我们初始化了usart2,而usart2 RX对应的DMA通道为DMA1 channel5,所以我们进行DMA1 ch5通道配置。

第一个为DMA1_Channel5->CPAR寄存器,在下表可知,用来设置对应接收数据的外设的地址,而USART的接收数据的寄存器为RDR,所以寄存器配置为DMA1_Channel5->CPAR = (uint32_t)&(USART2->RDR);

4edc953e2c684bbe819ffa954c899c08.png

   设置需要放数据的指定内存位置,根据指导手册可知CMAR为DMA通道用来放置数据的内存地址,所以此处设置为我们定义好的变量的地址。    4edc953e2c684bbe819ffa954c899c08.png

   设置单次传送数据量的大小,此处最大可设置为65535byte的数据大小。4edc953e2c684bbe819ffa954c899c08.png

最后开启DMA通道。4edc953e2c684bbe819ffa954c899c08.png

4edc953e2c684bbe819ffa954c899c08.png4edc953e2c684bbe819ffa954c899c08.png

void USART2_DMA_Recive(uint8_t *p_data,uint16_t length)
{
  DMA1_Channel5->CPAR = (uint32_t)&(USART2->RDR);          //Peripheral address
  DMA1_Channel5->CMAR = (uint32_t)p_data;                  //memory address
  DMA1_Channel5->CNDTR = length;                            //Set the length
  DMA1_Channel5->CCR |= DMA_CCR_MINC | DMA_CCR_EN;
}

02  等待串口中断,处理数据

4edc953e2c684bbe819ffa954c899c08.png

   此时在debug中,在我们定义好的DMA内存变量,地址在RAM初始完成,后续串口数据接收的时候,DMA会直接将数据置于p_data所对应的内存。

   然后在中断服务函数我们可以将我们数据进行处理,Uart_Channel_isr[1](USART2->RDR);,这个函数为我自己写的处理函数,中断里面函数都是数据复制,所以我直接在中断执行,一般大家会在中断写个标志,在主循环进行解析。但是DMA接收配合USART_ISR_IDLE标志在STM32平台下并不友好,如果主循环用来解析数据的时候,空闲中断还没有产生,本帧数据还尚未接收完成,但是由于内存数据已经在实时写入,DMA1_Channel5->CNDTR已经有所变化,并早于空闲中断产生,所以主循环就不能用DMA1_Channel5->CNDTR所接收数据长度进行解析了。一般建议,如果解析数据只是单纯的挪移,此时候直接在中断处理即可,对主程序并没有大的阻塞。

void USART2_IRQHandler(void)
{
  if ((USART2->ISR & USART_ISR_ORE) == USART_ISR_ORE) 
  {  
    USART2->ICR |= USART_ICR_ORECF;
  }
  if ((USART2->ISR & USART_ISR_IDLE) == USART_ISR_IDLE)  //The new frame data receive 
  {
    USART2->ICR |= USART_ICR_IDLECF;    
    Uart_Channel_isr[1](USART2->RDR);/*读取解析数据*/
   }  
}

03 恢复DMA,清空CNDTR,等待下次数据到来

   处理完数据之后,及时将DMA标志以及CNDTR清空,否则CNDTR一直不清空,会导致下次接收数据的时候,造成通道的占用,数据使用过之后,就清理掉CNDTR,这样保证每次接收数据的通道有足够的位置。

static void Usart2_Dma_Reload(uint16_t length)/*清空数据*/
{
  DMA1_Channel5->CCR &= ~(DMA_CCR_EN);             //disable the dma 
  DMA1_Channel5->CNDTR = length;          //Set the length
  DMA1_Channel5->CCR |= DMA_CCR_EN;                //enable the dma
}
目录
相关文章
|
1月前
|
传感器
【STM32】I2C练习,SHT3X温度传感器的数据读取
【STM32】I2C练习,SHT3X温度传感器的数据读取
|
2月前
|
Java C语言
STM32使用printf重定向到USART(串口)并打印数据到串口助手
STM32使用printf重定向到USART(串口)并打印数据到串口助手
46 0
|
8月前
|
缓存 自然语言处理 网络协议
STM32CubeMX | | 使用小熊派串口驱动峰汇ETH-01以太网模块上传数据到OneNet
STM32CubeMX | | 使用小熊派串口驱动峰汇ETH-01以太网模块上传数据到OneNet
107 0
|
8月前
|
Linux C语言 Android开发
ESP8266透传:利用STM32f103zet6发送数据到HTTP服务器
ESP8266透传:利用STM32f103zet6发送数据到HTTP服务器
190 0
|
9月前
|
传感器 数据采集
STM32(HAL库)通过ADC读取MQ2数据
STM32(HAL库)通过ADC读取MQ2数据
|
10月前
|
传感器 存储 C++
STM32读取BH1750光照强度数据打印到串口
BH1750是一种数字式环境光强度传感器(Digital Light Sensor),也称为其他名称,例如GY-302传感器、BH1750FVI传感器等。它的工作原理是通过收集光线照射到传感器上的量来测量环境亮度。
193 0
|
10月前
|
Java C语言
STM32使用printf重定向到USART(串口)并打印数据到串口助手
STM32使用printf重定向到USART(串口)并打印数据到串口助手
296 1
STM32使用printf重定向到USART(串口)并打印数据到串口助手
|
10月前
|
数据处理
STM32实现DMA接收串口数据
STM32实现DMA接收串口数据
227 0
|
11月前
STM32的USART发送数据时如何使用TXE和TC标志
STM32的USART发送数据时如何使用TXE和TC标志
132 0
|
11月前
|
传感器 数据采集
STM32 BMP280模块 获取气压温度高度传感器数据
STM32 BMP280模块 获取气压温度高度传感器数据 TFT显示
223 0