打印
[其他ST产品]

关于STM32如何触发DMA的问题,请指教!

[复制链接]
4285|7
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
wangpeng59|  楼主 | 2017-12-23 00:42 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
我目前在调的一个项目中,需要采用DMA的方式,从数组向串口发送数据。我计划的是通过外部中断,不断地触发DMA,使之移动数据,每进入中断一次,便将该数组内容移入串口的数据寄存器一次。可是每次串口助手只能收到第一次的数组数据,并不能持续不断地接收,不知道是怎么回事?我是将启动DMA通道的工作放在了DMA的初始化函数里,而外设请求DMA函数放入中断函数中的。
由于是刚刚开始用STM32,所以不太熟练,很多地方不懂。谢谢大家不吝赐教!!
以下是DMA初始化函数:
void DMA_Config(void)
{
    DMA_InitTypeDef DMA_InitStructure;

        RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);        //开启DMA时钟
       
        /*设置DMA源:内存地址&串口数据寄存器地址*/
    DMA_InitStructure.DMA_PeripheralBaseAddr = USART1_DR_Base;          

        /*内存地址(要传输的变量的指针)*/
    DMA_InitStructure.DMA_MemoryBaseAddr = (u32)ADbuffer;
       
        /*方向:从内存到外设*/               
    DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;       
       
        /*传输大小DMA_BufferSize=BYTE_SIZE。       
    DMA_InitStructure.DMA_BufferSize = BYTE_SIZE;
       
        /*外设地址不增*/            
    DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
       
        /*内存地址自增*/
    DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;       
       
        /*外设数据单位为半字,即每个传输数据位的大小为16位数据*/       
    DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
       
        /*内存数据单位为半字,即每个传输数据位的大小为16位数据*/
    DMA_InitStructure.DMA_MemoryDataSize = DMA_PeripheralDataSize_HalfWord;         
       
        /*DMA模式:只一次传输*/
    DMA_InitStructure.DMA_Mode = DMA_Mode_Normal ;         
       
        /*优先级:中*/       
    DMA_InitStructure.DMA_Priority = DMA_Priority_Medium;  
       
        /*禁止内存到内存的传输        */
    DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
       
        /*配置DMA1的4通道*/                  
    DMA_Init(DMA1_Channel4, &DMA_InitStructure);           
       
        DMA_Cmd (DMA1_Channel4,ENABLE);                                        //使能DMA
}

以下是外部中断服务函数,有GPIO下降沿进入:
/* I/O线中断,中断线为PB9 */
void EXTI9_5_IRQHandler(void)
{
        if(EXTI_GetITStatus(EXTI_Line9) != RESET) //确保是否产生了EXTI Line中断
        {
            ReadFromAD7606();                         //耗时约22.23uS,填充成8个元素的数组,每个元素16位
                    
            USART_DMACmd(USART1, USART_DMAReq_Tx, ENABLE);//填充完数组后,串口向DMA发出数据转移请求,启动发送
                       
            EXTI_ClearITPendingBit(EXTI_Line9);     //清除中断标志位
        }  
}
沙发
wangpeng59|  楼主 | 2017-12-23 00:58 | 只看该作者
貌似发错版块了。。可以删除吗

使用特权

评论回复
板凳
fengfeng的恒| | 2017-12-23 09:03 | 只看该作者
不需要外部中断;配置好串口,需要发送数据的时候,把缓冲地址与大小方到DMA配置里,直接发送即可。

使用特权

评论回复
地板
wangpeng59|  楼主 | 2017-12-23 13:31 | 只看该作者
fengfeng的恒 发表于 2017-12-23 09:03
不需要外部中断;配置好串口,需要发送数据的时候,把缓冲地址与大小方到DMA配置里,直接发送即可。 ...


1.我是把内存地址和传输数据大小等一次性配置在DMA初始化里的;

2.用STM32的PB0引脚接收AD采集芯片AD7606的转换完成信号,每当接收到这个信号后(下降沿),便进入外部中断,在中断服务函数中将接收到的8路转换数据先排列进1个数组,然后启动一次DMA传输,传输8路数据至串口数据寄存器发送;

3.但我目前串口助手只能接收到第一次的8路数组数据,之后便没有了。。可我的中断是一直在给STM32的PB0引脚发送的。所以我觉得我的DMA启动转移数据部分还是有问题,却不知道是什么问题。。

使用特权

评论回复
5
fengfeng的恒| | 2017-12-23 16:03 | 只看该作者
wangpeng59 发表于 2017-12-23 13:31
1.我是把内存地址和传输数据大小等一次性配置在DMA初始化里的;

2.用STM32的PB0引脚接收AD采集芯片AD76 ...

AD转换的速度是很快的,串口的速度比较慢。估计是后面的数据没发完,又被你的中断打断,重新配置了DMA,所以后面没数据了。你如果非要用外部中断,可以发送数据的时候,先暂停AD转换,然后发送完再启动AD转换。

使用特权

评论回复
6
wangpeng59|  楼主 | 2017-12-23 18:11 | 只看该作者
本帖最后由 wangpeng59 于 2017-12-23 18:15 编辑
fengfeng的恒 发表于 2017-12-23 16:03
AD转换的速度是很快的,串口的速度比较慢。估计是后面的数据没发完,又被你的中断打断,重新配置了DMA, ...

1.确实串口的速度比较慢,所以我才想到用DMA做传输的工作,省下CPU;

2.我的DMA在主函数里配置一次就不再配置了,中断服务函数的工作只是“先组成一个数组,然后启动DMA发送一次(正常模式)”。所以,进入每次中断应该不存在您提到的重新配置了DMA的问题;

3.AD7606我控制的是1ms采集一次数据,采集一次就给STM32发一次中断信号,并将采得的8路数据传给STM32。STM32便在中断函数里“先组成一个数组,然后启动DMA发送一次(正常模式)”至串口助手,所以ADC的采集速度是可控的;

4.听了您的建议,我大概明白了一些,我的串口速度是设置的比较慢(9600),但我觉得即便是这样,也只是在传输8路数据时,被新的中断打断几次。但应该还是能不断地收到新的8路数据的呀,怎么会正好收到8路数据(而且是正确的8路数据),就没有下一次了呢。。

5.我现在还不确定启动DMA的工作是通过外设发送请求,还是使能通道,您看我的两段程序写的是否有问题呢?我目前是通过外设发送请求来启动的。谢谢!!

使用特权

评论回复
7
wangpeng59|  楼主 | 2017-12-24 01:11 | 只看该作者
fengfeng的恒 发表于 2017-12-23 16:03
AD转换的速度是很快的,串口的速度比较慢。估计是后面的数据没发完,又被你的中断打断,重新配置了DMA, ...

终于发现问题所在了!通过看手册和思考,主要更改了2个方面:
1. DMA每次转移完数据,寄存器CNDTR都会变为0,下次进入中断需要再重新加载发送的数据量,才会有第二次发送;
2. 我把串口波特率调高(我调到了3100000),使之在1ms内可以发完8路数据,就不会被中断打断了。
目前测试,一切正常!实在是感谢fengfeng的恒的帮助,提醒了中断的问题,否则还在原地转圈儿呢!
话说现在论坛给不了分了吗?

使用特权

评论回复
8
fengfeng的恒| | 2017-12-26 10:09 | 只看该作者
wangpeng59 发表于 2017-12-24 01:11
终于发现问题所在了!通过看手册和思考,主要更改了2个方面:
1. DMA每次转移完数据,寄存器CNDTR都会变 ...

串口的速度如果更得上AD的速度就可以。我之前做的AD采集是1us一次,如果要把所有AD数据(一个AD采集两字节)都通过串口发送时不现实的,但只发送一个通道还是可以的。如果你的AD速度没那么快,也是可以匹配好的。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

39

主题

217

帖子

2

粉丝