OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 5007|回复: 2

H750的DMA串口接收分享,标题要满12字

[复制链接]

83

主题

344

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1991
金钱
1991
注册时间
2014-7-1
在线时间
188 小时
发表于 2020-11-30 09:12:50 | 显示全部楼层 |阅读模式
本帖最后由 shenqihao 于 2020-11-30 13:16 编辑

首先感谢正点原子网站网友的分享帮助。
DMA模式的串口接收,有几个注意点
1、内存中的数组地址要32字节对齐,数组大小要32字节整数倍。
比如://SendBuff地址一定要32字节对齐,SEND_BUF_SIZE一定要32字节整数倍
        #define SEND_BUF_SIZE 32
        u8 SendBuff[SEND_BUF_SIZE]__attribute__((section(".ARM.__at_0x24000000")));        
2、关闭DCache,不然读出数据错误。
        SCB_InvalidateDCache_by_Addr((uint32_t*)SendBuff,SEND_BUF_SIZE);
3、串口中断可以不开,但接收使能要记得开
       //UART3配置
        USART3->CR3=1<<6;       //使能串口3的DMA发送   
        USART3->CR1|=1<<2;                  //串口接收使能

4、MCU读写数组后,要再次关闭DCache
以下是DMA配置,在正点原子例程基础上修改的。

  1. void MYDMA_Config(DMA_Stream_TypeDef *DMA_Streamx,u8 chx,u32 par,u32 mar,u16 ndtr)
  2. {
  3.         DMA_TypeDef *DMAx;
  4.         DMAMUX_Channel_TypeDef *DMAMUXx;
  5.         u8 streamx;
  6.         if((u32)DMA_Streamx>(u32)DMA2)//得到当前stream是属于DMA2还是DMA1
  7.         {
  8.                 DMAx=DMA2;
  9.                 RCC->AHB1ENR|=1<<1;                //DMA2时钟使能  
  10.         }else
  11.         {
  12.                 DMAx=DMA1;
  13.                  RCC->AHB1ENR|=1<<0;                //DMA1时钟使能
  14.         }
  15.         while(DMA_Streamx->CR&0X01);//等待DMA可配置
  16.         streamx=(((u32)DMA_Streamx-(u32)DMAx)-0X10)/0X18;                        //得到stream通道号
  17.          if(streamx>=6)DMAx->HIFCR|=0X3D<<(6*(streamx-6)+16);                //清空之前该stream上的所有中断标志
  18.         else if(streamx>=4)DMAx->HIFCR|=0X3D<<6*(streamx-4);                //清空之前该stream上的所有中断标志
  19.         else if(streamx>=2)DMAx->LIFCR|=0X3D<<(6*(streamx-2)+16);        //清空之前该stream上的所有中断标志
  20.         else DMAx->LIFCR|=0X3D<<6*streamx;                                                        //清空之前该stream上的所有中断标志

  21.         if((u32)DMA_Streamx>(u32)DMA2)streamx+=8;                                        //如果是DMA2,通道编号+8
  22.         DMAMUXx=(DMAMUX_Channel_TypeDef *)(DMAMUX1_BASE+streamx*4);        //得到对应的DMAMUX通道控制地址
  23.         DMAMUXx->CCR=chx&0XFF;                //通道选择
  24.         
  25.         

  26.         DMA_Streamx->CR&=~(1<<0);         //先全部复位CR寄存器值 //关闭DMA传输
  27.         while(DMA_Streamx->CR&0X1);        //确保DMA可以被设置         
  28.         
  29.         DMA_Streamx->PAR=par;                                //DMA外设地址
  30.         DMA_Streamx->M0AR=mar;                        //DMA 存储器0地址
  31.         DMA_Streamx->NDTR=ndtr;                        //DMA 存储器0地址
  32.         DMA_Streamx->FCR &=~(1<<2);        //直接模式
  33.         
  34.         DMA_Streamx->CR|=1<<4;                //传输完成中断使能
  35.         DMA_Streamx->CR|=0<<6;                //外设到存储器模式
  36.         DMA_Streamx->CR|=1<<8;                //循环模式
  37.         DMA_Streamx->CR|=0<<9;                //外设非增量模式
  38.         DMA_Streamx->CR|=1<<10;                //存储器增量模式
  39.         DMA_Streamx->CR|=0<<11;                //外设数据长度:8位
  40.         DMA_Streamx->CR|=0<<13;                //存储器数据长度:8位
  41.         DMA_Streamx->CR|=0<<16;                //低优先级
  42.         DMA_Streamx->CR|=1<<0;                //开启DMA
  43.         
  44.         //DMA_Streamx->FCR=0X21;        //FIFO控制寄存器
  45. }
复制代码
以下是串口3的DMA配置
  1. //Uart3接收使能设置
  2. void DMA_Uart3ReceiveSet(void)
  3. {
  4.         //DMA配置
  5.         MYDMA_Config(DMA2_Stream7,45,(u32)&USART3->RDR,(u32)SendBuff,SEND_BUF_SIZE);
  6.         //UART3配置
  7.         USART3->CR3=1<<6;       //使能串口3的DMA接收
  8.         USART3->CR1|=1<<2;                  //串口接收使能
  9.         //不要Cache功能,DMA数据要直接透写进内存,否则读出数据有问题
  10.         //SendBuff地址一定要32字节对齐,SEND_BUF_SIZE一定要32字节整数倍
  11.         SCB_InvalidateDCache_by_Addr((uint32_t*)SendBuff,SEND_BUF_SIZE);
  12. }
复制代码
最后是主函数里面的while
  1. while(1)
  2.         {
  3. //                t++;
  4. //                Send_Uart3(t);
  5.                 delay_ms(1000);
  6.                 if((DMA2->HISR&(1<<27)) ==(1<<27))
  7.                 {
  8.                         DMA2->HIFCR |=1<<27;
  9.                         if(SendBuff[SEND_BUF_SIZE-1]!=0)
  10.                         {
  11.                                 for(t=0;t<SEND_BUF_SIZE;t++)
  12.                                 {
  13.                                         SendBuffR[t]=SendBuff[t];
  14.                                         Send_Uart3(SendBuff[t]);
  15.                                 }
  16.                                 SendBuff[SEND_BUF_SIZE-1]='\0';
  17.                                       SCB_InvalidateDCache_by_Addr((uint32_t*)SendBuff,SEND_BUF_SIZE);
  18. //                                SendBuff[SEND_BUF_SIZE-1]=0;
  19.                         }
  20.                 }

  21.         }
复制代码

复制代码


做一个相信自己的人
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

31

主题

2183

帖子

0

精华

资深版主

Rank: 8Rank: 8

积分
14365
金钱
14365
注册时间
2018-8-3
在线时间
1155 小时
发表于 2020-11-30 10:24:19 | 显示全部楼层
回复 支持 反对

使用道具 举报

2

主题

37

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
484
金钱
484
注册时间
2014-9-5
在线时间
179 小时
发表于 2021-11-26 22:33:53 | 显示全部楼层
楼主方便把例程发上来嘛,原子哥寄存器例程没有DMA接收部分,网上找了很多也不行。
回复 支持 反对

使用道具 举报

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

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-2-26 14:55

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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