找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 1163|回复: 4
收起左侧

STM32F DMA转移存储器的内容到串口发送寄存器,发送寄存器再发送会丢失数据吗?

[复制链接]
ID:959891 发表于 2022-2-14 00:51 | 显示全部楼层 |阅读模式
STM32F 配置DMA把数组的数据传送给串口的发送寄存器,然后串口的发送寄存器就可以自动进行发送。DMA发送的数据量是8200个,存储器属于自增模式。当串口的发送寄存器只有一个字节的空间,DMA把数组的数据一个一个传过来的时候,串口的发送寄存器有可能上一个传过来的数据还没来得及发送出去,就被DMA新的运过来的数据覆盖掉了,这样的话会导致数据丢失才对。但是为什么大家都这样呢,而且没有数据丢失的情况。DMA传送的数据到串口发送寄存器,和串口发送寄存器进行发送,这两个的时序是怎么配合的?


while(1)
        {
                t=KEY_Scan(0);
                if(t==KEY0_PRES)//KEY0按下
                {
                        LCD_ShowString(60,150,200,16,16,"Start Transimit....");
                        LCD_ShowString(60,170,200,16,16,"   %");//显示百分号
                        printf("\r\nDMA DATA:\r\n ");             
                       USART_DMACmd(USART1,USART_DMAReq_Tx,ENABLE);   
                        MYDMA_Enable(DMA1_Channel4);//开始一次DMA传输!          
                    //等待DMA传输完成,此时我们来做另外一些事,点灯
                    //实际应用中,传输数据期间,可以执行另外的任务
                    while(1)
                    {
                                if(DMA_GetFlagStatus(DMA1_FLAG_TC4)!=RESET)//等待通道4传输完成
                                {
                                        DMA_ClearFlag(DMA1_FLAG_TC4);//清除通道4传输完成标志
                                        break;
                        }
                                pro=DMA_GetCurrDataCounter(DMA1_Channel4);//得到当前还剩余多少个数据
                                pro=1-pro/((TEXT_LENTH+2)*100);//得到百分比          
                                pro*=100;      //扩大100倍
                                LCD_ShowNum(60,170,pro,3,16);          
                    }                            
                        LCD_ShowNum(60,170,100,3,16);//显示100%          
                        LCD_ShowString(60,150,200,16,16,"Transimit Finished!");//提示传送完成
                }
                i++;
                delay_ms(10);
                if(i==20)
                {
                        LED0=!LED0;//提示系统正在运行       
                        i=0;
                }                  
        }
}


void MYDMA_Enable(DMA_Channel_TypeDef*DMA_CHx)
{
        DMA_Cmd(DMA_CHx, DISABLE );  //关闭USART1 TX DMA1 所指示的通道      
        DMA_SetCurrDataCounter(DMA1_Channel4,DMA1_MEM_LEN);//DMA通道的DMA缓存的大小
        DMA_Cmd(DMA_CHx, ENABLE);  //使能USART1 TX DMA1 所指示的通道
}          



回复

使用道具 举报

ID:373388 发表于 2022-2-14 09:16 | 显示全部楼层
你不用DMA的时候为了防止你说的问题的产生是如何做的呢? 当然你会判断数据移位寄存器是否为空,才决定是否发送下一帧数据,DMA 会帮你自动完成这部分工作。
回复

使用道具 举报

ID:959891 发表于 2022-2-14 12:33 | 显示全部楼层
xhaity 发表于 2022-2-14 09:16
你不用DMA的时候为了防止你说的问题的产生是如何做的呢? 当然你会判断数据移位寄存器是否为空,才决定是否 ...

关于您说的DMA会自动判断移位寄存器是否为空,来决定是否发送下一个字节数据到串口发送寄存器,有什么依据吗?
回复

使用道具 举报

ID:625730 发表于 2022-2-14 13:39 | 显示全部楼层
yermsir 发表于 2022-2-14 12:33
关于您说的DMA会自动判断移位寄存器是否为空,来决定是否发送下一个字节数据到串口发送寄存器,有什么依 ...

数据手册上是这么个意思。
“利用DMA发送
使用DMA进行发送,可以通过设置USART_CR3寄存器上的DMAT位激活。当TXE位被置为’1’时,DMA就从指定的SRAM区传送数据到USART_DR寄存器。为USART的发送分配一个DMA通道的步骤如下(x表示通道号):
1. 在DMA控制寄存器上将USART_DR寄存器地址配置成DMA传输的目的地址。在每个TXE事件后,数据将被传送到这个地址。
2. 在DMA控制寄存器上将存储器地址配置成DMA传输的源地址。在每个TXE事件后,将从此存储器区读出数据并传送到USART_DR寄存器。
3. 在DMA控制寄存器中配置要传输的总的字节数。
4. 在DMA寄存器上配置通道优先级。
5. 根据应用程序的要求,配置在传输完成一半还是全部完成时产生DMA中断。
6. 在DMA寄存器上激活该通道。
当传输完成DMA控制器指定的数据量时,DMA控制器在该DMA通道的中断向量上产生一中断。
在发送模式下,当DMA传输完所有要发送的数据时,DMA控制器设置DMA_ISR寄存器的TCIF标志;监视USART_SR寄存器的TC标志可以确认USART通信是否结束,这样可以在关闭USART或进入停机模式之前避免破坏最后一次传输的数据;软件需要先等待TXE=1,再等待TC=1。
535”
回复

使用道具 举报

ID:959891 发表于 2022-2-14 18:14 | 显示全部楼层
TEC 发表于 2022-2-14 13:39
数据手册上是这么个意思。
“利用DMA发送
使用DMA进行发送,可以通过设置USART_CR3寄存器上的DMAT位激 ...

再您的指导下,我明白了,非常感谢。
回复

使用道具 举报

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

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

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