📄 dcdc.c
字号:
#include <absacc.h>
#include <reg51.h>
/*////////////////////////////*/
/*/// 常量定义 //*/
/*////////////////////////////*/
/* 定时器初值 */
#define V_T1 0xfd /*SCOM 9600 baud, ! notice: crystal 11.0592MHz */
#define V_TH0 0xee /* ~ 5ms , ! notice: crystal 11.0592MHz */
#define V_TL0 0x00
/* 数码管段驱动寄存器地址 */
#define ADDR_8SEG XBYTE[0x2000]
/* 数码管位驱动和指示灯驱动寄存器地址 */
#define ADDR_SEL XBYTE[0x4000]
///ADC0804驱动寄存器地址
#define ADDR_0804 XBYTE[0x6000]
/* 按键 */
sbit KEY1=P1^0;
sbit KEY2=P1^1;
sbit KEY3=P1^2;
sbit KEY4=P1^3;
/*输出端口*/
sbit PWM_Level=P3^5;
/*////////////////////////////*/
/*/// 变量定义 ///*/
/*////////////////////////////*/
/////定义占空比,数值放大了100倍
unsigned int data q;
unsigned int data highlevel;
/////定义电压值,数值放大了10倍
unsigned char data u;
/////定义PWM波一个周期内高电平的时间数值及定时器1中TH1和TL1的值
unsigned int data PWM_High;
unsigned char data PWM_High_TH;
unsigned char data PWM_High_TL;
/////定义PWM波一个周期内低电平的时间数值及定时器1中TH1和TL1的值
unsigned int data PWM_Low;
unsigned char data PWM_Low_TH;
unsigned char data PWM_Low_TL;
unsigned char flag;
bit sign;
bit calculate_q;
unsigned int data_0804;
/////表征键盘状态,值1表示按键都已松开,值0表示有键被按下
bit single_key;
/////对应四个按键,用来记录延时
unsigned char delay[4];
/* 数码管位驱动和指示灯驱动信号输出缓存,定义了一个可位寻址的变量 */
unsigned char bdata output_sel;
sbit led_1 = output_sel^5;
sbit led_2 = output_sel^6;
sbit led_3 = output_sel^7;
sbit led_4 = output_sel^4;
/* 数码管扫描驱动指针,为测试外部存储器(U3 6264),特使用xdata类型 */
unsigned char xdata digi_scaner;
unsigned char xdata Hex_8SEG[4];
/* 测试用计数值十进制表示,为测试外部存储器(U3 6264),特使用xdata类型 */
unsigned char xdata digi[4];
bit Kst1,Kst2,Kst3,Kst4;
bit states;
unsigned char workmod;
bit shinetwo;
unsigned char shinefour;
unsigned int idata aad[10]={0,0,0,0,0,0,0,0,0,0};
unsigned int idata sum;
unsigned char data temp;
unsigned char index;
float idata a1,b1,c1,a2,b2,c2; //对应10.0-8.7,8.7-5.0
float idata qf[5];
unsigned char dotnum;
unsigned int idata vf[5]={99,94,87,71,55};
unsigned int times;
bit autosign;
unsigned char Vo[]={238,234,229,225,220,216,211,206,201,197,192,187,182,178,173,168,163,158,153,148,143,138,133,128,123,118,113,108,103,97,92,88,83,78,73,68,63,58,53,48,43,39,35,30,26,23,20,18,15,13,11}; //5.0-10.0//
//5.0,5.1,5.2,5.3,5.4,5.5,5.6,5.7,5.8,5.9,6.0,6.1,6.2,6.3,6.4,6.5,6.6,6.7,6.8,6.9,7.0,7.1,7.2,7.3,7.4,7.5,7.6,7.7,7.8,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100
/*////////////////////////////*/
/*/// 函数定义 /*/
/*////////////////////////////*/
/**** 7段数码显示译码
参数:DATA: 需要显示的数字或符号;
返回值: 7段译码结果 ( D7~0 = PGFEDCBA )
*****/
unsigned char NUMTOSEG7(unsigned char DATA)
{
unsigned char AA;
switch (DATA){
case 0: AA=0xc0;break; /* ‘0’*/
case 1: AA=0xf9;break; /* ‘1’*/
case 2: AA=0xa4;break; /* ‘2’*/
case 3: AA=0xb0;break; /* ‘3’*/
case 4: AA=0x99;break; /* ‘4’*/
case 5: AA=0x92;break; /* ‘5’*/
case 6: AA=0x82;break; /* ‘6’*/
case 7: AA=0xf8;break; /* ‘7’*/
case 8: AA=0x80;break; /* ‘8’*/
case 9: AA=0x90;break; /* ‘9’*/
case 10: AA=0x88;break; /* ‘A’*/
case 20: AA=0x83;break; /* ‘b’*/
case 21: AA=0x8f;break; /* ‘k’*/
case 22: AA=0xf1;break; /* ‘j’*/
case 23: AA=0xc1;break; /* ‘u’*/
case 24: AA=0xff;break; /* 消隐 */
default: AA=0xff;
}
return(AA);
}
//======== 计算PWM波的高低电平持续时间数值 ========
void Caculate_PWM()
{
PWM_High=65535-highlevel;
PWM_Low=65535-(3000-highlevel);
EA=0;
PWM_High_TH=PWM_High/256;
PWM_High_TL=PWM_High%256;
PWM_Low_TH=PWM_Low/256;
PWM_Low_TL=PWM_Low%256;
EA=1;
}
//======== 粗略计算对应于期望电压的占空比 ========
void Cacult_Q()
{ float temp_U;
float temp_Q;
temp_U=u;
temp_U=temp_U/10;
if(u>=87) temp_Q=c1+b1*temp_U+a1*temp_U*temp_U;
else temp_Q=c2+b2*temp_U+a2*temp_U*temp_U;
q=temp_Q*100;
}
//======= 闭环自动调节电压 =======
void FeedBackControl()
{
if(data_0804<Vo[u-50]){
if(q<9990) q+=1;
}
else if(data_0804>Vo[u-50]){
if(q>10) q-=1;
}
}
//======= 开环自动拟合 =======
void AutoFitting()
{
a1=(0.7*qf[0]-1.2*qf[1]+0.5*qf[2])/0.42;
b1=-(12.67*qf[0]-22.32*qf[1]+9.65*qf[2])/0.42;
c1=(57.246*qf[0]-103.356*qf[1]+46.53*qf[2])/0.42;
a2=(1.6*qf[2]-3.2*qf[3]+1.6*qf[4])/8.192;
b2=-(20.16*qf[2]-45.44*qf[3]+25.28*qf[4])/8.192;
c2=(62.48*qf[2]-153.12*qf[3]+98.832*qf[4])/8.192;
}
//======= 闭环自动检测基准点 =======
void AutoAdjusting()
{
u=vf[dotnum];
if(times>=3000){
if(dotnum<5){
qf[dotnum]=q;
qf[dotnum]/=100;
}
dotnum++;
if(dotnum>=5){
AutoFitting();
dotnum=0;
autosign=0;
workmod=1;
u=50;
}
times=0;
}
}
//======= 按键事件响应管理 =======
void KeyBoard_Admin()
{
if(Kst1){
if(++workmod>2) workmod=0;
}
if(workmod==2){
if(Kst2){
if(++shinefour>4) shinefour=0;
}
if(shinefour==0){
if(Kst3&&q<9000) q+=1000;
if(Kst4&&q>1000) q-=1000;
}else if(shinefour==1){
if(Kst3&&q<9900) q+=100;
if(Kst4&&q>100) q-=100;
}else if(shinefour==2){
if(Kst3&&q<9990) q+=10;
if(Kst4&&q>10) q-=10;
}else if(shinefour==3){
if(Kst3&&q<9999) q+=1;
if(Kst4&&q>1) q-=1;
}else{
if(Kst3){
if(dotnum<5){
qf[dotnum]=q;
qf[dotnum]/=100;
}
dotnum++;
}
if(Kst4){
autosign=1;
times=0;
dotnum=0;
workmod=0;
}
}
}else{
if(Kst2) shinetwo=!shinetwo;
if(shinetwo){
if(Kst3&&u<=90) u+=10;
if(Kst4&&u>=60) u-=10;
}else{
if(Kst3&&u<=99) u+=1;
if(Kst4&&u>=51) u-=1;
}
calculate_q=1;
}
Kst1=Kst2=Kst3=Kst4=0;
}
//======= 指示灯管理 =======
void LedPrint()
{
if(workmod==2){
if(shinefour==4){
digi[0]=24;
digi[1]=24;
digi[2]=24;
digi[3]=dotnum+1;
}else{
digi[0]=q/1000;
digi[1]=(q-1000*digi[0])/100;
digi[2]=(q-1000*digi[0]-100*digi[1])/10;
digi[3]=q-1000*digi[0]-100*digi[1]-10*digi[2];
}
}else{
if(autosign) digi[0]=10;
else digi[0]=20+workmod;
digi[1]=u/100;
digi[2]=(u-100*digi[1])/10;
digi[3]=u-100*digi[1]-10*digi[2];
if(digi[1]==0) digi[1]=24;
}
}
//======== T0时钟中断服务程序,每5ms被执行一次 ========
timer0() interrupt 1 using 0
{
EA=0; /*关中断*/
/* 重新对计数器赋初值,并启动定时计数 */
TR0=0;
TH0=V_TH0;
TL0=V_TL0;
TR0=1;
EA=1;
output_sel = 0xf0; /*初值,令数码管驱动位无效,指示灯全灭*/
//键盘扫描
if(single_key){
if(KEY1==0) delay[0]++;
if(delay[0]>=10){
delay[0]=single_key=0;
Kst1=1;
}
if(KEY2==0) delay[1]++;
if(delay[1]>=10){
delay[1]=single_key=0;
Kst2=1;
}
if(KEY3==0) delay[2]++;
if(delay[2]>=10){
delay[2]=single_key=0;
Kst3=1;
}
if(KEY4==0) delay[3]++;
if(delay[3]>=10){
delay[3]=single_key=0;
Kst4=1;
}
}
if(KEY1&&KEY2&&KEY3&&KEY4) single_key=1;
if(++flag>=100) sign=1;
if(autosign) times++;
if(states) ADDR_0804=0;
else temp=ADDR_0804;
states=!states;
/* 检测到按键被按下(0)时,相应的指示灯电亮(0)*/
if(workmod==2){
if(shinefour==0) led_1=0;
else if(shinefour==1) led_2=0;
else if(shinefour==2) led_3=0;
else if(shinefour==3) led_4=0;
else led_2=led_4=0;
}else{
if(shinetwo) led_3=0;
else led_4=0;
}
if(!single_key) led_1=led_2=led_3=led_4=0;
/* 数码管扫描驱动指针值从1到4重复变换,每5ms间隔对一个数码管进行驱动,20ms一个轮回 */
if (++digi_scaner>=5) digi_scaner = 1;
switch (digi_scaner){
case 1: //驱动第一个数码管
output_sel |= 0x01;
ADDR_8SEG = Hex_8SEG[0];//输出到锁存器U5(在电路图中找)
break;
case 2: // 驱动第二个数码管
output_sel |= 0x02;
ADDR_8SEG = Hex_8SEG[1];//输出到锁存器U5
break;
case 3: // 驱动第三个数码管
output_sel |= 0x04;
ADDR_8SEG = Hex_8SEG[2];//输出到锁存器U5
break;
case 4: // 驱动第四个数码管
output_sel |= 0x08;
ADDR_8SEG = Hex_8SEG[3];//输出到锁存器U5
break;
}
ADDR_SEL = output_sel; /*输出到锁存器U6(在电路图中找)*/
}
//======== T1时钟中断服务程序,用于产生PWM波 ========
PWM_Wave() interrupt 3 using 1
{
EA=0; ////关中断
TR1=0;
if(PWM_Level){
PWM_Level=0;
TH1=PWM_Low_TH;
TL1=PWM_Low_TL;
}else{
PWM_Level=1;
TH1=PWM_High_TH;
TL1=PWM_High_TL;
}
TR1=1;
EA=1; ////开中断
}
//======== 主程序 ========
main()
{
/* 单片机系统初始化 */
P1=0XFF;
P3=0XFF;
/** 中断工作寄存器初始化 **/
IE=0X80;
IP=0X08;
IT0=0;
IT1=0;
/** 定时器工作寄存器初始化 **/
TMOD=0X11;
TH1=V_T1;
TL1=V_T1;
TH0=V_TH0;
TL0=V_TL0;
/** 串行通信口工作初始化 ,注:本例中虽未使用到串行通信口,但本段程序无妨保留**/
SM0=0; /*SCOM MODE 1 (8BIT UART VARBR)*/
SM1=1;
SM2=0;
REN=1;
TI=1;
/** 全局变量赋初值 **/
q=2000;
u=50;
sum=0;
autosign=0;
dotnum=0;
sign=1;
calculate_q=1;
PWM_Level=0;
a1=-4.323;b1=64.192;c1=-172.073;
a2=-0.470;b2=-2.844;c2=118.028;
single_key=0;
shinefour=0;
delay[0]=0;
delay[1]=0;
delay[2]=0;
delay[3]=0;
/** 开定时器,定时器0中断允许 **/
TR0=1;
TR1=1;
ET0=1;
ET1=1;
/* 主循环,本例中,在T0中断服务程序未被执行的空余时间里,处理机在以下程序中不断循环 */
while(1)
{
if(sign){
flag=0;
KeyBoard_Admin();
if(workmod==0){
if (++index>=10) index=0;
sum-=aad[index];
aad[index]=temp;
sum+=aad[index];
data_0804=sum/10;
FeedBackControl();
}else if(workmod==1){
if(calculate_q){
calculate_q=0;
Cacult_Q();
}
}else if(dotnum>=5){
AutoFitting();
dotnum=0;
}
if(autosign) AutoAdjusting();
highlevel=q*3/10;
Caculate_PWM();
}
LedPrint();
Hex_8SEG[0] = NUMTOSEG7(digi[0]);
Hex_8SEG[1] = NUMTOSEG7(digi[1]);
Hex_8SEG[2] = NUMTOSEG7(digi[2]);
if(workmod!=2) Hex_8SEG[2] -= 0x80;
Hex_8SEG[3] = NUMTOSEG7(digi[3]);
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -