找回密码
 立即注册
查看: 2229|回复: 13

请教STC8H8K64U的DMA-ADC数据传输

[复制链接]
  • 打卡等级:以坛为家I
  • 打卡总天数:263
  • 最近打卡:2025-04-03 13:38:29

10

主题

52

回帖

1354

积分

金牌会员

积分
1354
发表于 2023-9-7 09:56:25 | 显示全部楼层 |阅读模式
第一次接触DMA,想用DMA-ADC功能实现对多路模拟量的采集,
看手册没看懂,论坛里看到有个例程
https://www.stcaimcu.com/forum.p ... 1494&extra=page%3D1),例程更没看懂。
主要问题是:ADC_DMA 接收地址寄存器(DMA_ADC_RXAx)的作用是什么?
从例程看,定义了外部存储器所需数据的存放地址,u8 xdata DmaBuffer[ADC_CH][ADC_DATA] _at_ DMA_ADDR;
但是,主程序中用了
DMA_ADC_RXAH = (u8)(DMA_ADDR >> 8);        //ADC转换数据存储地址
DMA_ADC_RXAL = (u8)DMA_ADDR;

这明显是将外部数据往DMA_ADC_RXAx传送,这么传送的目的是什么?
那么DmaBuffer[ADC_CH][ADC_DATA]中的数据时怎么获得的?
回复

使用道具 举报 送花

  • 打卡等级:偶尔看看III
  • 打卡总天数:51
  • 最近打卡:2025-05-02 10:07:51

73

主题

5883

回帖

1万

积分

超级版主

积分
12079
发表于 2023-9-7 11:20:38 | 显示全部楼层
将ADC设置好,将DMA设置好,启动一次DMA,硬件会自动帮你完成多通道ADC转换+平均值计算,DMA完成后你去读取结果即可,转换过程中不需要你的CPU去过问。下面的程序给你参考。


用户请先别修改程序, 直接下载"16-15路12位ADC转换-DMA-串口1(P3.1)返回结果-C语言"里的"ADC.hex"测试.
下载时选择主频11.0592MHZ. 测试时, 电脑的串口助手设置115200,8,n,1.

本程序演示15路ADC和bandgap DMA采样,通过串口1(P3.1)发送给上位机,波特率115200,8,n,1.

0~7通道对应P1.0 P1.1 P5.4 P1.3~P1.7, 8~14通道对应P0.0~P0.6, 15通道为内部1.19V基准电压做输入的ADC值.


STC8H系列-ADC相关程序.rar (918.47 KB, 下载次数: 277)


回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家I
  • 打卡总天数:263
  • 最近打卡:2025-04-03 13:38:29

10

主题

52

回帖

1354

积分

金牌会员

积分
1354
发表于 2023-9-7 15:40:51 | 显示全部楼层
梁*** 发表于 2023-9-7 11:20
将ADC设置好,将DMA设置好,启动一次DMA,硬件会自动帮你完成多通道ADC转换+平均值计算,DMA完成后你去读取 ...

谢谢梁工,我详细看看哈。
不过这个程序和我给链接的程序完全是两个风格
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家I
  • 打卡总天数:263
  • 最近打卡:2025-04-03 13:38:29

10

主题

52

回帖

1354

积分

金牌会员

积分
1354
发表于 2023-9-7 21:04:05 | 显示全部楼层
本帖最后由 清风迎明月 于 2023-9-7 21:11 编辑
梁*** 发表于 2023-9-7 11:20
将ADC设置好,将DMA设置好,启动一次DMA,硬件会自动帮你完成多通道ADC转换+平均值计算,DMA完成后你去读取 ...

梁工,你给这个程序继续请教一下,还是有地方看的不是很明白,但感觉理解应该八九不离十。
DMA_ADC_RXA  = adc_tmp;
这句程序其实就是将ADC每次转换结果的相关数据的存放外部存储器首地址交代清楚了。
DMA—ADC的工作原理其实就是将每次获取的ADC的数据送入寄存器DMA_ADC_RXA,而DMA_ADC_RXA按指向首地址,结合转换次数等等按顺序去存放ADC各通道的相关数据。
我上面理解没有错吧?
不管是看手册,还是我给除链接的程序,还是你这个程序,一直纠结的是DMA_ADC_RXA寄存器的作用。

我给你那句程序加的注释如下:
DMA_ADC_RXA  = adc_tmp;        //将外部存放数据首地址赋给DMA_ADC_RXA

点评

意思差不多,DMA_ADC_RXA指定你要存储的首地址,之后DMA会按要求顺序逐个安放得到的数据。  详情 回复 发表于 2024-7-12 17:32
ADC DMA自动存放结果,则要给DMA指定存放的首地址。DMA_ADC_RXA = adc_tmp;就是给首地址。  详情 回复 发表于 2023-9-8 00:05
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:偶尔看看III
  • 打卡总天数:51
  • 最近打卡:2025-05-02 10:07:51

73

主题

5883

回帖

1万

积分

超级版主

积分
12079
发表于 2023-9-8 00:05:41 | 显示全部楼层
清风*** 发表于 2023-9-7 21:04
梁工,你给这个程序继续请教一下,还是有地方看的不是很明白,但感觉理解应该八九不离十。
DMA_ADC_RXA  = ...

ADC DMA自动存放结果,则要给DMA指定存放的首地址。DMA_ADC_RXA  = adc_tmp;就是给首地址。
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:初来乍到
  • 打卡总天数:2
  • 最近打卡:2024-07-11 15:57:13

4

主题

16

回帖

84

积分

注册会员

积分
84
发表于 2024-7-11 13:49:20 | 显示全部楼层
梁*** 发表于 2023-9-7 11:20
将ADC设置好,将DMA设置好,启动一次DMA,硬件会自动帮你完成多通道ADC转换+平均值计算,DMA完成后你去读取 ...

梁工,这个有视频教程的吗?

点评

简单应用,我没有视频。  详情 回复 发表于 2024-7-11 17:07
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:偶尔看看III
  • 打卡总天数:51
  • 最近打卡:2025-05-02 10:07:51

73

主题

5883

回帖

1万

积分

超级版主

积分
12079
发表于 2024-7-11 17:07:50 | 显示全部楼层
link*** 发表于 2024-7-11 13:49
梁工,这个有视频教程的吗?

简单应用,我没有视频。
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:初来乍到
  • 打卡总天数:2
  • 最近打卡:2024-07-11 15:57:13

4

主题

16

回帖

84

积分

注册会员

积分
84
发表于 2024-7-12 15:49:33 | 显示全部楼层
本帖最后由 link123 于 2024-7-12 15:51 编辑
梁*** 发表于 2024-7-11 17:07
简单应用,我没有视频。

梁工,里面代码有个不太懂的地方,
for(i=0; i<CHANNELS; i++)
{
        Tx_ADC((u8)(adc_tmp[COUNTS]>>8), adc_tmp[COUNTS+1]);        
}
这个代码为什么能输出平均值,假设我只开了通道0,16次转换,根据手册平均值的高位不是2n+2,低位不是2n+3吗?换成程序应该是adc_tmp[COUNTS*2+2]和adc_tmp[COUNTS*2+3],
Screenshot 2024-07-12 155039.png

点评

请看我的变量定义,定义的注释已经说得很清楚: #define CHANNELS 16 //定义DMA要扫描的ADC通道数 #define COUNTS 16 //定义每个ADC通道转换的次数 u16 xdata adc_tmp[CHANNELS][COUNTS+2]; //adc存放的数组  详情 回复 发表于 2024-7-12 17:19
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:偶尔看看III
  • 打卡总天数:51
  • 最近打卡:2025-05-02 10:07:51

73

主题

5883

回帖

1万

积分

超级版主

积分
12079
发表于 2024-7-12 17:19:28 | 显示全部楼层
link*** 发表于 2024-7-12 15:49
梁工,里面代码有个不太懂的地方,
for(i=0; i>8), adc_tmp[COUNTS+1]);        
}

请看我的变量定义,定义的注释已经说得很清楚:
#define        CHANNELS             16                //定义DMA要扫描的ADC通道数
#define        COUNTS                16                //定义每个ADC通道转换的次数
u16        xdata adc_tmp[CHANNELS][COUNTS+2];        //adc存放的数组, [n][0~(COUNTS-1)]为每次转换的值, [n][COUNTS]高字节为ADC通道号,低字节为取平均值后的余数,  [n][COUNTS+1)]为平均值
我的DMA扫描CHANNELS=16通道,每个通道COUNTS=16次,则完成后,每个通道前面16个数据(数组下标0~15)就是ADC结果,下标16是通道号+平均值余数,下目标17就是平均值,这下明白了吧?
如果你只做一个通道,则只需要定义一个一维数组即可:
#define        CHANNELS             16                //定义DMA要扫描的ADC通道数
u16        xdata adc_tmp[COUNTS+2];
数据的安排同上述。
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:偶尔看看III
  • 打卡总天数:51
  • 最近打卡:2025-05-02 10:07:51

73

主题

5883

回帖

1万

积分

超级版主

积分
12079
发表于 2024-7-12 17:21:30 | 显示全部楼层
这明显是将外部数据往DMA_ADC_RXAx传送,这么传送的目的是什么?
答:这是告诉DMA我要存放数据的首地址。

那么DmaBuffer[ADC_CH][ADC_DATA]中的数据时怎么获得的?
答:数据是DMA获取的。
回复 支持 反对

使用道具 举报 送花

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

本版积分规则

QQ|手机版|小黑屋|深圳国芯人工智能有限公司 ( 粤ICP备2022108929号-2 )

GMT+8, 2025-5-3 03:11 , Processed in 0.151494 second(s), 113 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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