是本人初学51时制作的自动调压电路,设计上比较笨拙,仅供参考,参考莫笑!有单片机程序原理图!
制作出来的实物图如下:
实物图
电路原理图如下:
变压转换详表
220V变24V电压比:9.166
输入电压低于160VLED亮,控口P1.1
输入电压高于260VLED亮,无输出
单片机源程序如下:
- #include <stc12c2052ad.h>
- #include <intrins.h>
- #define uchar unsigned char
- #define uint unsigned int
- #define AD_SPEED 0x60 //0000,0000 1080个时钟周期转换一次,
- #define nop _nop_()
- //
- sbit v16=P1^1;
- sbit v17=P1^2 ;
- sbit v18=P1^3;
- sbit v19=P1^4 ;
- sbit v20=P1^5 ;
- sbit v21=P1^6 ;
- sbit v22=P1^7 ;
- sbit v23=P3^7 ;
- sbit v24=P3^5;
- sbit v25=P3^4;
- sbit led16=P3^3;
- sbit led25=P3^2;
- /****************************************************************/
- void delayms(uint);
- int ADC();
- void InitADC();
- float voltage=0.0;
- uint vac,V=0.0,V1=0.0,V2;
- float vdc=0.00 ;
- void kaig();
- /***8**************************************************************/
- void main()
- {
- InitADC();
- delayms(1500);
- while (1)
- {
- WDT_CONTR=0x34;
-
- delayms(100);
- V2=ADC();
- delayms(10);
- vdc= V2/256.00*5.00 ;//单片机最高是5伏模拟电压
- if ((vdc>3.78)||(vdc<1.85)) //acv=269.35 acv=131.8
- {
- P1=0XFF;
- P3=0XFF;
- led25=0;
- led16=0;
- break;
- }
- else
- {
- if (V2<107) //vdc=2.0865 acv=148.68
- led16=~led16;
- if (V2>187) //vdc=3.6465 acv=259.8
- led25=~led25;
- delayms(100);
- kaig();
- }
-
-
- }
- }
- /////////////////////////////
- void kaig()
- {
- if (vdc<=2.31)
-
- {
-
- vac=16;
- led16=0;
- }
-
- if (2.31<vdc&&vdc<=2.45)
-
- vac=17;
-
- if (2.45<vdc&&vdc<=2.59)
-
- vac=18;
- if (2.59<vdc&&vdc<=2.73)
-
- vac=19;
-
- if (2.73<vdc&&vdc<=2.87)
-
- vac=20;
-
- if (2.87<vdc&&vdc<=3.01)
-
- vac=21;
-
- if (3.01<vdc&&vdc<=3.15)
-
- vac=22;
- if (3.15<vdc&&vdc<=3.29)
-
- vac=23;
-
- if (3.29<vdc&&vdc<=3.43)
-
- vac=24;
-
- if (3.43<vdc&&vdc<=3.57)
- vac=25;
-
- if (vdc>3.57)
- {
- vac=25;
- led25=0;
- }
- switch(vac)
- {
-
- case 16:
- if (v16==0)
- break;
- else
- {
-
- P1=0XFF;
- P3=0XFF;
- v16=0;
- }
- break;
- case 17:
- if (v17==0)
- break;
- else
- {
- P1=0XFF;
- P3=0XFF;
- v17=0;
- }
- break;
- case 18:
- if(v18==0)
- break;
- else
- {
- P1=0XFF;
- P3=0XFF;
- v18=0;
- }
- break;
- case 19:
- if(v19==0)
- break;
- else
- {
- P1=0XFF;
- P3=0XFF;
- v19=0;
- }
- break;
- case 20:
- if(v20==0)
- break;
- else
- {
- P1=0XFF;
- P3=0XFF;
- v20=0;
- }
- break;
- case 21:
- if(v21==0)
- break ;
- else
- {P1=0XFF;
- P3=0XFF;
- v21=0;
-
- }
- break;
- case 22:
- if(v22==0)
- nop;
- else
- {
- P1=0XFF;
- P3=0XFF;
- v22=0;
- }
- break;
- case 23:
- if(v23==0)
- break;
- else
- {
- P1=0XFF;
- P3=0XFF;
- v23=0;
- }
- break;
- case 24:
- if(v24==0)
- break;
- else
- {
- P1=0XFF;
- P3=0XFF;
- v24=0;
- }
- break;
- case 25:
- if(v25==0)
- break;
- else
- {
- P1=0XFF;
- P3=0XFF;
- v25=0;
- }
- break;
-
- }
-
-
-
- }
- /*void UartInit() //9600bps@11.0592MHz
- {
- PCON &= 0x7f; //波特率不倍速
- SCON = 0x50; //8位数据,可变波特率
- AUXR |= 0x40; //定时器1时钟为Fosc,即1T
- AUXR &= 0xfe; //串口1选择定时器1为波特率发生器
- TMOD &= 0x0f; //清除定时器1模式位
- TMOD |= 0x20; //设定定时器1为8位自动重装方式
- TL1 = 0xDC; //设定定时初值
- TH1 = 0xDC; //设定定时器重装值
- ET1 = 0; //禁止定时器1中断
- TR1 = 1; //启动定时器1
- }
-
-
- //
- //
- */
- //AD转换初始化 ----打开ADC电源
- void InitADC()
- {
- P1=0xff;
- ADC_CONTR|=0x80;
- delayms(80);
- //这两个寄存器用来设置 P1口四种状态,每一位对应一个P1引脚 ,按状态组合操作
- /*****************
- P1M0 和P1M1 寄存器位 7 6 5 4 3 2 1 0
- P1.7 P1.6 P1.5 P1.4 P1.3 P1.2 P1.1 P1.0
- 同理P3M0 P3M0 也是。因为STC12C2052AD只有两个P口,所以只有这俩组 STC12C5410AD还多P2M0 P1M0 有三组
- P1M0 P1M1 高
- 0 0 普通I0口 (准双向) P1寄存器位 7 6 5 4 3 2 1 0
- 0 1 强推挽输出 (20MA电流 )尽量少用 P1.7 P1.6 P1.5 P1.4 P1.3 P1.2 P1.1 P1.0
- 1 0 仅做输入 A/D转换时可用此模式
- 1 1 开漏 ,A/D转换时可用此模式
-
- 例如:
- 要设置P1.1为 AD 输入口
- 则 P1M0=0X02 ;
- P1M1=0X02; 开漏即可
- 当不用AD时,最好 关闭ADC电源 ,恢复为IO口状态
- ********************************/
- P1M0=0x01;//这两个寄存器用来设置 P1口四种状态,每一位对应一个P1引脚 ,按状态组合操作
- P1M1=0x01;//设置P1.0为开漏状态
- }
-
- // AD转换程序
- /******************************************************
- 注意:这个函数里注释的命令是通用命令,可以针对所有AD通道使用,我这就认准了P1.1一个通道,所以直接
- //赋值,省点"流量"!折磨我的问题就出在这个函数里的while等待语句
- while (1) //等待A/D转换结束
- {
- if (ADC_CONTR & 0x10) //0001,0000 测试A/D转换结束否
- { break; }
- }
- 这是能用的,我原来写的是:
- while (ADC_CONTR & 0x10==0);
- 这样写不能用,再说一遍:这样就不能用了!!
- 至于为嘛,因为 优先级,“==”比&优先级高,
- 所以加个括号就可以了
- while ( (ADC_CONTR & 0x10) == 0 );
- 不经常用C语言,就会记不住啦!!!
- 由此得到一个教训;小问题影响效率
- 经验:经常加一加括号会死啊,似乎也不耗“流量”吧!!
- *********************************************/
- int ADC()
- {
- ADC_DATA = 0; //清除结果
- ADC_CONTR = 0x60; //转换速度设置 0x60 最快速度
- ADC_CONTR = 0xE0; //1110,0000 清 ADC_FLAG, ADC_START 位和低 3 位 开启AD电源保持速度设置
- // ADC_CONTR =0xe1; // 选择 A/D 当前通道 P1.1 保持上句设置
- // ADC_CONTR |= 0x01; //选择 A/D 当前通道 P1.1
- delayms(2); //使输入电压达到稳定
- ADC_CONTR = 0xE8; //开启转换 1110 1001 保持上句设置
- // ADC_CONTR |= 0x08; //0000,1000 令 ADCS = 1, 启动A/D转换,
- while (1) //等待A/D转换结束
- {
- if (ADC_CONTR & 0x10) //0001,0000 测试A/D转换结束否
- { break; }
- }
- ADC_CONTR =0xE0;
- //ADC_CONTR &= 0xE7; //1111,0111 清 ADC_FLAG 位, 关闭A/D转换,
- return ADC_DATA; //返回 A/D 10 位转换结果
-
- ……………………
- …………限于本文篇幅 余下代码请从51黑下载附件…………
复制代码
所有资料51hei提供下载:
调压.rar
(162.1 KB, 下载次数: 22)
|