STC12C2052AD单片机0-9.9V电压表
- 格式:doc
- 大小:448.50 KB
- 文档页数:7
一种由STC12C2052AD单片机控制的改进型调压电路0 引言在ZXC10通信电源系统中,上位机输出的PWM调制信号的频率为1 kHz,而且系统要求电源能根据PWM信号的占空比进行调压。
即对电源输出电压在40 Vdc~60 Vdc范围内通过此PWM信号进行线性调节。
PWM信号5%占空比对应40±0.5 Vdc,95%的占空比对应60±0.5 Vdc。
以前此功能是用带有D/A的单片机来实现.即把PWM调制信号输入单片机,通过单片机来计算PWM信号的占空比,再根据PWM信号的占空比与输出电压的关系,并通过D/A转换来产生用于调节输出电压的偏移量,最后通过此偏移量和电源输出反馈量的共同作用来实现调压。
1 单片机调压系统通过带有D/A的单片机来实现调压系统的方框图如图1所示。
但是,由于带有D/A的单片机比较贵,因而会增加产品成本。
而如果把PWM 调制信号的频率提高,再经过一个简单的二阶有源低通滤波器来产生调压偏移量,则可用不带D/A转换的单片机来实现调压,这样可以大大节省成本。
其改进后的电路方框图如图2所示。
2 STC12C2052AD的PCA/PWM工作原理由于STC12C2052AD单片机是作于1个时钟/机器周期,且有增强型8051内核,故其速度比普通8051快8~12倍。
该单片机有2路可编程计数器阵列(PCA)/PWM,其中PCA1模块用作捕获模式,可识别输入的PWM调制信号,PCA0模块用作脉宽调节模式(PWM),可实现频率转换。
此外,由于该单片机价格比较便宜,故采用此单片机作为核心控制芯片。
2.1 STC12C2052AD单片机的PCA捕获模式STC12C2052AD系列单片机中的PCA可编程计数器阵列含有一个特殊的16位定时器,它可与2个16位捕获/比较模块相连。
每个模块可编程工作在4种模式下,即:上升/下降沿捕获、软件定时器、高速输出或可调制脉冲输出。
设计时,可将模块0连接到P3.7(CEX0/PCA0/PWM0),模块1连接到P3.5(CEX1/PCA1/PWM1)。
LCD显示的电压表#include <STC12C5A.h>#define data P0#define data1 P3#define ge 0x80+0x45#define yi 0x80+0x47 //小数点后一位#define er 0x80+0x48#define san 0x80+0x49/*定义ADC操作控制位,ADC_CONTR:ADC控制寄存器*/#define ADC_POWER 0x80 //ADC 电源控制位#define ADC_FLAG 0x10 //ADC 转换结束标志位#define ADC_START 0x08 //ADC 启动转换位#define ADC_SPEEDLL 0x00 //0010,0000,SPEED1=0,SPEED0=0,420个时钟周期转换一次#define ADC_SPEEDL 0x20 //0010,0000,SPEED1=0,SPEED0=1,280个时钟周期转换一次#define ADC_SPEEDH 0x40 //140个时钟周期转换一次#define ADC_SPEEDHH 0x60 //70个时钟周期转换一次sbit bf=P0^7;sbit rs=P2^0;sbit rw=P2^1;sbit en=P2^2;sbit test3=P3^1;sbit test1=P2^4;/*声明ADC相关特殊功能寄存器*/sfr ADC_LOW2 = 0xBE; //ADC 结果低2位/*----------------------------软件延时函数----------------------------*/void delay500ms (void){unsigned char i,j,k;for(i=15;i>0;i--)for(j=202;j>0;j--)for(k=81;k>0;k--);}void tiaoshi(unsigned char x){ P3=x;while(test1);while(!test1);P3=0xff;}/*----------------------------初始化ADC特殊功能寄存器函数----------------------------*/void InitADC(){ void _nop_(void);P1ASF = 0x01; //将P1所有口线设置成模拟口ADC_RES = 0; //清除上一次的转换结果ADC_LOW2=0;ADC_CONTR = 0x00;ADC_CONTR = ADC_POWER | ADC_SPEEDLL | ADC_START ; //设置ADC控制寄存器,包括接通电源、设置转换速度、转换通道、启动A/D转换等_nop_();_nop_();_nop_();_nop_(); //延时}void busy(void){ void _nop_(void);unsigned char x;do{data=0xff;en=1;rs=0;rw=1;_nop_();x=data;en=0;_nop_();}while(x&0x80);}void lcd_wcom(unsigned char com){ busy();rs=0;rw=0;en=1;data=com;en=0;}void lcd_wdat(unsigned char dat){ busy();rs=1;rw=0;en=1;data=dat;en=0;}void lcd_init(){ lcd_wcom(0x38);lcd_wcom(0x0c);lcd_wcom(0x06);lcd_wcom(0x01);}void main(){ void _nop_(void);unsigned char code str0[]="Channel 0:";unsigned char code str1[]=" Vio= . V";unsigned char i;unsigned int temp;unsigned long int temp1;float result;lcd_init();lcd_wcom(0x80);for(i=0; str0[i];i++)lcd_wdat( str0[i] );lcd_wcom(0x80+0x40);for(i=0; str1[i] ;i++)lcd_wdat( str1[i] );while(1){ for(i=100,temp1=0;i>0;i--){ InitADC(); //初始化ADC相关特殊功能寄存器,启动A/D 转换while(!(ADC_CONTR&ADC_FLAG));ADC_CONTR&=~ADC_FLAG;temp=ADC_RES;temp=temp<<2;temp=temp+ADC_LOW2;temp1=temp1+temp;}result=(float)temp1/100;result=result*5/1023;temp=result*1000;i=temp/1000;temp=temp%1000;i=i+0x30;lcd_wcom(ge);lcd_wdat(i);i=temp/100;temp=temp%100;i=i+0x30;lcd_wcom(yi);lcd_wdat(i);i=temp/10;temp=temp%10;i=i+0x30;lcd_wcom(er);lcd_wdat(i);i=temp;i=i+0x30;lcd_wcom(san);lcd_wdat(i);/* delay500ms (); */ }}。
STC12C2052AD之数字电压表0-99V做了N个ICL7107的数字电压表头都没有成功,今天改为带AD的单片机了。
AD部分代码来看网络。
电路就不发了。
数码管用四位共阳。
小数点后面有一点跳动,不过对于用面包板搭建的电路,应该算不错吧。
基准电压采用TL431.电压在2.61和2.37之间跳动。
/************************************************ **********************基于STC12C4052AD单片机的0-99V数字电压表程序数码之家首发。
ID:abenyaoP1.6口为0-5V模拟量输入端,P1.5口连接TL431l输出的2.5V基准电源,4位串行LED数码管显示************************************************* *********************/#include ; //单片机头文件#include ; //51基本运算(包括_nop_空函数)#define uchar unsigned char#define uint unsigned int#define LEDBus P3//a3.0-b3.1-c3.2-d3.3-e3.4-f3.5-g3.7-dp1.0#define ON 1//定义0为打开#define OFF 0//定义1为关闭sbit ge=P1^4;//个位位选sbit shi=P1^3;//十位位选sbit bai=P1^2;//百位位选sbit qian=P1^1;//千位位选sbit db=P1^0;char d[5];uint R,M,N;//若定义成uchar型就只能显示2.5V以下的数值uchar codeLEDTab[]={0xc0,0xf9,0x64,0x70,0x59,0x52,0x42,0xf8 ,0x40,0x58};/************************************************ *****************函数名:毫秒级CPU延时函数调用:delay (?);参数:1~65535(参数不可为0)返回值:无结果:占用CPU方式延时与参数数值相同的毫秒时间备注:应用于1T单片机时i;0;t--)//如果t大于0,t减1(外层循环)for(i=600;i>;0;i--);//i等于124,如果i大于0,i减1}/************************************************ *******************函数名:ADC初始化及8位A/D转换函数返回值:8位的ADC数据结果:读出指定ADC接口的A/D转换值,并返回数值备注:适用于STC12C2052AD系列单片机(必须使用STC12C2052AD.h头文件)************************************************* ******************/uchar Read (uchar CHA){uchar AD_FIN=0; //存储A/D转换标志;若在函数外定义此变量则不能得到连续变化的模拟量的显示/******以下为ADC初始化程序****************************/CHA &= 0x07;//选择ADC的8个接口中的一个(0000 0111 清0高5位)ADC_CONTR = 0x60; //ADC转换的速度(0XX0 0000 其中XX控制速度,请根据数据手册设置)_nop_();ADC_CONTR |= CHA;//选择A/D当前通道_nop_();ADC_CONTR |= 0x80;//启动A/D电源delay(1);//使输入电压达到稳定(1ms即可?/******以下为ADC执行程序****************************/ADC_CONTR |= 0x08;//启动A/D转换(0000 1000 令ADCS = 1)_nop_();_nop_();_nop_();_nop_();while (AD_FIN ==0){//等待A/D转换结束AD_FIN = (ADC_CONTR & 0x10); //0001 0000测试A/D转换结束否}ADC_CONTR &= 0xE7;//1111 0111 清ADC_FLAG位, 关闭A/D转换, return (ADC_DATA);//返回A/D转换结果(8位)}/************************************************ ******************显示函数转换函数:M=模拟量采样值,N=基准电压源采样值(本例为2.5V),R=模拟量输入值(待显示值)N=256*2.5/Vcc;变形后得Vcc=256*2.5/N;代入M=256*R/Vcc;得到M=R*N/2.5;变形后得R=M*2.5/N 1.105为输入端分压比。
【接线说明】【输入控制设备】【输出控制设备】【NPN输人开关接线方式举例说明】【PNP输人开关接线方式举例说明】【输出举例说明】【输出举例说明】(开关量输出、干接点输出)【UART通信说明】也可以通过TTL下载【原理图】提供PDF格式/******************************************************************** 程序说明:1、P1.7口输入开关信号控制数码管开始延时。
2、当数码管延时时间达到59分99秒时继电器吸合并保持吸合状态。
********************************************************************/#include<STC12C2052AD.h> //库文件#include<intrins.h>#define uchar unsigned char //宏定义字符型变量#define uint unsigned int //宏定义整型变量/********************************************************************IO口定义********************************************************************/uint playdate;uint datef=0;uint datem=0;uint sec; //定义计数值,每过1/10 秒,sec 加一uchar biaozhi=0;//按下次数值uint tcnt; //键值判断sbit P10=P1^0;//数码管段sbit P11=P1^1;//数码管段sbit P12=P1^2;//数码管段sbit P13=P1^3;//数码管段sbit P14=P1^4;//数码管段sbit P15=P1^5;//数码管段sbit P16=P1^6;//数码管段sbit P17=P1^7;//AD信号输入sbit P30=P3^0;//按键输入sbit P31=P3^1;//按键输入sbit P32=P3^2;//数码管位sbit P33=P3^3;//数码管位sbit P34=P3^4;//数码管位sbit P35=P3^5;//数码管位sbit OUT=P3^7; //继电器输出/********************************************************************初始定义*********************************************************************/code uchar seg7code[10]={ 0x84,0xf6,0x8a,0xa2,0xf0,0xa1,0x81,0xb6,0x80,0xa0}; //显示段码数码管字跟/********************************************************************延时函数*********************************************************************/void delay1(uchar t){uchar i,j;for(i=0;i<t;i++){for(j=13;j>0;j--);{ ;}}}/********************************************************************延时函数*********************************************************************/ void delay()//延时程序0.1秒{uchar m,n,s;for(m=10;m>0;m--)for(n=20;n>0;n--)for(s=248;s>0;s--);}/********************************************************************显示函数*********************************************************************/ void Led() //显示函数{/*****************数据转换*****************************/uint z,x,c,v;z=datef%100/10;; //求分十位x=datef%10; //求分个位c=datem%100/10; //求秒十位v=datem%10; //求秒个位P1M0=0X00;P1M1=0XFF;P3M0=0X00;P3M1=0XFF;P32=0;P33=0;P34=0;P35=0;P1=seg7code[z];P32=1;P33=0;P34=0;P35=0;delay1(80);P32=0;P33=0;P34=0;P35=0;P1=seg7code[x];P32=0;P33=1;P34=0;P35=0;delay1(80);P32=0;P33=0;P34=0;P35=0;P1=seg7code[c];P32=0;P33=0;P34=0;P35=1;delay1(80);P32=0;P33=0;P34=0;P35=0;P1=seg7code[v];P32=0;P33=0;P34=1;P35=0;delay1(80);P32=0;P33=0;P34=0;P35=0;}/********************************************************************按键函数*********************************************************************/void key(){if((P17==0)&&(biaozhi==0)){ delay1(250);if(P17==0){TR0=1;sec=0; OUT=1;biaozhi=1;}} }/********************************************************************定时中断服务函数*********************************************************************/ void t0(void) interrupt 1 using 0 //定时中断服务函数{tcnt++; //每过250ust tcnt 加一if(tcnt==3694) //计满400 次(1/10 秒)时4000为秒{tcnt=0; //重新再计sec++;if(sec==3600) //单位为秒60分00秒{OUT=0;TR0=0;//sec=0;}}}/********************************************************************主函数*********************************************************************/ void main(){TMOD=0x02; //定时器工作在方式2TH0=0x06; //对TH0 TL0 赋值TL0=0x06;TR0=0; //开始定时ET0=1;EA=1;sec=0;OUT=1;biaozhi=0;while(1){key();Led();datef=sec/60;datem=sec%60;}}/********************************************************************程序结束*********************************************************************/#include<STC12C2052AD.h> //库文件#include<intrins.h>#define uchar unsigned char //宏定义字符型变量#define uint unsigned int //宏定义整型变量/*声明SFR 相关与的IAP*/sfr IAP_DATA = 0xE2;sfr IAP_ADDRH = 0xE3;sfr IAP_ADDRL = 0xE4;sfr IAP_CMD = 0xE5;sfr IAP_TRIG = 0xE6;sfr IAP_CONTR = 0xE7;/********************************************************************定义ISP/IAP/EEPROM 命令*********************************************************************/ #define CMD_IDLE 0#define CMD_READ 1#define CMD_PROGRAM 2#define CMD_ERASE 3#define ENABLE_IAP 0x83//SYSCLK<12MH#define IAP_ADDRESS 0x0000 //存储地址/********************************************************************IO口定义********************************************************************/ bit write=0;uchar biaozhi=6;//按下次数值uint tcnt,sec; //键值判断uint datA,datB; //接通和断开存储值uchar tg,ts,tb; //接通个十百标志uchar dg,ds,db; //断开个十百标志uchar TDbz=0;//通断标志bit bz1=0;//输入标志sbit P10=P1^0;//数码管段sbit P11=P1^1;//数码管段sbit P12=P1^2;//数码管段sbit P13=P1^3;//数码管段sbit P14=P1^4;//数码管段sbit P15=P1^5;//数码管段sbit P16=P1^6;//数码管段sbit P17=P1^7;//AD信号输入sbit P30=P3^0;//按键输入sbit P31=P3^1;//按键输入sbit P32=P3^2;//数码管位sbit P33=P3^3;//数码管位sbit P34=P3^4;//数码管位sbit P35=P3^5;//数码管位sbit OUT=P3^7; //继电器输出/********************************************************************初始定义*********************************************************************/code uchar seg7code[10]={0xfB,0x89,0xf5,0xDD,0x8F,0xdE,0xfE,0xc9,0xfF,0xdF}; //显示段码数码管字跟/********************************************************************延时函数*********************************************************************/void delay1(uchar t){uchar i,j;for(i=0;i<t;i++){for(j=13;j>0;j--);{ ;}}}/********************************************************************延时函数*********************************************************************/ void delay()//延时程序0.1秒{uchar m,n,s;for(m=10;m>0;m--)for(n=20;n>0;n--)for(s=248;s>0;s--);}/********************************************************************接通显示函数*********************************************************************/ void LedT() //显示函数{/*****************数据转换*****************************/uint x,c,v;x=datA/100; //求百位c=datA%100/10; //求十位v=datA%10; //求个位P32=1;P33=1;P34=1;P35=1;P1=0Xef; //显示字母AP32=0;P33=1;P34=1;P35=1;delay1(80);P32=1;P33=1;P34=1;P35=1;P1=seg7code[x];P32=1;P33=0;P34=1;P35=1;delay1(80);P32=1;P33=1;P34=1;P35=1;P1=seg7code[c];P32=1;P33=1;P34=1;P35=0;delay1(80);P32=1;P33=1;P34=1;P35=1;P1=seg7code[v];P32=1;P33=1;P34=0;P35=1;delay1(80);P32=1;P33=1;P34=1;P35=1;}/********************************************************************断开显示函数*********************************************************************/ void LedD() //显示函数{/*****************数据转换*****************************/uint x,c,v;x=datB/100; //求百位c=datB%100/10; //求十位v=datB%10; //求个位P32=1;P33=1;P34=1;P35=1;P1=0Xbe; //显示字母BP32=0;P33=1;P34=1;P35=1;delay1(80);P32=1;P33=1;P34=1;P35=1;P1=seg7code[x];P32=1;P33=0;P34=1;P35=1;delay1(80);P32=1;P33=1;P34=1;P35=1;P1=seg7code[c];P32=1;P33=1;P34=1;P35=0;delay1(80);P32=1;P33=1;P34=1;P35=1;P1=seg7code[v];P32=1;P33=1;P34=0;P35=1;delay1(80);P32=1;P33=1;P34=1;P35=1;}/********************************************************************显示A函数*********************************************************************/ void LedA() //显示函数{/*****************数据转换*****************************/P32=1;P33=1;P34=1;P35=1;P1=0Xef; //显示字母BP32=0;P33=1;P34=1;P35=1;delay1(80);P32=1;P33=1;P34=1;P35=1;}/********************************************************************显示B函数*********************************************************************/ void LedB() //显示函数{/*****************数据转换*****************************/P32=1;P33=1;P34=1;P35=1;P1=0Xbe; //显示字母BP32=0;P33=1;P34=1;P35=1;delay1(80);P32=1;P33=1;P34=1;P35=1;}/********************************************************************按键函数*********************************************************************/void key(){if(P30==0){delay();if(P30==0){TR0=0;biaozhi++;if(biaozhi>6){biaozhi=0;}datA=tb*100+ts*10+tg;datB=db*1 00+ds*10+dg;while(!P30);write=1;}}if(biaozhi==0){LedA();P1=seg7code[tb];P32=1;P33=0;P34=1;P35=1;delay1(80);if(P31==0){delay();if(P 31==0){tb++; if(tb>9)tb=0;}while(!P31);}}if(biaozhi==1){LedA();P1=seg7code[ts];P32=1;P33=1;P34=1;P35=0;delay1(80);if(P31==0){delay();if(P 31==0){ts++; if(ts>9)ts=0;}while(!P31);}}if(biaozhi==2){LedA();P1=seg7code[tg];P32=1;P33=1;P34=0;P35=1;delay1(80);if(P31==0){delay();if(P 31==0){tg++; if(tg>9)tg=0;}while(!P31);}}if(biaozhi==3){LedB();P1=seg7code[db];P32=1;P33=0;P34=1;P35=1;delay1(80);if(P31==0){delay();if( P31==0){db++; if(db>9)db=0;}while(!P31);}}if(biaozhi==4){LedB();P1=seg7code[ds];P32=1;P33=1;P34=1;P35=0;delay1(80);if(P31==0){delay();if(P 31==0){ds++; if(ds>9)ds=0;}while(!P31);}}if(biaozhi==5){LedB();P1=seg7code[dg];P32=1;P33=1;P34=0;P35=1;delay1(80);if(P31==0){delay();if( P31==0){dg++; if(dg>9)dg=0;}while(!P31);datA=tb*100+ts*10+tg;datB=db*100+ds*10+dg;}}if(biaozhi==6){if(TDbz==0){LedT();}if(TDbz==1){LedD();}}/********************************************************************定时中断服务函数*********************************************************************/ void t0(void) interrupt 1 using 0 //定时中断服务函数{tcnt++; //每过250ust tcnt 加一if(tcnt==3810) //计满400 次(1/10 秒)时4000为秒{tcnt=0; //重新再计if(TDbz==0){datA--;if(datA==0){TDbz=1;OUT=0;}}if(TDbz==1){datB--;if(datB==0){TDbz=0;OUT=1;TR0=0;}}}}/******************************************************************** 禁用ISP/IAP/EEPROM functionmake 单片机在一安全状态*********************************************************************/ void IapIdle(){IAP_CONTR = 0; //IAP_CMD = 0; //IAP_TRIG = 0; //IAP_ADDRH = 0x80; //IAP_ADDRL = 0; //}/********************************************************************读数据*********************************************************************/uchar IapReadByte(uint addr){uchar dat;IAP_CONTR = ENABLE_IAP;IAP_CMD = CMD_READ;IAP_ADDRL = addr;IAP_ADDRH = addr >> 8;IAP_TRIG = 0x46;IAP_TRIG = 0xb9;_nop_();dat = IAP_DATA;IapIdle();return dat;}/********************************************************************写数据*********************************************************************/void IapProgramByte(uint addr, uchar dat){IAP_CONTR = ENABLE_IAP;IAP_CMD = CMD_PROGRAM;IAP_ADDRL = addr;IAP_ADDRH = addr >> 8;IAP_DATA = dat;IAP_TRIG = 0x46;IAP_TRIG = 0xb9;_nop_();IapIdle();}/********************************************************************擦除数据*********************************************************************/void IapEraseSector(uint addr){IAP_CONTR = ENABLE_IAP;IAP_CMD = CMD_ERASE;IAP_ADDRL = addr;IAP_ADDRH = addr >> 8;IAP_TRIG = 0x46;IAP_TRIG = 0xb9;_nop_();IapIdle();}/********************************************************************主函数*********************************************************************/ void main(){TMOD=0x02; //定时器工作在方式2TH0=0x06; //对TH0 TL0 赋值TL0=0x06;TR0=0; //定时开关ET0=1;EA=1;sec=0;OUT=1;P1M0=0X00;P1M1=0X7F;P3M0=0X00;P3M1=0XFF;tb = IapReadByte(0x01); //读取0x01中的数据ts = IapReadByte(0x02); //读取0x02中的数据tg = IapReadByte(0x03); //读取0x03中的数据db = IapReadByte(0x04); //读取0x02中的数据ds = IapReadByte(0x05); //读取0x03中的数据dg = IapReadByte(0x06); //读取0x03中的数据datA=tb*100+ts*10+tg;datB=db*100+ds*10+dg;P17=1;while(1){if((P17==0)&&(bz1==0)){delay1(180);if(P17==0){bz1=1;TR0=1;OUT=1;tcnt=0;datA=tb*100+ts*10+tg;datB=db*100+ds*10+dg;}}if((P17==1)&&(bz1==1)){bz1=0;}key();if(write==1){write=0;IapEraseSector(0); //擦除扇区IapProgramByte(0x01,tb);//写入数据IapProgramByte(0x02,ts);//写入数据IapProgramByte(0x03,tg);//写入数据IapProgramByte(0x04,db);//写入数据IapProgramByte(0x05,ds);//写入数据IapProgramByte(0x06,dg);//写入数据}}}/********************************************************************程序结束*********************************************************************/ #include<STC12C2052AD.h>#include<intrins.h>#include<math.h>#include "INTRINS.H"#define uchar unsigned char //宏定义字符型变量#define uint unsigned int //宏定义整型变量sfr IAP_DATA = 0xE2;sfr IAP_ADDRH = 0xE3;sfr IAP_ADDRL = 0xE4;sfr IAP_CMD = 0xE5;sfr IAP_TRIG = 0xE6;sfr IAP_CONTR = 0xE7;#define CMD_IDLE 0#define CMD_READ 1#define CMD_PROGRAM 2#define CMD_ERASE 3#define ENABLE_IAP 0x83//SYSCLK<12MH#define IAP_ADDRESS 0x0000 //存储地址void IapEraseSector(uint addr);//擦除数据void IapProgramByte(uint addr, uchar dat);//写数据uchar IapReadByte(uint addr);//读数据void IapIdle();//禁用ISP/IAP/EEPROM functionmake 单片机在一安全状态bit flag_eeprom1=0;//掉电存储的标志位sbit P32=P3^2;//数码管位sbit P33=P3^3;//数码管位sbit P34=P3^4;//数码管位sbit P35=P3^5;//数码管位sbit pa = P1^6;sbit pb = P1^0;sbit pc = P1^3;sbit pd = P1^4;sbit pe = P1^5;sbit pf = P1^1;sbit pg = P1^2;uint tcnt1=0;//用于刷新数码管uint g_uistopwatch1=0;//全局变量,在数码管上显示的一个变量uint qiannum1,bainum1,shinum1,genum1;unsigned int qiannum11,bainum11=0,shinum11=0,genum11=0;//用于传到数码管上显示sbit key1=P3^0;//key1sbit key2=P3^1;//key2sbit in=P1^7;//insbit out=P3^7;//outunsigned int innum=0;void seg7code(unsigned char num);void P3t1();void timer0_1init(void);//定时配置static unsigned char presstime=0;//时间值按键用到的unsigned int kf0=1;//按键用的标志位unsigned int kt0=0;//按键用的标志位void keyflag();//按键结束调用unsigned int if0=1,if1=1;unsigned int keynum=0;//数码管的位unsigned int inum1=0;unsigned char inum11=0,inum12=0,innum1=0,innum2=0;void displaynums(){//将数字传到数码管上显示if(if0==1){g_uistopwatch1=innum;if(innum>=inum1){out=0;}else{out=1;}}else{inum1=qiannum11*1000+bainum11*100+shinum11*10+genum11; //将num1三个数码管的值付给inumg_uistopwatch1=inum1;}}void keycan(){//按键if(key1==0){//当按键1按下if(kf0){//当标志位kf0=1的时候进行if(presstime>80){//当时间值大于一百的时候kf0=0;//标志位kf0=0kt0=1;//标志位kt0=0presstime=0;//时间清零,重新进行if0=0;if1=1;keynum++;//数码管的位if(keynum==5){//当位到4则置位0keynum=0;if0=1;}}}}else{//当按键松开keyflag();}//按键1结束if(key2==0){if(kf0){if(presstime>80){kf0=0;kt0=1;presstime=0;flag_eeprom1=1;if(keynum==0){if1++;if(if1==2){if0=0;}if(if1==3){innum=0;if1=1;if0=1;}}else{switch(keynum){case 1:qiannum11++;//数码管一加加if(qiannum11>9){//当数码管一加加到9时置为1qiannum11=0;}break;case 2:bainum11++;if(bainum11>9){bainum11=0;}break;case 3:shinum11++;if(shinum11>9){shinum11=0;}break;case 4:genum11++;if(genum11>9){genum11=0;}break;default:break;}}}}}else{keyflag();}//松开按键进行显示}void main(){P1M0=0X00;P1M1=0XFF;timer0_1init();inum11 = IapReadByte(0x01); //读取0x01中的数据inum12 = IapReadByte(0x02); //读取0x01中的数据innum1 = IapReadByte(0x03); //读取0x01中的数据innum2 = IapReadByte(0x04); //读取0x01中的数据inum1=inum11*100+inum12;innum=innum1*100+innum2;g_uistopwatch1=innum;qiannum11=inum1/1000;bainum11=inum1/100%10;shinum11=inum1/10%10;genum11=inum1%10;while(1){keycan();//按键displaynums();if(in==0){//in按下if(kf0){//当标志位kf0=1的时候进行if(presstime>80){//当时间值大于一百的时候kf0=0;//标志位kf0=0kt0=1;//标志位kt0=0presstime=0;//时间清零,重新进行flag_eeprom1=1;innum++;}}}else{//当按键松开keyflag();}//in结束if(flag_eeprom1==1){//加掉电存储,必需加到这,不然有一些小问题flag_eeprom1=0;inum11=inum1/100;//把int型的值拆分到char型inum12=inum1%100;innum1=innum/100;//把int型的值拆分到char型innum2=innum%100;IapEraseSector(0); //擦除扇区IapProgramByte(0x01,inum11);//写入数据IapProgramByte(0x02,inum12);//写入数据IapProgramByte(0x03,innum1);//写入数据IapProgramByte(0x04,innum2);//写入数据}}}void timer0(void)interrupt 1 {//500等于1秒TL0 = 0xCD; //重新设置定时器0时间为2msTH0 = 0xF8; //重新设置定时器0的初始值tcnt1++;presstime++;genum1=g_uistopwatch1%10;//个位shinum1=g_uistopwatch1%100/10;//十位bainum1=g_uistopwatch1%1000/100;//百位qiannum1=g_uistopwatch1/1000;//qian位switch(tcnt1){case 1:P3t1();seg7code(qiannum1);if(keynum==1 || keynum==0){P32=0;}break;case 2:P3t1();seg7code(bainum1); if(keynum==2 || keynum==0){P33=0;}break;case 3:P3t1();seg7code(shinum1); if(keynum==3 || keynum==0){P35=0;}break;case 4:P3t1();seg7code(genum1); if(keynum==4 || keynum==0){P34=0;}break;default:tcnt1=0;break;}}void timer0_1init(void){//定时配置TMOD=0x11;//将定时器0,1都设置为模式1TL0 = 0xCD;//设置定时器0时间为2msTH0 = 0xF8;//设置定时器0的初始值TR0=1;//开启定时器0TR1=1;//开启定时器1EA=1;//开总中断ET0=1;//开定时器0的中断}void s0(){pa = 1;pb = 1;pc = 1;pd = 1;pe = 1;pf = 1;pg = 0;} void s1(){pb = 1;pc = 1;pa = 0;pg = 0;pd = 0;pe = 0;pf = 0;} void s2(){pa = 1;pb = 1;pg = 1;pe = 1;pd = 1;pf = 0;pc = 0;} void s3(){pa = 1;pb = 1;pg = 1;pc = 1;pd = 1;pf = 0;pe = 0;} void s4(){pb = 1;pg = 1;pc = 1;pf = 1;pa = 0;pd = 0;pe = 0;} void s5(){pa = 1;pg = 1;pc = 1;pd = 1;pf = 1;pe = 0;pb = 0;} void s6(){pa = 1;pg = 1;pc = 1;pd = 1;pf = 1;pe = 1;pb = 0;} void s7(){pa = 1;pb = 1;pc = 1;pf = 0;pe = 0;pd = 0;pg = 0;} void s8(){pa = 1;pb = 1;pg = 1;pc = 1;pd = 1;pf = 1;pe = 1;} void s9(){pa = 1;pb = 1;pg = 1;pc = 1;pd = 1;pf = 1;pe = 0;} void s10(){pa =0;pb = 0;pc = 0;pf = 0;pe = 0;pd = 0;pg = 0;} void seg7code(unsigned char num){if(num == 0){s0();}else if(num == 1){s1();}else if(num == 2){s2();}else if(num == 3){s3();}else if(num == 4){s4();}else if(num == 5){s5();}else if(num == 6){s6();}else if(num == 7){s7();}else if(num == 8){s8();}else if(num == 9){s9();}}void P3t1(){P32=1;P33=1;P34=1;P35=1;}void keyflag(){//按键结束调用,按键的建议使用,这样可以减小code,但是触发的不建议if(kt0){//当标志位kt0=1的时候进行if(presstime>50){//当时间值大于一百的时候kf0=1;//标志位kf0=1kt0=0;//标志位kt0=0presstime=0;//时间清零,重新进行}}}/********************************************************************禁用ISP/IAP/EEPROM functionmake 单片机在一安全状态*********************************************************************/void IapIdle(){IAP_CONTR = 0; //IAP_CMD = 0; //IAP_TRIG = 0; //IAP_ADDRH = 0x80; //IAP_ADDRL = 0; //}/********************************************************************读数据*********************************************************************/uchar IapReadByte(uint addr){uchar dat;IAP_CONTR = ENABLE_IAP;IAP_CMD = CMD_READ;IAP_ADDRL = addr;IAP_ADDRH = addr >> 8;IAP_TRIG = 0x46;IAP_TRIG = 0xb9;_nop_();dat = IAP_DATA;IapIdle();return dat;}/********************************************************************写数据*********************************************************************/void IapProgramByte(uint addr, uchar dat){IAP_CONTR = ENABLE_IAP;IAP_CMD = CMD_PROGRAM;IAP_ADDRL = addr;IAP_ADDRH = addr >> 8;IAP_DATA = dat;IAP_TRIG = 0x46;IAP_TRIG = 0xb9;_nop_();IapIdle();}/********************************************************************擦除数据*********************************************************************/void IapEraseSector(uint addr){IAP_CONTR = ENABLE_IAP;IAP_CMD = CMD_ERASE;IAP_ADDRL = addr;IAP_ADDRH = addr >> 8;IAP_TRIG = 0x46;IAP_TRIG = 0xb9;_nop_();IapIdle();}【尺寸图】【图片展示】【加装配套外壳效果】。
单片机课程设计数字电压表目录第1章课题的设计要求、目的、意义 ................................................................... 1 1.1课题的设计要求: ......................................................................... ................. 1 1.2课题的设计目的与意义: ......................................................................... ..... 1 第2章系统总体方案选择与说明 ...........................................................................2 2.1通道转换方案设计 ........................................................................... ............... 2 2.2显示部分方案设计 ........................................................................... ............... 2 第3章系统结构框图与工作原理 ...........................................................................3 3.1 系统结构框图 ........................................................................... ...................... 3 3.2 工作原理 ........................................................................... .............................. 4 第4章各单元硬件设计说明及计算方法 ............................................................... 5 4.1单片机的选择 ........................................................................... ....................... 5 4.2时钟电路与复位电路的设计 ..........................................................................6 4.3LED显示电路设计与器件选择 (7)4.4 A/D转换电路和测量电路的设计 ................................................................... 9 第5章软件设计与说明 ........................................................................... .............. 11 5.1系统软件设计(流程图) ......................................................................... ... 11 5.2 程序设计 ....................................................................................................... 12 第6章使用说明与调试结果 ........................................................................... ...... 13 总结 ........................................................................... ................................................ 14 参考资料 ........................................................................... ........................................ 15 附录1 系统原理图 ........................................................................... ....................... 16 附录2 程序清单 ........................................................................... (17)第1章课题的设计要求、目的、意义1.1课题的设计要求:设计并制作用单片机控制一个数字式电压表。
使用STC12C5204AD单片机的数字电压表这是一块使用STC12C5204AD数字电压表的制作程序,P0.0-P0.3 共阴数码管位驱动端,P2口为共阴数码管段a-g及dp的段驱动端口,P0、P2口设置为推挽输出方式,段输出加470欧限流电阻,AD为8位,转换电压分度5/256=0.0195312V,分流电阻为实测阻值,AD值*0.0195312v/对地分流电阻,算出分流电流,然后用分流电流*分流电阻与限流电阻之和即为要显示的输入电压值。
业余使用,精度已经够用了,比那个小的指针的要准确多了。
其中涉及到端口设置的地方大家对照芯片手册更正。
#include ; //STC12C5204AD头文件 (6 K) 下载次数:15 #include ;//_nop_();#define uchar unsigned char#define uint unsigned int//sfr ADC_CONTR=0XBC;//adc使能位.ADC电源控制位sfr ADC_RES=0XBD;// adc数据高八位,即ADC值sfr P1ASF=0X9D;//P1各端口ADC使能端uchar led_bcd[]={0x3F,/*0*/ //共阴数码管0x06,/*1*/0x5B,/*2*/0x4F,/*3*/0x66,/*4*/0x6D,/*5*/0x7D,/*6*/0x07,/*7*/0x7F,/*8*/0x6F,/*9*/0x00,/* */0x7c /*b*/},ad_data;uint data dis[5]={0x00,0x00,0x00,0x00,0x00},ZZ; //定义四个显示数据单元和一个数据存储单元//dis[4,3,2,1,5] 显示:12.345为存储单元/************************************************ *******************//* 延时子程序*//**//**//************************************************ *******************/void delay(uint z)//延时子函数{uchar de1,de2;for(de1=z;de1>;0;de1--)for(de2=100;de2>;0;de2--);}/*******************************************************///显示子函数 display(h1,h2,h3,h4)//h1,h2,h3,h4 为四位LED数码管显示变量///////************************************************ *******/void display(uchar h1,uchar h2,uchar s1,uchar s2) ////LED显示函数(参数:LED1,LED2,LED3,LED4) {// 第一个数码管显示数据if(h1==0x3f) h1=0x00;//0消隐语句P2=h1;//delay(2);P00=0;delay(2);//参数2-10数值大LED亮度高但闪烁感强,数值小LED亮度低,但闪烁感小.P2=0X00;P00=1;/************************************************ *******/// 第二个数码管显示数据P2=h2|0x80;//delay(2);P01=0;delay(2); //参数2-10数值大LED亮度高但闪烁感强,数值小LED亮度低,但闪烁感小.P2=0X00;P01=1;//delay(5);/************************************************ *******/// 第三个数码管显示数据P2=s1;//delay(2);P02=0;delay(2); //参数2-10数值大LED亮度高但闪烁感强,数值小LED亮度低,但闪烁感小.P2=0X00;P02=1;// delay(5);/************************************************ *******/// 第四个数码管显示数据P2=s2;//delay(2);P03=0;delay(2); //参数2-10数值大LED亮度高但闪烁感强,数值小LED亮度低,但闪烁感小.P2=0X00;P03=1;//delay(5);}void init()//系统初始化函数{P2M1=0Xff; //强推挽推动a-g dpP2M0=0X00; //强推挽推动a-g dpP0M1=0X0f; //强推挽推动位P0M0=0X00; //强推挽推动位P0=0XFF;//初始化P2=0;//初始化/***定时器0初始化设置*****/TMOD = 0x01;TH0 = 0xFC; //初值1msTL0 = 0x18; //初值1msEA = 1;//开总中断ET0 = 1; //定时器0中断打开TR0 = 1; //打开定时器开始计时/*************************/ZZ=0;}void initADC() //AD初始化{P1ASF=0x01;//只使用P1.0端口做为ADC输入端.ADC_RES=0;//ADC数据寄存器清零ADC_CONTR=ADC_POWER|ADC_SPEEDLL; //打开ADC开关并设置转换速率详见STC12C52.Hdelay(2); //打开ADC并延时.}uchar readADC()//读AD{ADC_CONTR=ADC_POWER|ADC_SPEEDLL|0|ADC_START;_nop_();_nop_();_nop_();_nop_();while(!(ADC_CONTR&ADC_FLAG));//等待转换完成标志ADC_CONTR&=~ADC_FLAG;//close ADCreturn ADC_RES;//返回ADC值.}void main(){init();initADC();//初始化ADCad_data=readADC();//开机转换while(1){float j;uchar ad_data;while(ZZ>;=500) //500毫秒读一次ADC{ad_data=readADC();//读入ADC数据ZZ=0;}j=ad_data*19.5312;//由AD数据*19.5312(放大1000倍)=分流后的电压j=j/9890; //j(电压)/接地电阻(实测)9890欧j=j*60190;//j(电流)*(输入限流电阻(实测)60190欧+接地电阻(实测)9890欧) 计算出实际输入电压如果使用高精度电阻,则直接输入电阻值dis[4]=j/1000;dis[3]=dis[4]/10;dis[2]=dis[4]%10;//h=(h-(dis[3]*10+dis[2]))*100;dis[4]=j/10-dis[4]*100;//dis[4]=j%100;//小数位第一位dis[1]=dis[4]/10;dis[0]=dis[4]%10;//小数位第二位//delay(10000);}}void Timer0Interrupt(void) interrupt 1{ZZ++;//AD读取间隔时间控制TH0 = 0xFC;TL0 = 0x18;display(led_bcd[dis[3]],led_bcd[dis[2]],led_bcd[d is[1]],led_bcd[dis[0]]);}。
STC12C2052AD AD转换C程序+PWM输出功能实现
功能:STC12C2052AD AD转换C程序+PWM输出功能成功使用。
应用:AD检测电压进行过欠压保护(继电器控制)+PWM把直流电压斩波成脉动直流。
板子功能:给手机电池充电。
降压用的LM317,小电流应用应该够了。
没时间去买开关管,就用的9013开关。
图纸:
//以下是成功了的程序。
如果你需要应用在你自己的项目中,您只需要更改io就能直接应用了
//程序的完整版本下载地址:
#include //stc单片机专用的头文件
#include
#define uchar unsigned char
#define uint unsigned int
#define AD_SPEED 0x60 //0110,0000 1 1 270个时钟周期转换一次,
/************河北正定欢迎您!少占鱼欢迎您!******************************/
//
sbit M=P1 ; //过压指示灯
sbit N=P1 ; //欠压指示灯
sbit LED=P1 ; //工作正常灯
sbit CONTRL=P3 ; //输出控制端
sbit PWM=P3 ;
/****************************************************************/
void pwm();
void delayms(uint);
uint ADC();。
STC12 系列单片机简要介绍(罗列STC单片机解密型号)1. STC12系列单片机为增强型8051 芯片,1T,单时钟/ 机器周期,指令代码完全兼容传统8051单片机。
2. 工作电压:STC12C5410AD 系列工作电压:5.5V - 3.8V(5V 单片机)/3.8V - 2.4V(3V 单片机)STC12C2052AD 系列工作电压:5.5V - 3.4V(5V 单片机)/3.8V - 2.4V(3V 单片机,可到2V)3. 工作频率范围:0 - 35 MHz,相当于普通8051 的0~420MHz.实际工作频率可达48MHz4. 用户应用程序空间12K / 10K / 8K / 6K / 4K / 2K / 1K 字节5. 片上集成512 字节RAM(STC12C5410AD 系列), STC12C2052AD 系列单片机为256 字节RAM6. 通用I/O 口(27/23/15 个),复位后为:准双向口/ 弱上拉(普通8051 传统I/O 口)可设置成四种模式:准双向口/ 弱上拉,推挽/ 强上拉,仅为输入/ 高阻,开漏每个I/O 口驱动能力均可达到20mA,但整个芯片最大不得超过55mA7. ISP(在系统可编程)/IAP(在应用可编程),无需专用编程器,无需专用仿真器可通过串口(P3.0/P3.1)直接下载用户程序,数秒即可完成一片8. EEPROM 功能9. 看门狗10.内部集成MAX810 专用复位电路(外部晶体20M 以下时,可省外部复位电路)11. 时钟源:外部高精度晶体/ 时钟,内部R/C 振荡器用户在下载用户程序时,可选择是使用内部R/C 振荡器还是外部晶体/ 时钟常温下内部R/C 振荡器频率为:5.2MHz ~ 6.8MHz精度要求不高时,可选择使用内部时钟,但因为有制造误差和温漂,应认为是4MHz ~8MHz12. 共2 个16 位定时器/ 计数器,但可用PCA 模块再产生4 个定时器(2052 系列只有两路PCA)13. 外部中断2 路,下降沿中断或低电平触发中断,Power Down 模式可由外部中断唤醒14. PWM(4 路)/PCA(可编程计数器阵列,4 路),5410 系列是4 路,2052 系列只有两路--- 也可用来当4 路D/A 使用--- 也可用来再实现4 个定时器--- 也可用来再实现4 个外部中断(上升沿中断/ 下降沿中断均可分别或同时支持)15. A/D 转换, 10 位精度ADC,共8 路。
目录1 前言 (1)2 系统方案设计 (2)2.1 电子秤的设计要求 (2)2.2 实验原理 (2)3 硬件设计 (3)3.1控制器部分 (3)3.2 数据采集部分 (4)3.2.1 传感器 (4)3.2.2 前级放大器部分 (5)3.2.3 A/D 转换器 (7)3.3 人机交互界面 (7)3.4总体工作电路原理图 (8)4 具体实现方案 (9)4.1 A/D转换程序的设计 (9)4.2 显示程序的设计 (10)5 设计体会 (11)参考文献 (12)附录 (13)1 前言电子称重技术从静态称重向动态称重发展:计量方法从模拟测量向数字测量发展;测量特点从单参数测量向多参数测量发展,特别是对快速称重和动态称重的研究与应用。
电子称重技术基本达到国际上20世纪90年代中期的水平,少数产品的技术已处于国际领先水平。
国内的电子秤市场中,1009左右量程的电子秤精度一般为0.019即10mg。
在研究方法上,电子称重系统的工作原理一般是将作用在承载器上的质量或力的大小,通过压力传感器转换为电信号,并通过控制电路来处理该电信号。
但就总体而言,我国电子衡器产品的数量和质量与工业发达国家相比还有较大差距,其主要差距是技术与工艺不够先进、工艺装备与测试仪表老化、开发能力不足、产品的品种规格较少、功能不全、稳定性和可靠性较差等。
称量是市场交易中很基本的活动,是商业领域最基本的衡具。
传统的量具是杆称或盘称,20世纪70年代开始出现了电子称。
早期的电子称多通过模拟电路实现,随着电子技术的不断发展,数字芯片的价格逐渐下降,模拟控制已逐步被数字控制所替代,电子称的设计模式也大都以微处理器为核心,使精度和可靠性都有了明显得提高。
因为小型商用电子称对适时性要求不高,运算也不太复杂,所以用8位微处理器足可满足要求。
本系统采用单片机STC12C2052AD 为控制核心,实现电子秤的基本控制功能。
系统的硬件部分包括最小系统板,数据采集、人机交互界面三大部分。