找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 678|回复: 14
打印 上一主题 下一主题
收起左侧

STC8G1K08 ADC问题

[复制链接]
跳转到指定楼层
楼主
ID:1146155 发表于 2025-11-26 17:33 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
一路ADC已经读取内部的LDO的电压1.19V,但是我还想使用另外一路读取传感器的模拟值。如何多路ADC同步进行!原理和程序实现
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:1153607 发表于 2025-11-27 08:26 | 只看该作者
STC老妖的库里有现成的历程,拿去用就是了。
回复

使用道具 举报

板凳
ID:1153607 发表于 2025-11-27 08:31 | 只看该作者
“同步进行”是做不到的,只能是按照顺序一个个的进行。一定要同步进行ADC使用专用芯片或者干脆几片CPU同步工作进行。
回复

使用道具 举报

地板
ID:712493 发表于 2025-11-27 09:15 | 只看该作者
大部分的MCU就只有一个ADC转换模块,外面多路IO有ADC输入只是通过内部电子开关切换而已!
回复

使用道具 举报

5#
ID:879809 发表于 2025-11-27 11:26 | 只看该作者
一个ADC不可能实现理想的“同步”,分别切换采样转换能看上去是“同步”的。内部LDO电压采集一次就足够了,用来标定传感器电压,同步毫无意义。
回复

使用道具 举报

6#
ID:327265 发表于 2025-11-27 11:36 | 只看该作者
轮询切换采集
回复

使用道具 举报

7#
ID:712493 发表于 2025-11-27 15:17 | 只看该作者
weisc6955 发表于 2025-11-27 08:31
“同步进行”是做不到的,只能是按照顺序一个个的进行。一定要同步进行ADC使用专用芯片或者干脆几片CPU同步 ...

看手册  专用ADC芯片大多也只有2个转换模块!
回复

使用道具 举报

8#
ID:712493 发表于 2025-11-27 15:19 | 只看该作者
rundstedt 发表于 2025-11-27 11:26
一个ADC不可能实现理想的“同步”,分别切换采样转换能看上去是“同步”的。内部LDO电压采集一次就足够了, ...

读内部LDO实际是反向读取 MCU的VDD电压值,由于VDD理论是可变的,所以读一次是不行的
回复

使用道具 举报

9#
ID:712493 发表于 2025-11-27 15:22 | 只看该作者

多个ADC通道需要采集确实不是很好安排顺序的,而且多个ADC通道采集其响应速度会低很多!
回复

使用道具 举报

10#
ID:879809 发表于 2025-11-27 16:15 | 只看该作者
fj51hei 发表于 2025-11-27 15:19
读内部LDO实际是反向读取 MCU的VDD电压值,由于VDD理论是可变的,所以读一次是不行的

VDD理论上是不可能剧烈变化的,只会缓慢漂移,1分钟甚至10分钟测一次都没问题。
回复

使用道具 举报

11#
ID:1133081 发表于 2025-11-27 21:21 | 只看该作者
用串口助手观察结果,mV。
  1. #include "STC8G.H"
  2. #include "intrins.h"
  3. #define uint unsigned int
  4. #define uchar unsigned char
  5. #define ulong unsigned long

  6. uchar data dis_buf[8];
  7. int *BGV;//内部1.19V参考信号源值
  8. uint res;//读取内部第15通道ADC结果
  9. uint VCC;//电源电压
  10. uint VCA;//缓冲
  11. uint Vin;//被测电压
  12. uint VADC;//ADC转换结果
  13. uint count;//计数
  14. bit flag;//T0中断标志
  15. bit busy;//串口发送标志

  16. void Uart1_Init(void)        //115200bps@11.0592MHz
  17. {
  18.         SCON = 0x50;                //8位数据,可变波特率
  19.         AUXR |= 0x40;                //定时器时钟1T模式
  20.         AUXR &= 0xFE;                //串口1选择定时器1为波特率发生器
  21.         TMOD &= 0x0F;                //设置定时器模式
  22.         TL1 = 0xE8;                        //设置定时初始值
  23.         TH1 = 0xFF;                        //设置定时初始值
  24.         ET1 = 0;                        //禁止定时器中断
  25.         TR1 = 1;                        //定时器1开始计时
  26.         ES = 1;                                //使能串口1中断
  27. }

  28. void UartSend(char dat)
  29. {
  30.     while (busy);//等待中断复位
  31.     busy = 1;
  32.     SBUF = dat;
  33. }

  34. //初始化ADC
  35. void ADC_Init(void)
  36. {
  37.         P_SW2 |= 0x80;
  38.         ADCTIM = 0x3f;         //设置ADC内部时序
  39.         P_SW2 &= 0x7f;
  40.         ADCCFG = 0x2f;         //设置ADC时钟为系统时钟/2/16,12位结果右对齐
  41.         ADC_CONTR = 0x80;      //使能ADC模块
  42. }
  43. //读取ADC结果
  44. uint ADC_Read(uchar ch)
  45. {
  46.         ADC_CONTR = ch;                          //启动AD转换
  47.         _nop_();
  48.         _nop_();
  49.         while (!(ADC_CONTR & 0x20));                //查询ADC完成标志
  50.         ADC_CONTR &= ~0x20;                         //清完成标志
  51.         return ADC_RES << 8 | ADC_RESL;         //返回12位ADC结果
  52. }

  53. void Timer0_Init(void)                //2毫秒@11.0592MHz
  54. {
  55.         AUXR |= 0x80;                        //定时器时钟1T模式
  56.         TMOD &= 0xf0;                        //设置定时器模式
  57.         TL0 = 0x9A;                                //设置定时初始值
  58.         TH0 = 0xA9;                                //设置定时初始值
  59.         TF0 = 0;                                //清除TF0标志
  60.         TR0 = 1;                                //定时器0开始计时
  61.         ET0 = 1;                                //使能定时器0中断
  62.         EA  = 1;                          //使能总中断
  63. }

  64. void main()
  65. {
  66.         uchar i;
  67.         P0M0 = 0xff;       //设置P0为推挽口
  68.         P0M1 = 0x00;
  69.         P1M0 = 0x00;       //设置P1.0为ADC口
  70.         P1M1 = 0x80;
  71.         P2M0 = 0x00;
  72.         P2M1 = 0x00;
  73.         P3M0 = 0x00;
  74.         P3M1 = 0x00;
  75.         P4M0 = 0x00;
  76.         P4M1 = 0x00;
  77.         P5M0 = 0x00;
  78.         P5M1 = 0x00;
  79.         BGV = (int idata *)0xef;//内部1.19V参考信号源值
  80.         ADC_Init();
  81.         Uart1_Init();
  82.         Timer0_Init();
  83.         while (1)
  84.         {
  85.                 if(flag)
  86.                 {
  87.                         flag=0;
  88.                         ADC_Read(0xcf);//丢掉两次检测
  89.                         ADC_Read(0xcf);
  90.                         res=ADC_Read(0xcf);   //读取第15通道ADC结果
  91.                         VCC = (int)(4096L * *BGV / res);//计算电源电压
  92.                         VCA=VCC;
  93.                         for(i=0;i<4;i++)//数据分解存入缓存地址前4
  94.                         {
  95.                                 dis_buf[3-i]=VCA%10;
  96.                                 VCA/=10;
  97.                         }
  98.                         ADC_Read(0xc7);//丢掉两次检测
  99.                         ADC_Read(0xc7);
  100.                         VADC=ADC_Read(0xc7);   //读取第7通道ADC结果
  101.                         Vin=VCC*(ulong)VADC/4096;//计算输入电压
  102.                         for(i=0;i<4;i++)//数据分解存入缓存地址后4
  103.                         {
  104.                                 dis_buf[7-i]=Vin%10;
  105.                                 Vin/=10;
  106.                         }
  107.                         for(i=0;i<8;i++)//串口发送数据
  108.                         {
  109.                                 UartSend(dis_buf[i]+'0');
  110.                         }                       
  111.                 }
  112.         }
  113. }
  114. //
  115. void Timer0_Isr(void) interrupt 1
  116. {
  117.         if(++count>=500)
  118.         {
  119.                 count=0;
  120.                 flag=1;
  121.         }
  122. }

  123. void Uart1_Isr(void) interrupt 4
  124. {
  125.         if (TI)                                //检测串口1发送中断
  126.         {
  127.                 TI = 0;                        //清除串口1发送中断请求位
  128.                 busy = 0;
  129.         }
  130.         if (RI)                                //检测串口1接收中断
  131.         {
  132.                 RI = 0;                        //清除串口1接收中断请求位
  133.         }
  134. }
复制代码



回复

使用道具 举报

12#
ID:1146155 发表于 2025-11-28 18:33 | 只看该作者
fj51hei 发表于 2025-11-27 15:22
多个ADC通道需要采集确实不是很好安排顺序的,而且多个ADC通道采集其响应速度会低很多!

但是我发现在主函数while(1)中使用串口打印没问题,如果加入了188数码管的显示程序,那么串口就打不出来!程序是顺序执行的,不知道是为什么
回复

使用道具 举报

13#
ID:1146155 发表于 2025-11-28 18:36 | 只看该作者
发表于 2025-11-27 11:36
轮询切换采集

假如我想读1ADC0通道(初始化-读)这个过程完了以后。我再想读ADC1通道(初始化-读),程序上是whlie(1){(ADC0初始化-读);(ADC1初始化-读初始化-读);(ADC2初始化-读初始化-读); ..................;}是这样组合的吗,
回复

使用道具 举报

14#
ID:1146155 发表于 2025-11-28 18:37 | 只看该作者
WL0123 发表于 2025-11-27 21:21
用串口助手观察结果,mV。

谢谢大佬
回复

使用道具 举报

15#
ID:1146155 发表于 2025-11-28 18:48 | 只看该作者
感谢各位大佬的回复
回复

使用道具 举报

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

本版积分规则

小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

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