数码之家

 找回密码
 立即注册

QQ登录

只需一步,快速开始

微信登录

微信扫一扫,快速登录

搜索
查看: 3323|回复: 14

[C51] 小白学51单片机,ADC检测电压并显示

[复制链接]
发表于 2024-3-4 11:10:52 | 显示全部楼层 |阅读模式

爱科技、爱创意、爱折腾、爱极致,我们都是技术控

您需要 登录 才可以下载或查看,没有账号?立即注册 微信登录

x
这几天在学ADC,IC是STC8H8K64U 实际做出来感觉有些不对,
显示15通道(内部1.19V)时,我的显示1.24V

1.jpg

检测通道4,电位器扭到底显示0

2.jpg

电位器往上扭电压会随着增大,但到了4.9以上就显示全是8了,

3.jpg
不知道是哪里处理不对



 楼主| 发表于 2024-3-4 11:13:27 | 显示全部楼层
代码如下:

ADC部分:
  1. #include <stc8h.h>
  2. #include "intrins.h"         //_nop_
  3. #include "delayms.h"
  4. typedef unsigned char u8;
  5. typedef unsigned int u16;
  6. u16 voltage;
  7. void adc_init()
  8. {       
  9.         ADCTIM=0x3f;        //0011 1111
  10.         //cssetup ADC通道选择时间0 1个时钟
  11.         //cshold  ADC通道选择保持01 2个时钟
  12.         //smspduty ADC模拟信号采样时间11111 32个时钟
  13.         ADCCFG=        0x2f;        //0010 1111
  14.         //resfmt 转换结果右对齐,B5为1
  15.         //speed  ADC工作时钟1111 sysclk/2/16
  16.         ADC_CONTR=0x80;        //1000 0000
  17.         //adc_power        打开ADC电源B7为1
  18.         delayms(10);                       
  19. }

  20. u16        get_adc12bitresult(u8 channel)
  21. {
  22.         ADC_RES=0;        //
  23.         ADC_RESL=0;        //
  24.         ADC_CONTR=(ADC_CONTR & 0xf0) | 0x40 | channel;        //启动ADC
  25.         //adc_start ADC转换启动0x40 B6为1
  26.         //adc_chs 模拟通道选择
  27.         _nop_();_nop_();_nop_();_nop_();
  28.         while((ADC_CONTR & 0x20)==0);         //等待ADC结束
  29.         //adc_flag 0x20        ADC转换标志B5为1
  30.         ADC_CONTR &= ~0x20;        //标志归0
  31.         return (((u16)ADC_RES<<8) | ADC_RESL);        //高8位左移8位再或上低8位
  32. }

  33. void adc_convert(u8 chn)
  34. {
  35.         u16 j;
  36.         u8 k;
  37.         get_adc12bitresult(chn);        //查询方式做一次ADC,丢弃
  38.         get_adc12bitresult(chn);        //查询方式做一次ADC,丢弃
  39.         for (k=0;k<16;k++)
  40.         j=j+get_adc12bitresult(chn);
  41.         j=j/16;
  42.         voltage=j*0.12207;  //(5/4096)*100
  43. }
复制代码
端口设置部分:
  1. #include <stc8h.h>

  2. void gpio_init()
  3. {
  4.         P_SW2 |= 0x80;        //扩展寄存器XFR访问使能        1000 0000或等于 B7要为1
  5.         P0M1=0x00; P0M0=0x00;        //P0口设置为准双向口 接数码管段选
  6.         P1M1=0x10; P1M0=0x00;        //P1口设置为准双向口 数码管位选P1.4 ADC4
  7.         P5M1=0x00; P5M0=0x00;        //P5口设置为准双向口 P5.2数码管位选
  8. }
复制代码


显示部分:
  1. #include <stc8h.h>
  2. #include "delayms.h"
  3. #include "adc.h"

  4. sbit led_a = P1^0;        //
  5. sbit led_b = P1^1;        //
  6. sbit led_c = P5^2;        //
  7. sbit led_d = P1^3;        //
  8. //数码管接在P0口       
  9. unsigned char code table[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x7f};

  10. void display()          //显示函数
  11. {
  12.          P0=table[voltage%10];          //送出段选信号
  13.          led_a=0;                                 //打开个位位选
  14.          delayms(5);
  15.          led_a=1;

  16.          P0=table[voltage/10%10];          //送出段选信号
  17.          led_b=0;                                   //打开十位位选
  18.          delayms(5);
  19.          led_b=1;

  20.          P0=table[voltage/100%10]&table[10];          
  21.          led_c=0;
  22.          delayms(5);
  23.          led_c=1;

  24.          P0=table[voltage/1000%10];         
  25.          led_d=0;
  26.          delayms(5);
  27.          led_d=1;
  28. }
复制代码

主函数部分:
  1. #include <stc8h.h>                //头文件
  2. #include "display.h"
  3. #include "adc.h"
  4. #include "delayms.h"
  5. #include "gpio.h"

  6. void main ()          //主函数
  7. {
  8.         gpio_init();  //初始化
  9.         adc_init();          //初始化
  10.         while(1)
  11.         {
  12.                 adc_convert(4);  //ADC4 P1.4
  13.                 display();         //调用显示函数
  14.         }
  15. }


复制代码




回复 支持 反对

使用道具 举报

 楼主| 发表于 2024-3-4 14:50:00 | 显示全部楼层
用万用表实测电压也是很接近的,就是为什么扭到最大时不是显示5,怎样让这个显示值更稳定一些?
回复 支持 反对

使用道具 举报

 楼主| 发表于 2024-3-4 19:37:58 | 显示全部楼层
                   j = (u16)((u32)j * 119 / Bandgap);  //计算外部电压, Bandgap为1.19V, 测电压分辨率0.01V
回复 支持 反对

使用道具 举报

 楼主| 发表于 2024-3-5 09:30:19 | 显示全部楼层
电压值跟万用表还是接近的,就是数码管最后一位有点闪

7672d293207b926cd8946cf8d09a7a6.jpg

441066a6ee87a535b814696d60bccf9.jpg


回复 支持 反对

使用道具 举报

 楼主| 发表于 2024-3-6 11:07:00 | 显示全部楼层
我今天又反复试了一下,
在j这里取平均值效果不理想,
for (k=0;k<16;k++)
        j=j+get_adc12bitresult(chn);
        j=j/16;
        voltage=j*0.12207;  //(5/4096)*100
但在voltage累加再取平均值就,最后一位就不会闪了
回复 支持 反对

使用道具 举报

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

本版积分规则

APP|手机版|小黑屋|关于我们|联系我们|法律条款|技术知识分享平台

闽公网安备35020502000485号

闽ICP备2021002735号-2

GMT+8, 2025-6-23 00:59 , Processed in 0.249600 second(s), 14 queries , Redis On.

Powered by Discuz!

© 2006-2025 MyDigit.Net

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