liucw99 发表于 2025-7-18 17:21:04

Ai8H单片机ADC采样,定时器触发,DMA的问题求助

我的问题如下:
单片机是Ai8H8K64U,工作频率内部时钟11.0592MHz。目标是想通过ADC采样,然后计算获取交流电的有效电压值。
现在已经使用ADC查询的方式,连续采样16次计算一个平均值作为一个采样点,共计得到512个这样的数值,再通过计算得到交流电的有效电压值。
从验证的结果看,这个方式的误差基本上可以保证在2%以内,但是比较耗费单片机的CPU的时间。
目前想做一点改进:
1、在20ms内(一个周期),通过定时器/PWM来触发ADC,采样512个点(测试过,256个点的误差有点大,而且平均值偏差也比较大)。
2、采样的数据点,通过DMA的方式传输到缓存(XDATA的一个数组)。
3、512个点采样结束后,给出一个结束标志位(中断标志,或者是自定义的标志位都可以),然后根据结束标志位启动计算过程。
我自己也曾经尝试过用DMA来传输数据,不过失败了,得到的结果总是一个固定数值。所以才来这里求助。
无论是官方的高手(比如梁工)还是路过的大神,帮我提供一下思路,我去尝试下。

国芯人工智能 发表于 2025-7-18 17:23:00

尊敬的用户:

您好!感谢您对STC8H系列单片机的深入使用与探索。针对您提出的问题,我们将从ADC采样、定时器触发、DMA传输及数据处理等方面进行专业分析,并提供可行的解决方案。

一、系统概述

您所使用的单片机为STC8H8K64U,其内部时钟频率为11.0592MHz(注意:您提到的是“110592MHz”,应为11.0592MHz)。目标是通过ADC采集交流电的有效电压值,目前采用查询方式完成16次采样取平均值,共采集512个点,最终计算有效值。当前方法精度满足要求,但CPU占用较高,因此希望优化为定时器触发ADC+DMA传输的方式,以提升效率并减少CPU负担。

二、问题分析与建议

1. 定时器触发ADC采样

您希望在20ms内(即一个工频周期)完成512次采样,这意味着每点间隔约为 39.0625μs。对于STC8H系列单片机而言,若使用内部时钟11.0592MHz,其机器周期为 1/11.0592MHz × 12 = 1.087μs,因此可以配置定时器实现精确的采样间隔。
推荐方式:使用定时器中断或PWM输出作为ADC触发源。
注意事项:
ADC采样速率需匹配定时器频率;
确保ADC采样时间足够(一般建议至少10μs以上);
若使用PWM触发ADC,需确保PWM输出频率与采样率一致。

2. DMA传输ADC数据

您尝试使用DMA传输ADC数据失败,结果固定不变,可能原因如下:
DMA通道未正确配置:ADC数据寄存器地址与目标缓冲区地址未设置正确;
ADC未启用DMA请求:需在ADC控制寄存器中开启DMA使能;
DMA优先级冲突:其他外设可能抢占DMA资源;
缓存区未初始化:XDATA数组未正确分配空间或未清空;
ADC未进入正常工作模式:如未开启ADC、未选择正确的输入通道等。

建议步骤:

1. 配置ADC为连续采样模式,并启用DMA请求;
2. 设置DMA通道,将ADC数据寄存器(如ADCDATA)映射到XDATA数组;
3. 启动ADC和DMA后,等待DMA传输完成标志;
4. 检查DMA状态寄存器,确认是否发生错误或未完成。

3. 采样完成后触发计算

当DMA完成512个数据的传输后,可通过以下方式触发计算:
DMA传输完成中断:在DMA中断服务程序中设置标志位;
DMA传输完成标志位:通过读取DMA状态寄存器判断是否完成;
软件轮询:在主循环中检测标志位,触发计算过程。

建议使用DMA中断方式,避免主循环频繁轮询,提高系统响应性。

三、参考代码结构(伪代码)

c
// 定义ADC与DMA相关变量
define ADCSAMPLECOUNT 512
unsigned int adcbuffer; // XDATA数组
volatile unsigned char dmacompleteflag = 0;

// 初始化ADC
void ADCInit(void) {
    ADCEN = 1;                // ADC使能
    ADCCON1 |= 0x08;          // 选择通道0
    ADCCON1 |= 0x01;          // 选择连续采样模式
    ADCCON1 |= 0x40;          // 开启DMA请求
}

// 初始化DMA
void DMAInit(void) {
    DMACON = 0x00;            // 清除DMA配置
    DMACON |= 0x01;         // 选择DMA通道0
    DMASRC0 = (unsigned int)&ADCDATA; // ADC数据寄存器地址
    DMADST0 = (unsigned int)adcbuffer; // 缓冲区地址
    DMALN0 = ADCSAMPLECOUNT2; // 数据长度(16位)
    DMACON |= 0x80;         // 启动DMA
}

// 定时器初始化(用于触发ADC)
void TimerInit(void) {
    TMOD = 0x01;            // 定时器0模式1
    TH0 = 0x00;
    TL0 = 0x00;
    ET0 = 1;                  // 开启定时器0中断
    TR0 = 1;                  // 启动定时器
}

// 定时器中断服务函数
void Timer0ISR(void) interrupt 1 {
    // 触发一次ADC采样(可配合PWM或直接触发)
    ADCCON1 |= 0x80;          // 触发ADC转换
}

// DMA中断服务函数
void DMAISR(void) interrupt 15 {
    if (DMACON & 0x01) {      // 判断DMA通道0是否完成
      dmacompleteflag = 1;
      DMACON &= ~0x01;      // 清除DMA标志
    }
}

// 主循环
void main(void) {
    ADCInit();
    DMAInit();
    TimerInit();

    while(1) {
      if (dmacompleteflag) {
            // 执行有效值计算
            float Vrms = CalculateVrms(adcbuffer, ADCSAMPLECOUNT);
            // ...后续处理
            dmacompleteflag = 0;
      }
    }
}

四、常见问题排查建议

| 问题 | 原因 | 解决方案 |
|------|------|----------|
| DMA传输数据始终为0 | ADC未正确配置或未启动 | 检查ADC使能、通道选择、采样模式 |
| DMA未触发 | DMA配置错误或未启用 | 检查DMA通道、源地址、目标地址、长度 |
| 计算误差大 | 采样点不足或采样不准确 | 增加采样点数或调整采样频率 |
| CPU占用高 | 查询方式效率低 | 改用DMA+中断方式 |

五、总结

通过定时器触发ADC与DMA传输数据相结合的方式,可以显著降低CPU负载,提高系统效率。建议按上述步骤进行配置,并结合实际测试不断调试参数。如仍有疑问,欢迎进一步交流。

祝您项目顺利!

——国芯人工智能团队

[本文内容由国芯人工智能辅助生成,仅供参考]

梁工 发表于 2025-7-18 18:15:04

你可以搜搜本站关于交流电采样计算电压、电流有效值的帖子。
我做过不少交流互感器、霍尔互感器(交直流兼容)、直接采样的方式,采样计算交流电压有效值、电流有效值、有功功率、视在功率、功率因数,得益于STC的低噪声、高精度的12位ADC,测量结果非常满意!
ADC采样交流电计算有效值,采样速度为一个周期20ms采样4的倍数次,次数越多越好,但是次数太多会很占CPU时间,2个通道不超过20KHz(一个周期采样400次,可以连续采样4个周期1600次),6个通道不超过10KHz(一个周期采样200次,可以连续采样10个周期1600次)。
如果只测量一路交流电压或电流,则使用PWMA自动触发ADC、ADC中断读取数据并计算平方和,是最优方案。
如果是多路ADC,则使用ADC DMA,但ADC DMA不能设置采样率,所以要用定时器中断来启动ADC DMA。定时器中断设置为最高优先级。
比如使用ADC DMA采样6个通道(三相交流电压、电流),定时器中断触发ADC DMA,DMA中断读取结果。通道安排顺序为:电压1、电流1、电压2、电流2、电压3、电流3,这样同一相电压和电流相位差不超过0.15度。
ADC速度控制在6~8us,定时器中断10KHz,触发ADC DMA,无符号长整形变量最多可连续累加2000次的平方和而不会溢出,对应时间为200ms。

liucw99 发表于 2025-7-19 10:21:33

国芯人工智能 发表于 2025-7-18 17:23
尊敬的用户:

您好!感谢您对STC8H系列单片机的深入使用与探索。针对您提出的问题,我们将从ADC采样、定时 ...

非常感谢你的帮助,我按照你的思路去试试。

liucw99 发表于 2025-7-19 10:22:00

梁工 发表于 2025-7-18 18:15
你可以搜搜本站关于交流电采样计算电压、电流有效值的帖子。
我做过不少交流互感器、霍尔互感器(交直流兼 ...

好的,也非常感谢你的回复。
页: [1]
查看完整版本: Ai8H单片机ADC采样,定时器触发,DMA的问题求助