{感谢原作者提供}
//STC多用下载器
//单片机用STC15W208AS,频率为22.1M,注意单片机只有时钟0及2
//功能有串口自动断电下载,4路输入电压检测(最大值25V),输
//出5v及3.3V的检测,输出电流检测,外接输入电压检测,及单片机的电压检测。
//串口监控下载,如连续为0X7F的值,就说明要断电重启下载数据,
//串口断电控制方式,每0.1s变一次波特率,如收到是7F的值,
//就停止变波特率,判断是否是连接7F,如是就断电重启。
//4输入的最大值为25v,电流最大值为2a
//开关的作用,短按为换页,长按为输出电源控制开关。
单片机源程序如下:
- #include <STC15W408AS.h>
- #include <intrins.h>
- #include <oled.h>
- unsigned char oldkey,keyval,jisu,rxdatvol,RSjisu,onjisu,RETjisu,kkkkjisu;
- unsigned int keyjixu;
- bit readtimekong,disppagebit,powonkong,time02s,RSPOWonkong,kkkk,time01kong;
- unsigned char STCADbit[9];
- unsigned int STCADvol[9],voldat[9];
- unsigned char tetete;
- sbit KEY1=P5^5;
- sbit LEDout=P5^4;
- sbit POWkong=P3^7;
- void delay(unsigned int t) //长延时程序,延时t毫秒,STC 1T单片机11.0592M晶振I值为648,22.1I值为1298,12MI值为705。
- {
- unsigned int i;
- while(t--)
- {
- for(i=705;i>0;i--);
- }
- }
- void delay1() //
- {
- unsigned int i;
- for(i=340;i>0;i--);
-
- }
- //以下为AD检测
- void ADCINT()
- {
- P1M1=0xff;//AD高阻
- P1ASF=0xff;//设置 P1为AD口,根据实际设置。
- ADC_RES=0;//ad清0
- // AUXR1=0x04;//设置数据方式,低8位+高2位方式,易于运算。
- CLK_DIV=0X20;//由于408AS与204E不同,需写成这。
- }
- unsigned int ADCwrite(unsigned char ch)
- { //由于所检测的电压不用快,所以采用查询或延时法,没用中断法。 ch值从0-7,对应为P10-P17
- unsigned int x;
- ADC_CONTR=0x88+ch;//设置启动 ,用慢速采集
- //查询法。查询是否完成AD,由于是单片机内的,如出错单片机也出错,所以没做跳开处理。
- while ( !(ADC_CONTR & 0x10) );//等待A/D转换结束(ADC_FLAG==0)
- ADC_CONTR &= 0xE7; //11100111,置ADC_FLAG=0清除结束标记, 置ADC_START=0关闭A/D 转换
- //delay(1);//延时法。由于设置及晶振的原因,大约为20US完成过程。这里延时1MS
- x=ADC_RES*256+ADC_RESL;
- return x;
- }
- void nowtempAD()
- {//采用采集10次取平均值,整个采集时间在20MS,防止交流干扰。 每0.2S运行一次
- //0为3.3V,1为输入1,2为输入2,3为输入3,4为输入4,5为+5V,6为外接IN,7为电流,8为计算出来的单片机电压CPU。
- unsigned char x,xx;
- unsigned int k=0;
- unsigned long y;
- bit ll=0;
- for(x=0;x<9;x++)
- {
- STCADvol[x]=0;
- }
-
-
- for(x=0;x<10;x++)//采集10次。
- {
- P1ASF=0x00;
- STCADvol[0]=ADCwrite(0)+STCADvol[0];//1.25V基准
- delay1();
- P1ASF=0xff;
- for(xx=0;xx<8;xx++)
- {
- STCADvol[xx+1]=ADCwrite(xx)+STCADvol[xx+1];
- }
- }
- //以下为计算
- for(x=0;x<9;x++)
- {
- STCADvol[x]=STCADvol[x]/10;
- if(STCADvol[x]>1000)
- {
- STCADbit[x]=1;
- }
- else
- {
- STCADbit[x]=0;
- }
- }
- //0为3.3V,1为输入1,2为输入2,3为输入3,4为输入4,5为+5V,6为外接IN,7为电流,8为计算出来的单片机电压CPU。
- //以下的125等值是用于修改的。如电压与实测不同,需修改这个值。
- y=(long)1024*125/STCADvol[0];//STCADvol[0]为基准
- voldat[8]=y;//8为计算出来的单片机电压CPU。
- y=(long)STCADvol[1]*124/STCADvol[0];
- voldat[0]=y;////0为3.3V,
- y=(long)STCADvol[2]*685/STCADvol[0];
- voldat[1]=y;//1为输入1,
- y=(long)STCADvol[3]*703/STCADvol[0];
- voldat[2]=y;//2为输入2,
- y=(long)STCADvol[4]*706/STCADvol[0];
- voldat[3]=y;//3为输入3,
- y=(long)STCADvol[5]*702.5/STCADvol[0];
- voldat[4]=y;//4为输入4,
- y=(long)STCADvol[6]*248/STCADvol[0];
- voldat[5]=y;//5为+5V,
- y=(long)STCADvol[7]*53/STCADvol[0];
- voldat[6]=y;//6为外接IN,
- y=(long)STCADvol[8]*59/STCADvol[0];
- voldat[7]=y;//7为电流,
- }
- void disp0(bit all)
- {
- if(all==1)
- {
- OLED_Clear();
-
- OLED_ShowCHinese(4,0,0);
- OLED_ShowCHinese(20,0,1);
- OLED_ShowCHinese(36,0,2);
- OLED_ShowChar(52,0,13);
- OLED_ShowChar(60,0,14);
- OLED_ShowChar(68,0,15);
- OLED_ShowCHinese(76,0,3);
- OLED_ShowCHinese(92,0,4);
- OLED_ShowCHinese(108,0,5);
-
- //+5V:5.05V
- OLED_ShowChar(0,2,18);
- OLED_ShowChar(12,2,5);
- OLED_ShowChar(24,2,19);
- OLED_ShowChar(32,2,10);
- OLED_ShowChar(72,2,19);
- //3.3V:3.30V
- OLED_ShowChar(0,4,3);
- OLED_ShowChar(8,4,20);
- OLED_ShowChar(16,4,3);
- OLED_ShowChar(24,4,19);
- OLED_ShowChar(32,4,10);
- OLED_ShowChar(72,4,19);
- //电流:0.50A
- OLED_ShowCHinese(0,6,6);
- OLED_ShowCHinese(16,6,8);
- OLED_ShowChar(32,6,10);
- OLED_ShowChar(72,6,21);
- //IN:12.5V
- OLED_ShowChar8x6(98,2,17);
- OLED_ShowChar8x6(104,2,18);
- OLED_ShowChar8x6(110,2,16);
- OLED_ShowChar(119,3,19);
- //CPU:5.05V
- OLED_ShowChar8x6(95,5,19);
- OLED_ShowChar8x6(101,5,20);
- OLED_ShowChar8x6(107,5,21);
- OLED_ShowChar8x6(113,5,16);
- OLED_ShowChar(119,6,19);
- }
- //0为3.3V,1为输入1,2为输入2,3为输入3,4为输入4,5为+5V,6为外接IN,7为电流,8为计算出来的单片机电压CPU。
- //+5V值
- if(STCADbit[6]==1)
- {//OL
- OLED_ShowChar(40,2,22);
- OLED_ShowChar(48,2,23);
- OLED_ShowChar(56,2,11);
- OLED_ShowChar(64,2,11);
- }
- else
- {
- OLED_ShowChar(40,2,voldat[5]/100);
- OLED_ShowChar(48,2,20);
- OLED_ShowChar(56,2,voldat[5]%100/10);
- OLED_ShowChar(64,2,voldat[5]%10);
- }
- //3.3V值
- if(STCADbit[1]==1)
- {
- OLED_ShowChar(40,4,22);
- OLED_ShowChar(48,4,23);
- OLED_ShowChar(56,4,11);
- OLED_ShowChar(64,4,11);
- }
- else
- {
- OLED_ShowChar(40,4,voldat[0]/100);
- OLED_ShowChar(48,4,20);
- OLED_ShowChar(56,4,voldat[0]%100/10);
- OLED_ShowChar(64,4,voldat[0]%10);
- }
- //电流值
- if(STCADbit[8]==1)
- {
- OLED_ShowChar(40,6,22);
- OLED_ShowChar(48,6,23);
- OLED_ShowChar(56,6,11);
- OLED_ShowChar(64,6,11);
- }
- else
- {
- OLED_ShowChar(40,6,voldat[7]/100);
- OLED_ShowChar(48,6,20);
- OLED_ShowChar(56,6,voldat[7]%100/10);
- OLED_ShowChar(64,6,voldat[7]%10);
- }
- //IN值
- if(STCADbit[7]==1)
- {
- OLED_ShowChar(88,3,22);
- OLED_ShowChar(96,3,23);
- OLED_ShowChar(104,3,11);
- OLED_ShowChar(111,3,11);
- }
- else
- {
- OLED_ShowChar(88,3,voldat[6]/100);
- OLED_ShowChar(96,3,voldat[6]%100/10);
- OLED_ShowChar(104,3,20);
- OLED_ShowChar(111,3,voldat[5]%10);
- }
- //CPU值
- OLED_ShowChar(88,6,voldat[8]/100);
- OLED_ShowChar(96,6,20);
- OLED_ShowChar(103,6,voldat[8]%100/10);
- OLED_ShowChar(111,6,voldat[8]%10);
-
-
- }
- void disp1(bit all)
- {
- if(all==1)
- {
- OLED_Clear();
-
- //电压1:12.55V
-
- OLED_ShowCHinese(0,0,6);
- OLED_ShowCHinese(16,0,7);
- OLED_ShowChar(32,0,1);
- OLED_ShowChar(40,0,10);
- OLED_ShowChar(68,0,20);
- OLED_ShowChar(92,0,19);
- //电压2:12.55V
- OLED_ShowCHinese(0,2,6);
- OLED_ShowCHinese(16,2,7);
- OLED_ShowChar(32,2,2);
- OLED_ShowChar(40,2,10);
- OLED_ShowChar(68,2,20);
- OLED_ShowChar(92,2,19);
- //电压3:12.55V
- OLED_ShowCHinese(0,4,6);
- OLED_ShowCHinese(16,4,7);
- OLED_ShowChar(32,4,3);
- OLED_ShowChar(40,4,10);
- OLED_ShowChar(68,4,20);
- OLED_ShowChar(92,4,19);
- //电压4:12.55V
- OLED_ShowCHinese(0,6,6);
- OLED_ShowCHinese(16,6,7);
- OLED_ShowChar(32,6,4);
- OLED_ShowChar(40,6,10);
- OLED_ShowChar(68,6,20);
- OLED_ShowChar(92,6,19);
- }
- //0为3.3V,1为输入1,2为输入2,3为输入3,4为输入4,5为+5V,6为外接IN,7为电流,8为计算出来的单片机电压CPU。
- //电压1值
- if(STCADbit[2]==1)
- {
- OLED_ShowChar(52,0,22);
- OLED_ShowChar(60,0,23);
- OLED_ShowChar(76,0,11);
- OLED_ShowChar(84,0,11);
- }
- else
- {
- OLED_ShowChar(52,0,voldat[1]/1000);
- OLED_ShowChar(60,0,voldat[1]%1000/100);
- OLED_ShowChar(76,0,voldat[1]%100/10);
- OLED_ShowChar(84,0,voldat[1]%10);
- }
- //电压2值
- if(STCADbit[3]==1)
- {
- OLED_ShowChar(52,2,22);
- OLED_ShowChar(60,2,23);
- OLED_ShowChar(76,2,11);
- OLED_ShowChar(84,2,11);
- }
- else
- {
- OLED_ShowChar(52,2,voldat[2]/1000);
- OLED_ShowChar(60,2,voldat[2]%1000/100);
- OLED_ShowChar(76,2,voldat[2]%100/10);
- OLED_ShowChar(84,2,voldat[2]%10);
- }
- //电压3值
- if(STCADbit[4]==1)
- {
- OLED_ShowChar(52,4,22);
- OLED_ShowChar(60,4,23);
- OLED_ShowChar(76,4,11);
- OLED_ShowChar(84,4,11);
- }
- else
- {
- OLED_ShowChar(52,4,voldat[3]/1000);
- OLED_ShowChar(60,4,voldat[3]%1000/100);
- OLED_ShowChar(76,4,voldat[3]%100/10);
- OLED_ShowChar(84,4,voldat[3]%10);
- }
- //电压4值
- if(STCADbit[5]==1)
- {
- OLED_ShowChar(52,6,22);
- OLED_ShowChar(60,6,23);
- OLED_ShowChar(76,6,11);
- OLED_ShowChar(84,6,11);
- }
- else
- {
- OLED_ShowChar(52,6,voldat[4]/1000);
- OLED_ShowChar(60,6,voldat[4]%1000/100);
- OLED_ShowChar(76,6,voldat[4]%100/10);
- OLED_ShowChar(84,6,voldat[4]%10);
- }
- }
- //***********************键盘扫描子程序。******************
- //*********************************************************
- unsigned char keyboard()//键盘扫描
- {
- unsigned char keyboardj;
- keyboardj=0;
- if(KEY1==0)
- {
- delay(10);
- if(KEY1==0)
- {
- keyboardj=1;
- }
- }
-
- return keyboardj;
- }
- //************键盘控制子程序***************
- //
- //
- //******************************************
- void keykong()//主要功能是
- {
- unsigned char keyyy;
- keyyy=keyboard();
-
- if (keyyy!=oldkey)
- {
- if(keyyy==0)//
- {
- if(keyjixu>0)
- {
- if(keyjixu<80)
- {
- if(oldkey==1)
- {
- keyval=1;
- }
- }
- else
- {
- //keyval=11;
- keyjixu=0;
- }
- }
- else
- {
- keyval=0;
- keyjixu=0;
- }
- }
-
- }
- oldkey=keyyy;
- if(keyyy==1)//
- {
- keyjixu++;
- if(keyjixu==80)keyval=11;
- }
- //键盘处理完成。
- //以下为功能子程序
- if(keyval==1)
- {
- keyval=0;//这步必须的,清键值。
- keyjixu=0;//清计数值,这两步是必要的。
- //短按翻页
- if(disppagebit==1)
- {
- disppagebit=0;
- disp0(1);
- }
- else
- {
- disppagebit=1;
- disp1(1);
- }
-
-
- }
- if(keyval==11)
- {//
- keyval=0;//这步必须的,清键值。
- //keyjixu=0;//清计数值,这两步是必要的。
- //长按开关电源
- if(powonkong==0)
- {
- powonkong=1;//开总电源
- POWkong=0;//电源控制
- }
- else
- {
- powonkong=0;//开总电源
- POWkong=1;//电源控制
- }
- }
- }
- void Timer0Init(void) //2毫秒@22.1184MHz
- {
- AUXR |= 0x80; //定时器时钟1T模式
- TMOD &= 0xF0; //设置定时器模式
- TMOD |= 0x01; //设置定时器模式
- TL0 = 0x33; //设置定时初值
- TH0 = 0x53; //设置定时初值
- TF0 = 0; //清除TF0标志
- TR0 = 1; //定时器0开始计时
- ET0=1; //启动T定中断
-
- //IT1=1;//置中断1为脉冲低电平触发。
- //EX1=1;//开中断1
-
- EA=1; //启动总中断
- }
- /*void rs1_232tx(unsigned char txdata)
- {
- SBUF=txdata;//把数据传给串口寄存器SBUF。
- while(!TI);//检测是否发完。
- TI=0;//重置初值。
- }*/
- void UartInit(void) //19200bps@22.1184MHz
- {
- SCON = 0x50; //8位数据,可变波特率
- AUXR |= 0x01; //串口1选择定时器2为波特率发生器
- AUXR |= 0x04; //定时器2时钟为Fosc,即1T
- T2L = 0xE0; //设定定时初值
- T2H = 0xFE; //设定定时初值
- AUXR |= 0x10; //启动定时器2
-
- ES=1;//开中断
- }
- void UartInit1()//这个是变化的串口参数
- {
- ES=0;//关串口中断
- RETjisu=0;
- onjisu=0;
- rxdatvol=0;
- //OLED_ShowChar(0,0,RSjisu);
- //rs1_232tx(RSjisu);
- switch(RSjisu)
- {
- case 0:
- T2L = 0x00; //设定定时初值//1200bps@22.1184MHz
- T2H = 0xEE; //设定定时初值
- break;
- case 1:
- T2L = 0x00; //设定定时初值//2400bps@22.1184MHz
- T2H = 0xF7; //设定定时初值
- break;
- case 2:
- T2L = 0x80; //设定定时初值//4800bps@22.1184MHz
- T2H = 0xFB; //设定定时初值
- break;
- case 3:
- T2L = 0xC0; //设定定时初值//9600bps@22.1184MHz
- T2H = 0xFD; //设定定时初值
- break;
- case 4:
- T2L = 0x80; //设定定时初值//14400bps@22.1184MHz
- T2H = 0xFE; //设定定时初值
- break;
- case 5:
- T2L = 0xE0; //设定定时初值//19200bps@22.1184MHz
- T2H = 0xFE; //设定定时初值
- break;
- case 6:
- T2L = 0x40; //设定定时初值//28800bps@22.1184MHz
- T2H = 0xFF; //设定定时初值
- break;
- case 7:
- T2L = 0x70; //设定定时初值//38400bps@22.1184MHz
- T2H = 0xFF; //设定定时初值
- break;
- case 8:
- T2L = 0xA0; //设定定时初值//57600bps@22.1184MHz
- T2H = 0xFF; //设定定时初值
- break;
- case 9:
- T2L = 0xD0; //设定定时初值//115200bps@22.1184MHz
- T2H = 0xFF; //设定定时初值
- break;
- }
- RSjisu++;
- if(RSjisu>9)RSjisu=0;
- delay(20);
- ES=1;//开中断
- }
- void main()
- {
- P5M0=0x10;//P54推换
- Timer0Init();
- UartInit();
- OLED_Init();
- ADCINT();
- WDT_CONTR=0X3d;//开看门狗,由于是长时间工作,防止死机。2S内喂狗一次。
- AUXR1=0x40;//串口转P3637
- disp0(1);
- disppagebit=0;
- powonkong=1;//开总电源
- POWkong=0;//电源控制
- while(1)
- {
- WDT_CONTR=0X3d;//开看门狗,由于是长时间工作,防止死机。2S内喂狗一次。
- keykong();
- if(readtimekong==1)
- {
- nowtempAD();
- if(disppagebit==0)
- {
- disp0(0);//刷新
-
- }
- else
- {
- disp1(0);
- }
- //if(powonkong==1)
- //{//当总控为开,LED亮,如串口收到0x7f,就闪
- if(time02s==1&&rxdatvol==0x7f)//当收到7F时,表示下载,闪,
- {
- LEDout=0;
- }
- else
- {
- LEDout=1;
- }
- // }
- //else
- //{
- // LEDout=0;
- // }
-
- if(RSPOWonkong==1)
- {//当收到重启控制时,判断当前是不是处于总电源开,如是开就启动重启
- if(powonkong==1)
- {//整个过程大约需1.5s
- RETjisu++;
- if(RETjisu==2)POWkong=1;//关电源控制
- if(RETjisu==4)POWkong=0;//开电源控制
- if(RETjisu==8)
- {
- RSPOWonkong=0;//清控制值
- RETjisu=0;
- onjisu=0;
- }
- }
-
-
- }
-
-
- readtimekong=0;
- }
- if(time01kong==1)
- {
- if(kkkk==1)
- {
- kkkkjisu++;
- if(kkkkjisu>3)
- {
- kkkk=0;
- kkkkjisu=0;
- }
- }
- else
- {
- UartInit1();
- }
- time01kong=0;
- }
-
- }
- }
- void tt0(void) interrupt 1
- {//2毫秒@22.1184MHz
- //200MS数据,
-
- TL0 = 0x33; //设置定时初值
- TH0 = 0x53; //设置定时初值
- jisu++;
- if(jisu==50)time01kong=1;
- if(jisu>=100) //0.2S
- {
- jisu=0;
- readtimekong=1;
- time01kong=1;
- time02s=~time02s;
- }
- }
- void comm1(void) interrupt 4
- { //串口1中断 控接收协议:2B引导码FF FE,开关值及左右转值(加1为0x01,减10x02,短按0x04,长按0x08)。
- //注意清空RSzhuantai值,防止接收到非法数据不返回。
- if(RI)
- {
-
- RI=0; //rs1_232tx(SBUF);
- rxdatvol=SBUF;
- if(rxdatvol==0x7f)
- {
- kkkk=1;
- onjisu++;
- if(onjisu>20)
- {
- RSPOWonkong=1;//连接接收20次就重启
- ……………………
- …………限于本文篇幅 余下代码请从51黑下载附件…………
复制代码
所有资料51hei提供下载(原理图+pcb+源码):
DIY带电压电流表的多功能STC免冷启动自动下载器.zip
(593.47 KB, 下载次数: 306)
|