打印
[技术问答]

这里有官方技术吗?看下这个demo问题出在哪里?

[复制链接]
1240|8
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
GZZXB|  楼主 | 2019-5-21 17:13 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式

ADC扫描3个通道,采用DMA搬运到buff。代码设置如下

为什么只有前面3个单元数据才正确,后面的不搬运了?该怎么改动才能实现将
扫描到的3个通道,顺序一直往buff里填充?
代码是在官方SDK上简单修改而来。
HC32L136_DDL_Rev1.0.0.rar (1.5 MB)

使用特权

评论回复
沙发
aoyi| | 2019-5-22 12:54 | 只看该作者
你的硬件是怎么连接的呢

使用特权

评论回复
板凳
drer| | 2019-5-22 12:59 | 只看该作者
初始化代码贴上来瞅瞅

使用特权

评论回复
地板
gwsan| | 2019-5-22 13:00 | 只看该作者
楼主本想在哪个通道读出来数据呢

使用特权

评论回复
5
martinhu| | 2019-5-22 13:33 | 只看该作者
本帖最后由 martinhu 于 2019-5-22 18:28 编辑

看你一次扫描只采了3个通道,采样完成之后3个通道的采样数据搬运到buff里面?你用的burst硬件触发,当第一次ADC采样完成后,DMA触发,传送3*6,供18次,
因为ADC结果寄存器只有012有值,所以只看到前面3个数组有值。



根据你描述的需求,我觉得你应该使用DMAC的硬件块(Block)传输,这样每次ADC转换完成后,传输一个请求,DMA传输一次
你可以注意手册上Block和Burst的区别

还有ADC的扫描转换,并不是使能一次,就可以永不停止地扫描转换了。

具体到你这个应用,因为没有BC为0,源地址是不会重载的(在TC为0时候重载),

所以我使用了timer2来触发ADC转换,转换完成后触发一次DMA搬运,
并且使用timer中断计数

HC32L136_DDL_Rev1.0.0.zip

1.03 MB

使用特权

评论回复
6
GZZXB|  楼主 | 2019-5-22 17:52 | 只看该作者
//使能DMA触发
  Adc_ConfigDmaTrig(DmaSqr);
  
  stcDmaCfg.enMode =  DmaBlock;//DmaBurst;                  
  stcDmaCfg.u16BlockSize = 0x03u;
  stcDmaCfg.u16TransferCnt = 6;         //burst模式,一次触发传输数据大小为 3*1,
  stcDmaCfg.enTransferWidth = Dma32Bit;            
  stcDmaCfg.enSrcAddrMode = AddressIncrease;
  stcDmaCfg.enDstAddrMode = AddressIncrease;
  stcDmaCfg.bDestAddrReloadCtl = FALSE;
  stcDmaCfg.bSrcAddrReloadCtl = TRUE;//FALSE;
  stcDmaCfg.bSrcBcTcReloadCtl = TRUE;//FALSE;
  stcDmaCfg.u32SrcAddress = (uint32_t) &(M0P_ADC->SQRRESULT0);
  stcDmaCfg.u32DstAddress = (uint32_t)&ADC_Result_Array[0];
  stcDmaCfg.enRequestNum = ADCSQRTrig;                //设置为ADCSQR触发
  Dma_InitChannel(DmaCh0,&stcDmaCfg);       
  
  //使能DMA,使能DMA0,启动DMA0
  Dma_Enable();
  Dma_EnableChannel(DmaCh0);
  //Dma_Start(DmaCh0);               
  Adc_SQR_Start();

在中断 里
void AdcContIrqCallback(void)
{   
    Adc_GetSqrResult(&u16AdcRestult0, 0);
    Adc_GetSqrResult(&u16AdcRestult2, 1);
    Adc_GetSqrResult(&u16AdcRestult5, 2);
  
    stcAdcIrqFlag.bAdcSQRIrq = TRUE;
        Adc_SQR_Start();
}

源地址一直递增不能回到,初始化的ad地址
stcDmaCfg.u32SrcAddress = (uint32_t) &(M0P_ADC->SQRRESULT0);
该怎样设置才能实现传输完一个块后,SRC地址返回到初始化DMA的地址?

使用特权

评论回复
7
martinhu| | 2019-5-22 18:34 | 只看该作者
GZZXB 发表于 2019-5-22 17:52
//使能DMA触发
  Adc_ConfigDmaTrig(DmaSqr);
  

目前好像只有TC为0的时候源地址才会重载,所以按照你的需求,一般BC设为3,TC设为1(库函数配置);
ADC的转换你使用软件,每次只能转换一次,或者用timer定时触发ADC转换;
但是这样设置好像不能直接等DMAC传输你需要的次数之后停止,得用别的方式计数停止,
你可以参考我刚才上传的代码,

使用特权

评论回复
8
GZZXB|  楼主 | 2019-5-22 22:21 | 只看该作者
martinhu 发表于 2019-5-22 18:34
目前好像只有TC为0的时候源地址才会重载,所以按照你的需求,一般BC设为3,TC设为1(库函数配置);
ADC ...

                                         感谢你的回复
是的所以我认为在不加入软件处理的前提下,一次DMA最多只能搬运16个数据. 也就是BC的最大值.
需要搬运更多的值只能软件介入.  用STM32F030 启动一次AD转换是可以一直循环扫描转换的,DMA也是可以循环填充的.  看来这个DMA是STM32的低配版吧.

使用特权

评论回复
9
martinhu| | 2019-5-23 09:50 | 只看该作者
GZZXB 发表于 2019-5-22 22:21
感谢你的回复
是的所以我认为在不加入软件处理 ...

对于ADC的连续扫描,如果想要一直不断地扫描,目前是通过循环的硬件触发ADC,比如timer触发,间隔时间可自由调整。
对于DMA搬运次数,以前有个帖子里面讨论过,对于对等大小的源和目的区域,搬运次数可以是65536*16,如果CONFB0.MSK位置1,对于对等的区块搬运,可以永远进行下去,比如从ADC.SqrResult0~ADC.SqrResult2搬运到AdcBuffer[0]~AdcBuffer[2]里面,可以在没有软件干预的情况下永远传输下去。
对于传输源和目的不等的情况,如果源只有一个数据,比如ADC.SqrResult0,那么源地址固定的话,Block为1,TC可以是从1~65536次做到对buffer的堆叠。
像你这样的,源有3个寄存器,目前好像是在目的地址不重载的情况下可以做到对buffer的堆叠,但是需要防止目的buffer的溢出。

使用特权

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

本版积分规则

96

主题

331

帖子

10

粉丝