找回密码
 立即注册
查看: 601|回复: 10

ADC_DMA测多通道时通道之间会影响吗

[复制链接]
  • 打卡等级:以坛为家II
  • 打卡总天数:455
  • 最近打卡:2025-06-10 13:10:51
已绑定手机

236

主题

340

回帖

1686

积分

金牌会员

积分
1686
发表于 2024-12-17 20:20:37 | 显示全部楼层 |阅读模式

0f51ddf0-eb4c-40ee-a250-973dff66b1d3.png

当我只开启15通道测得的电压是对的,但我同时开启10通道一起测时,原本15通道的值就不对了

10通道暂时是悬空的

QQ20241217-201715.png

在xdata创建两个数组,把数组地址赋值给DMA_ADC_RXA,测得的数组第二个值就是15通道的值,计算得到的电压不对,

但只测15通道,使用数组第一个值计算得到的电压是正确的

回复

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:540
  • 最近打卡:2025-08-13 15:59:34
已绑定手机
已实名认证

116

主题

2685

回帖

6698

积分

版主

积分
6698
发表于 2024-12-17 20:37:05 | 显示全部楼层

image.png

不更改 ADC_DMA 配置寄存器 2(DMA_ADC_CFG2)的话,默认转换次数就是1,如果你使用int宽度的数组,那么第一通道就需要占用数组的0~2地址,第二个通道需要从数组的第三个下标开始取出

例如ShuZu[3]这种形式,而不是是直接取出下一个。

回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:526
  • 最近打卡:2025-08-13 09:45:20
已绑定手机

86

主题

5898

回帖

1万

积分

超级版主

积分
10657
发表于 2024-12-17 21:07:51 | 显示全部楼层
  1. unsigned char xdata DMA_Buffer[ADC_CH][ADC_NUM*2+4] _at_ DMA_ADDR;
  2. for(i=0;i<ADC_CH;i++)
  3.                         {
  4.                                 ADC_Value[i]=DMA_Buffer[i][2*ADC_NUM+2];
  5.                                 ADC_Value[i]<<=8;
  6.                                 ADC_Value[i]|=DMA_Buffer[i][2*ADC_NUM+3];
  7.                                 ADC_Value[i]<<=8;
  8.                                 ADC_Value[i]|=DMA_Buffer[i][2*ADC_NUM+1];
  9.                                 ADC_Value[i]>>=4;        //20bit结果右移4位得16位结果
  10.                         }
复制代码
https://www.stcaimcu.com/forum.php?mod=redirect&goto=findpost&ptid=2537&pid=19963

回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:455
  • 最近打卡:2025-06-10 13:10:51
已绑定手机

236

主题

340

回帖

1686

积分

金牌会员

积分
1686
发表于 2024-12-18 08:49:54 | 显示全部楼层
王*** 发表于 2024-12-17 20:37
不更改 ADC_DMA 配置寄存器 2(DMA_ADC_CFG2)的话,默认转换次数就是1,如果你使用int宽度的数组,那么第 ...

转换一次不就各个通道取一次值吗,两个通道不就取了4个字节数据吗
为什么会有8字节数据

点评

有硬件自动平均值和对应的通道号,上面的数据格式截图已经说明了具体的内容  详情 回复 发表于 2024-12-18 08:53
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:540
  • 最近打卡:2025-08-13 15:59:34
已绑定手机
已实名认证

116

主题

2685

回帖

6698

积分

版主

积分
6698
发表于 2024-12-18 08:53:07 | 显示全部楼层
QQ6243*** 发表于 2024-12-18 08:49
转换一次不就各个通道取一次值吗,两个通道不就取了4个字节数据吗
为什么会有8字节数据 ...

有硬件自动平均值和对应的通道号,上面的数据格式截图已经说明了具体的内容
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:455
  • 最近打卡:2025-06-10 13:10:51
已绑定手机

236

主题

340

回帖

1686

积分

金牌会员

积分
1686
发表于 2024-12-18 08:57:44 | 显示全部楼层
王*** 发表于 2024-12-18 08:53
有硬件自动平均值和对应的通道号,上面的数据格式截图已经说明了具体的内容 ...

硬件取平均值每个通道都会有吗,也就是一个通道取一次就有5字节数据

点评

每个通道都会有 一个通道如果只转换一次的话,也是需要占用6个byte数据  详情 回复 发表于 2024-12-18 09:33
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:540
  • 最近打卡:2025-08-13 15:59:34
已绑定手机
已实名认证

116

主题

2685

回帖

6698

积分

版主

积分
6698
发表于 2024-12-18 09:33:34 | 显示全部楼层

每个通道都会有

一个通道如果只转换一次的话,也是需要占用6个byte数据

image.png

回复 支持 反对

使用道具 举报 送花

  • 打卡等级:初来乍到
  • 打卡总天数:4
  • 最近打卡:2025-08-13 10:27:55
已绑定手机

1

主题

4

回帖

33

积分

新手上路

积分
33
发表于 5 天前 | 显示全部楼层
王*** 发表于 2024-12-18 09:33
每个通道都会有
一个通道如果只转换一次的话,也是需要占用6个byte数据

大神能不能解释一下,
41 44 43 30 3A 20 20
41 44 43 31 3A 20 20
41 44 43 32 3A 20 20
41 44 43 33 3A 20 20
41 44 43 34 3A 20 20
41 44 43 35 3A 20 20这个我是直接复制参考程序,不知道这些代表什么意思,

点评

看不出来,感觉不像adcdma的数据?里面没有ADC转换通道号啊  详情 回复 发表于 5 天前
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:540
  • 最近打卡:2025-08-13 15:59:34
已绑定手机
已实名认证

116

主题

2685

回帖

6698

积分

版主

积分
6698
发表于 5 天前 | 显示全部楼层
平*** 发表于 2025-8-8 20:23
大神能不能解释一下,
41 44 43 30 3A 20 20
41 44 43 31 3A 20 20

看不出来,感觉不像adcdma的数据?里面没有ADC转换通道号啊
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:初来乍到
  • 打卡总天数:4
  • 最近打卡:2025-08-13 10:27:55
已绑定手机

1

主题

4

回帖

33

积分

新手上路

积分
33
发表于 4 天前 | 显示全部楼层
这个是STC官方例程,
#include "config.h"
bit        B_ADC_DMA_busy;
bit        B_ADC_DMA_ok;

u16        xdata adc_tmp[CHANNELS][COUNTS+2];       
//adc存放的数组, [n][0~(COUNTS-1)]为每次转换的值, [n][COUNTS]高字节为ADC通道号,低字节为取平均值后的余数,  
//[n][COUNTS+1)]为平均值

void ADC_DMA_Init()
{
  //P1n_HighZ(0x3b);        //设置要做ADC的IO做高阻输入, P1.0(ADC0) P1.1(ADC1) P1.3(ADC3) P1.4(ADC4) P1.5(ADC5)
        //P5n_HighZ(0x00);        //设置要做ADC的IO做高阻输入, P5.4(ADC2)
                ADC_CONTR = 0x80 + 0;        //ADC on + channel
        ADCCFG = RES_FMT + ADC_SPEED;
        ADCTIM = CSSETUP + CSHOLD + SMPDUTY;
       
        DMA_ADC_CFG  = (1<<7) + (0<<2) + 0;        //bit7=1: 允许ADC_DMA中断, 0:禁止.  bit3 bit2: ADC_DMA中断优先级(低0~3高), bit1 bit0: ADC_DMA数据总线访问优先级(低0~3高)
        DMA_ADC_STA  = 0;                //bit0: ADC_DMA完成(中断请求)标志, 需要软件清0.
        DMA_ADC_CFG2 = 9;                //每个通道转换的次数, 0-->1次, 8-->2次, 9-->4次, 10-->8次, 11-->16次, 12-->32次, 13-->64次, 14-->128次, 15-->256次.
        DMA_ADC_CHSW1 = 0x00;        //ADC通道使能, bit7~bit0对应通道15~8.
        DMA_ADC_CHSW0 = 0x3f;        //ADC通道使能, bit7~bit0对应通道7~0.
}

void        ADC_DMA_TRIG(u16 xdata *AdcBuf)
{
        u16        i;

        if(B_ADC_DMA_busy)        return;                //DMA正忙则返回,避免重复触发
        i   = (u16)AdcBuf;                                //要发送数据的首地址
        DMA_ADC_RXAH   = (u8)(i >> 8);        //存放的地址高字节
        DMA_ADC_RXAL   = (u8)i;                        //存放的地址低字节
        DMA_ADC_STA    = 0;                //bit0: ADC_DMA完成(中断请求)标志, 需要软件清0.
        B_ADC_DMA_busy = 1;                //标志ADC-DMA忙,ADC DMA中断中清除此标志,使用ADC DMA前要确认此标志为0
        DMA_ADC_CR   = (1<<7) + (1<<6);                //启动ADC_DMA,  bit7=1:允许ADC_DMA功能, 0:禁止.   bit6=1:触发ADC_DMA功能.
}


void ADC_DMA()
{
                u8        i,k;
          static u16        j = 0;
                delay_ms(1);
                if(++j >= 1000)        //每隔1000ms触发一次DMA_ADC
                {
                        j = 0;
                        ADC_DMA_TRIG(&adc_tmp[0][0]);        //启动ADC_DMA
                }

                if(B_ADC_DMA_ok)        //已完成
                {
                        B_ADC_DMA_ok = 0;
                        for(i=0; i<CHANNELS; i++)
                        {
                                //printf("ADC%u:  ", adc_tmp[i][COUNTS]>>8);        //打印通道号ADCn:
          printf("ADC%u:  ", adc_tmp[i][COUNTS]);        //打印通道号ADCn:
                                for(k=0; k<COUNTS; k++)
                                {
                                        //printf("采样%u= ", (int)k);        //打印提示采样值序号 采样x
                                //        printf("%u,  ", adc_tmp[i][k]);        //使用printf()发送,字符不对齐
                                        //Tx_u16(adc_tmp[i][k]);                        //使用Tx_u16()发送,字符对齐
                                }
                                        //printf("平均值=%u.\r\n", adc_tmp[i][COUNTS+1]);
                        }
                }
}



void ADC_DMA_Interrupt(void) interrupt 13
{
        DMA_ADC_STA = 0;        //清除ADC_DMA完成(中断请求)标志
        B_ADC_DMA_busy = 0;        //清除ADC-DMA忙标志
        B_ADC_DMA_ok   = 1;        //标志已完成
}
回复 支持 反对

使用道具 举报 送花

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

本版积分规则

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

GMT+8, 2025-8-13 16:42 , Processed in 0.131068 second(s), 112 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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