找回密码
 立即注册

QQ登录

只需一步,快速开始

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

STC8G1K08A单片机模数转换问题

[复制链接]
跳转到指定楼层
楼主
四个电阻串联,用STC8G1K08A单片机的P3^0口做模数转换ADC,用万用表测 2  3  4 点的电压,分别为 1.25V,2.50V,3.75V 按照理论,这三个点的模数变换数值应该为 256, 512, 768 ,实际显示的是250,377,440,除去变换的误差,这和理论值差的也太多了,程序是按照厂家提供的例程编写的,电路上的5V电压直接取自单片机的VCC和GND.测量时就是直接用杜邦线连P3^0口和 2 3 4 点,没有串限流电阻,也没有并分流电阻,这是程序出了问题还是电路出了问题?求论坛里的大神给指点一二。

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏5 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:213173 发表于 2021-7-4 07:31 | 只看该作者
给你一个应用实例参考,因电池供电,P3.2既作ADC输入,也作中断唤醒。ADC检测压力传感器信号,当无压力达到一定时间,进入休眠。一旦有压力MCU唤醒正常工作。你的问题可能是ADC转换结果寄存器设置不当。
  1. //STC8G1K08A工作电压范围1.9~5.5V
  2. //#include "reg51.h"
  3. #include <STC8.H>
  4. #include "intrins.h"
  5. typedef unsigned char uchar;
  6. typedef unsigned int uint;
  7. typedef unsigned long ulong;
  8. #define  ADCTIM  (*(unsigned char volatile xdata *)0xfea8)
  9. //#define ceiling 636 //上限
  10. //#define floor   923 //下限
  11. sbit LED_R=P5^4;
  12. sbit LED_G=P5^5;
  13. //sbit AVDD =P3^3;

  14. uint code table[36]={
  15. 923         ,//        0
  16. 915         ,//        1
  17. 907         ,//        2
  18. 898         ,//        3
  19. 890         ,//        4
  20. 882         ,//        5
  21. 874         ,//        6
  22. 866         ,//        7
  23. 858         ,//        8
  24. 850         ,//        9
  25. 841         ,//        10
  26. 833         ,//        11
  27. 825         ,//        12
  28. 817         ,//        13
  29. 809         ,//        14
  30. 800         ,//        15
  31. 792         ,//        16
  32. 784         ,//        17
  33. 776         ,//        18
  34. 768         ,//        19
  35. 760         ,//        20
  36. 751         ,//        21
  37. 743         ,//        22
  38. 735         ,//        23
  39. 727         ,//        24
  40. 719         ,//        25
  41. 710         ,//        26
  42. 702         ,//        27
  43. 694         ,//        28
  44. 686         ,//        29
  45. 677         ,//        30
  46. 669         ,//        31
  47. 661         ,//        32
  48. 653         ,//        33
  49. 645         ,//        34
  50. 636    };//35

  51. bit flag=0;//完成标志
  52. //uchar i;
  53. uint CY_ADC;//采样值
  54. uint time;

  55. void Timer0Init()                //2毫秒@11.0592MHz
  56. {
  57.         AUXR |= 0x80;                //定时器时钟1T模式
  58.         TMOD &= 0xF0;                //设置定时器自动重装模式
  59.         TL0 = 0x9A;                        //设置定时初值
  60.         TH0 = 0xA9;                        //设置定时初值
  61.         TF0 = 0;                        //清除TF0标志
  62.         TR0 = 1;                        //定时器0开始计时
  63. }
  64. /*----------------------------
  65.         读取ADC结果
  66. ----------------------------*/
  67. void GetADCResult()
  68. {        //ADC 控制器  电源  启动  完成  --   15通道模拟选择位
  69.         //ADC_CONTR    B7    B6    B5   B4   B3   B2   B1   B0
  70.         static uint count=0;
  71.         static uint PJZ_ADC=0;                //累加10次采样的变量1

  72.         count++;
  73.         if(count==1)ADC_CONTR = 0x80;           //使能ADC模块
  74.         if(count>=2&&count<=11)
  75.         {
  76.                 ADC_CONTR|= 0x42;       //启动AD转换,P3.2 ADC输入   
  77.                 _nop_();_nop_();
  78.                 while (!(ADC_CONTR & 0x20));            //查询ADC完成标志
  79.                 ADC_CONTR &= ~0x20;                     //清完成标志
  80.                 PJZ_ADC+=(ADC_RES<<8|ADC_RESL);         //累计10次读取10位ADC结果
  81.         }
  82.         if(count==11)
  83.         {
  84.                 CY_ADC=PJZ_ADC/10;
  85.                 PJZ_ADC=0;
  86.                 ADC_CONTR = 0x00;                //关闭ADC
  87.                 flag=1;
  88.         }
  89.         if(count>=10)//200ms
  90.                 count=0;
  91. }

  92. void main()
  93. {
  94.         P3M0 = 0x00;        //设置P3.2为ADC口
  95.         P3M1 = 0x04;        //设置P3.2为ADC口
  96.         P5M0 = 0x00;
  97.         P5M1 = 0x00;
  98.         P_SW2 |= 0x80;                //打开
  99.         ADCTIM = 0x3f;          //设置 ADC 内部时序
  100.         P_SW2 &= 0x7f;                //关闭
  101.         ADCCFG = 0x27;           //设置ADC结果右对齐,速度为512系统时钟        ADCCFG = 0x0f;  // 设置 ADC 时钟为系统时钟 /2/16/16
  102. //        ADC_CONTR = 0x80;  // 使能 ADC 模块
  103.         Timer0Init();
  104.   //ADC配置寄存器 --  --  格式控制  --   速度控制位
  105.   //   ADCCFG     B7  B6     B5     B4   B3 B2 B1 B0     
  106.         while (1)
  107.         {
  108.                 if(TF0)
  109.                 {
  110.                         TF0=0;
  111.                         GetADCResult();
  112.                         if(flag==1)
  113.                         {
  114.                                 flag=0;
  115.                                 if(CY_ADC>table[0])
  116.                                 {
  117.                                         time++;
  118.                                         LED_R=1;
  119.                                         LED_G=1;
  120.                                 }
  121.                                 else if(CY_ADC>table[0] && CY_ADC<table[36])
  122.                                 {
  123.                                         time=0;
  124.                                         LED_R=1;
  125.                                         LED_G=0;
  126.                                 }
  127.                                 else if(CY_ADC<table[36])
  128.                                 {
  129.                                         time=0;
  130.                                         LED_R=0;
  131.                                         LED_G=0;
  132.                                 }
  133.                                 if(time>=15000)
  134.                                 {
  135.                                         time=0;
  136.                                         P3M1 = 0x00;//设置P3.2为准双向
  137. //                                        AVDD = 0;
  138.                                         TR0 = 0;//关闭定时器
  139.                                         EX0 = 1; // 使能 INT0 中断 , 用于唤醒 MCU
  140.                                         EA = 1;
  141.                                         _nop_();_nop_();_nop_();_nop_();
  142.                                         PCON = IDL;  //MCU 进入空闲(省电)模式   
  143.                                         _nop_();_nop_();_nop_();_nop_();
  144.                                 }
  145.                         }
  146.                 }
  147.         }
  148. }

  149. void INT0_Isr() interrupt 0
  150. {
  151.         EX0 = 0; // 关闭 INT0 中断
  152.         EA = 0;        // 关闭总中断
  153. //        AVDD = 1;
  154.         P3M1=0x04; //设置P3.2为ADC口
  155.         TR0 = 1;                //启动定时器
  156. }
复制代码
回复

使用道具 举报

板凳
ID:401564 发表于 2021-7-4 19:02 | 只看该作者
代码呢?
STC8G1K08A这个IC容易受干扰,特别是电路中有高频信号的情况下
在ADC的采样输入一定要有一个104以上的电容,而且得是靠近端口的
单片机的VCC一定在做好滤波,104电容一定要靠近VCC
GND不能到处乱跑
回复

使用道具 举报

地板
ID:123289 发表于 2021-7-5 11:32 | 只看该作者
这个问题许多人会遇到,其它很多人不知道原因。
多路AD采样系统中有一个采样电容。系统会对电容上的电压进行对分试探转换,系统希望电容上的电压不要跳动,否则影响AD对分计算。于是系统在转换时会断开采样电容与外界的联系(本处AD是不是这样处理就不清楚了),这就需要切换采样通道后,稍等一下,待采样电容上的电充、分完全后,再下令开始采样!!!
楼主试试看:切换采样通道后,等50ms,再下令转换电压。改变等待时间,看看AD值有何变化?
回复

使用道具 举报

5#
ID:704846 发表于 2021-7-5 23:38 | 只看该作者
谢谢各位大侠的指点。
    我想做个小对讲机,限于体积,选用STC8G1K08A做控制芯片,它的IO口只有六个,去掉两个串口,再去掉三个用于功能选择按键的IO口,就剩一个IO口,只能用LED的闪烁频率来显示功能选择项,显得很LOW,后来发现了一个例子,按照他的思路,精简了一下,就三个选择项,装上后就是这个样,电压和ADC数值不成比例。我自己总结的原因是 ADC有内阻,接上后相当于并联,可能影响读数,也有可能是我的十位ADC结果转换成十进制数的计算方法有问题,也有可能是设置ADC各个寄存器的时候没有仔细看说明书,直接按照例程搬过来的,可能某个寄存器的高位或低位没设置,造成读数不准。
    但是,按照这个电路,每个按键的读数都比较稳定,目的已经达到了,先不探究具体原因了,节省下来的IO口,我弄了个IIC的OLED显示屏,用来显示频率,音量,亚音,话筒灵敏度等等,就显得很高大上了。想想还有一大堆的字模 bmp要自己画,脑袋都大了。
  再次感谢各位大神的指导,受益匪浅。希望以后能继续得到大家的帮助。
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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