|
对,就是跳来跳去……我都没想到这么不准……
用来测热敏电阻的,用的电阻分压,原理图见下。
万用表测量在1.65-1.75之间,但是用单片机adc就跳来跳去,一会零点几,一会一点几……
如果把单片机静置,单片机就会保持在一个不确定的数值上。动两下,就会跳来跳去好久
甚至,断开电阻分压的供电和地(我设计了跳线),依然显示有电压,还是跳来跳去。
神奇。。
STC8H1k28自带adc,adc参考电压直接连了vcc,用ams1117和两节7号电池都是如此。
即使参考电压再不准,也不至于这样吧……
总而言之,言而总之,跳变没有任何规律。
如下是程序,原理图和实拍。tm1640驱动没有问题,非常好用(在别人基础上改的,最近学的多了才知道是iic)。
adc程序是在datasheet里复制的,有改动,后续处理是参考了数十个程序融合而成的。
单片机源程序如下:
- //头文件-----------------------------------------------
- #include <stc8.h>
- #include<stdio.h>
- #include <intrins.h>
- #define ADCTIM (*(unsigned char volatile xdata *)0xfea8)
- //端口声明----------------------------------------------
- sbit led1=P1^6;
- sbit led2=P1^7;
- sbit DIN=P3^4;
- sbit CLK=P3^5;
- sbit key1=P3^2;
- sbit key2=P3^3;
- unsigned char ah;
- unsigned char al;
- //端口声明----------------------------------------------
- unsigned int i;
- unsigned char code nbr[11]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x39}; //共阳数码管段码数据
- void delay(unsigned z)
- {
- unsigned x,y;
- for(x=z;x>0;x--)
- for(y=300;y>0;y--);
- }
- //IIC协议start通讯开始函数-----------------------------------
- void I2CStart()
- {
- DIN=1;
- CLK=1;
- delay(2);
- DIN=1;
- delay(2);
- DIN=0;
- delay(4);
- CLK=0;
- delay(2);
- }
- //IIC协议stop通讯结束函数-----------------------------------
- void I2CStop()
- {
- CLK=1;
- delay(2);
- DIN=0;
- delay(2);
- DIN=1;
- delay(2);
- CLK=0;
- DIN=0;
- }
- //发送8bit数据,从低位开始-----------------------------
- void I2CWritebyte(unsigned char oneByte)
- {
- unsigned char i;
- for(i=0;i<8;i++)
- {
- CLK=0;
- if(oneByte&0x01)
- DIN=1;
- else
- DIN=0;
- delay(3);
- CLK=1;
- oneByte=oneByte>>1;
- }
- CLK=0;
- delay(4);
- DIN=0;
- delay(2);
- }
- //TM1640写数据,再次封装,简化程序----------------------------
- void tmw(int ha,hb)
- {
- I2CStart();
- I2CWritebyte(ha); //地址命令设置:初始地址00H
- for(i=0;i<1;i++) //发送16位显示数据
- {
- I2CWritebyte(hb); //显示值
- }
- I2CStop();
- }
- //TM1640开启显示便捷函数-------------------------------------
- void tms()
- {
- I2CStart();
- I2CWritebyte(0x8c); //显示控制:显示开,脉冲宽度设为11/16
- I2CStop();
- }
- //adc中断-----------------------------------------------------
- void ADC_Isr() interrupt 5
- {
- ADC_CONTR &= ~0x20; //清中断标志
- ah = ADC_RES; //读取 ADC 结果
- al = ADC_RESL; //读取 ADC 结果
- delay(2);//必要的延时
- ADC_CONTR |= 0x40; //继续 AD 转换
- }
- //adc采样函数-----------------------------------------------------
- void ad()
- {
- unsigned int ab = 0;
- int ac = 0;
- float ad;
- ab = ah*4+al;//两个寄存器(adc结果)合并
- ad = ab*10000/1024*3.2;//计算电压(无小数点)
- ac = ad;
- tmw(0xc0,nbr[ac/1000%10]);//每一位依次显示在数码管上
- delay(10);
- tmw(0xc1,nbr[(ac/100)%10]);
- delay(10);
- tmw(0xc2,nbr[(ac/10)%10]);
- delay(10);
- tmw(0xc3,nbr[ac%10]);
- delay(10);
- tms();
- delay(20);
-
- }
- //main函数-----------------------------------------------------
- void main()
- {
- //uart_init();
- P0M0 = 0x00; //配置io口寄存器为双向口
- P0M1 = 0x01; //设置 P0.0 为 ADC 口
- P1M0 = 0x00;
- P1M1 = 0x00;
- P2M0 = 0x00;
- P2M1 = 0x00;
- P3M0 = 0x00;
- P3M1 = 0x00;
- P4M0 = 0x00;
- P4M1 = 0x00;
- P5M0 = 0x00;
- P5M1 = 0x00;
- P_SW2 |= 0x80;
- ADCTIM = 0x3f; //设置 ADC 内部时序
- P_SW2 &= 0x7f;
- ADCCFG = 0x0f; //设置 ADC 时钟为系统时钟/2/16/16
- ADC_CONTR = 0x88; //使能 ADC 模块
- EADC = 1; //使能 ADC 中断
- EA = 1;
- ADC_CONTR |= 0x40; //启动 AD 转换
- led1 = 0;
- while(1){
- ad();
- }
- }
复制代码
数码管用的tm1640驱动。热敏电阻10k,分压电阻10k(实测9.2k)
没有连锡,焊接没问题,热敏电阻拆下来量了没坏
神奇,完全可以改造成随机数生成器……
|
|