从一个废仪表上拆了一个数码管版,经过改造,焊出相应的驱动板,做出一个电压表。
选用STC15w408AS单片机,由于引脚少,选用74hc138芯片作为位选,74hc595作为段选,用TL431的2.5v稳压源做参考电压。
电压表的设计思路:其实就是运用单片机内置的多个接口ADC转换。选用稳压2.5v进行ADC转换,这样电压变化小,转出的ADC的值变的也小(估值558左右),再经过另外一路两个电阻分压点转换出来的ADC的值进行计算。理论上能做到0~无穷大量程的(没啥实际意义)。根据这个思路如果分压电阻小于1R,根据分压计算也可以设计出电流表。这里没做电压电流表,其实知道原理就行了。
制作出来的实物图如下:
复制的代码注释乱码,大家可以下载附件查看,标注详细,适合初学单片机ADC的人。注:本人也是菜鸟一枚,大家互相交流学习,有更好的方案可以留言。共同进步。
单片机源程序如下:
- #include <STC15F2K60S2.H>
- #include<intrins.h>
- #define ADC_POWER 0x80
- #define ADC_FLAG 0x10
- #define ADC_START 0x08
- #define ADC_SPEEDLL 0x00
- #define ADC_SPEEDL 0x20
- #define ADC_SPEEDH 0x40
- #define ADC_SPEEDHH 0x60
- typedef unsigned char uchar;
- typedef unsigned int uint;
- sbit LSA=P1^2;
- sbit LSB=P1^0;
- sbit LSC=P3^7; //定义138逻辑芯片A,B,C脚
- sbit SRCLK=P3^6;
- sbit RCLK=P3^3;
- sbit SER=P3^2;//定义595芯片驱动脚
- uchar number[]={0x82,0xf6,0x43,0x46,0x36,0x0e,0x0a,0xe6,0x02,0x06}; //0-9断码非标准码
- unsigned char ch=4; //通道4,根据手册0为P1^0,1为P1^1,依次类推
- float voltage=0; //定义浮点电压参数
- uint ref=0,vin=0; //定义431稳压2.5v的ADC值。ref值是P1^4,vin是P1^3的ADC值
- void Hc595SendByte(uchar dat);//声明595函数
- void DigDisplay();//声明显示函数
- void Delay1ms() //@24.000MHz
- {
- unsigned char i, j;
- i = 24; j = 85;
- do
- {
- while (--j);
- } while (--i);
- }
- void adc_int() interrupt 5 //ADC中断
- {
-
- uint j=0;
- ADC_CONTR &=!ADC_FLAG;//清除中断标志位
- if(ch==4)
- {
- ref=(ADC_RES*4+ADC_RESL); //读取P1^4口ADC值保存在ref变量中,由于采用tl431稳压2.5v,所以这个值大约在558左右。
- }
- else if(ch==3)
- {
- vin=(ADC_RES*4+ADC_RESL); //读取P1^3口ADC值,这个值经过两个电阻分压得到的。
- voltage=(2.5*vin)/ref; //计算电压
- }
- if(ch==4) //切换转换ADC口
- ch=3;
- else if(ch==3)
- ch=4;
- for(j=0;j<=30;j++);
- ADC_RES=0;
- ADC_RESL=0;
- ADC_CONTR=ADC_POWER |ADC_SPEEDLL | ADC_START | ch;//启动ADC转换
- }
- void main()
- {
- uint i;
- P1ASF=0x18;//参考手册,0x38=00011000,开启P1^3,P1^4为ADC输入口,其余P1口为正常IO口
- ADC_RES=0;
- ADC_CONTR=ADC_POWER|ADC_SPEEDLL | ADC_START | ch;
- for(i=0;i<1000;i++);
- IE=0xA0;
- while(1)
- {
- DigDisplay();
- }
- }
- void Hc595SendByte(uchar dat)
- {
- uchar a;
- SRCLK=0;
- RCLK=0;
- for(a=0;a<8;a++)
- {
- SER=dat>>7;
- dat<<=1;
- SRCLK=1;
- _nop_();
- SRCLK=0;
- }
- RCLK=1;
- _nop_();
- RCLK=0;
- }
- void DigDisplay()
- {
- uchar i;
- uint j;
- float k;
- k=voltage*380; //这个值可以修正,依据是根据两个电阻的分压点计算的,同事放大1000倍,这样下面显示可以显示小数。
- j=(uint) k; //转换成INT类型,不然下面的编译不了。
-
- for(i=0;i<8;i++)
- {
- switch(i)
- {
- case(0):
- LSA=0;LSB=0;LSC=0;Hc595SendByte(number[vin/1000]); break;
- case(1):
- LSA=1;LSB=0;LSC=0;Hc595SendByte(number[vin%1000/100]); break;
- case(2):
- LSA=0;LSB=1;LSC=0; Hc595SendByte(number[vin%1000%100/10]);break;
- case(3):
- LSA=1;LSB=1;LSC=0;Hc595SendByte(number[vin%1000%100%10]); break; //显示当前测量的ADC的值,0-1023
- case(4):
- LSA=0;LSB=0;LSC=1; Hc595SendByte(number[j/1000]);break;
- case(5):
- LSA=1;LSB=0;LSC=1;Hc595SendByte(number[j%1000/100]&0xfd); break;
- case(6):
- LSA=0;LSB=1;LSC=1;Hc595SendByte(number[j%1000%100/10]); break;
- case(7):
- LSA=1;LSB=1;LSC=1; Hc595SendByte(number[j%1000%100%10]);break; //显示当前电压值
-
- }
-
- Delay1ms();
- Hc595SendByte(0xFF);
-
- }
- }
复制代码
所有资料51hei提供下载:
STC15W408AS电压表.zip
(39.41 KB, 下载次数: 107)
|