单片机主程序.docx
- 文档编号:26031776
- 上传时间:2023-06-17
- 格式:DOCX
- 页数:20
- 大小:20.19KB
单片机主程序.docx
《单片机主程序.docx》由会员分享,可在线阅读,更多相关《单片机主程序.docx(20页珍藏版)》请在冰豆网上搜索。
单片机主程序
一、程序的预处理和外部变量、函数定义
#include“at89x52.h”
#include
#include
#include
#defineucharunsignedchar
#defineuintunsignedint
#definenop_nop_()/*定义空操作指令*/
#definemaxvolt300
#defineminvolt5
#defineminfre0
#definemaxfre4000
#defineUM300
#defineIM2
#definefc12000
#defineKP0.2
#defineKI25
#defineKD0
#defineCOM8155XBYTE[0x7FF8]
#definePAXBYTE[0x7FF9]
#definePBXBYTE[0x7FFA]
#defineR0XBYTE[0Xdf00]
#defineR1XBYTE[0Xdf01]
#defineR2XBYTE[0Xdf02]
#defineR3XBYTE[0Xdf03]
#defineR4XBYTE[0Xdf04]
#defineR5XBYTE[0Xdf05]
#defineR14XBYTE[0Xdf0E]
#defineR15XBYTE[0Xdf0F]
sbitSCL=P3^4;/*24C01SCL接脚=89C52T0P3.4*/
sbitSDA=P3^5;/*24C01SDA接脚=89C52T1P3.5*/
sbitRST=P1^0;
bitFLAG0=0,wuxiao=0,CHF=0,CHA=0,exit;
/*设定位标号FLAG0=1键盘扫描回应*/
Charptr=0,ptr1=0;/*PTR键盘扫描指标,ptr1显示器扫描指标*/
Chara1=0,b1=100;/*宣告变数a1为TIMER0的中断次数,ptr为TIMER1扫描数码管指标*/
charini[6]={0x40,0x5A,0x2c,0x02,0x00,0x00};//放置初始化数据
charcon[6]={0xcd,0xcc,0x06,0x80,0x80,0x80};//放置控制数据
staticconstchartab[16]={0x01,0x02,0x03,0x0c,/*键盘码00,01,02,03,*/
0x04,0x05,0x06,0x0d,/*键盘码04,05,06,07,*/
0x07,0x08,0x09,0x0e,/*键盘码08,09,0a,0b,*/
0x0a,0x00,0x0b,0x0f};/*键盘码0c,0d,0e,0f*/
staticconstcharduanxuan[17]={0x3F,0x06,0x5b,0x4F,
0x66,0x6D,0x7D,0x07,
0x7F,0x6F,0x77,0x7C,
0x39,0x5E,0x79,0x71,0x00};
charlia=0,lu=0,dot,weishu=0;
chardispel[8];//显示值存放阵列
charbufdata[9];
charbufuart[6];//串口接收值存放列阵
floatvdataset=220;
floatvdata[3]={220,220,220};
voiddelay(uintvalue)//延时子程序
{
while(value!
=0)value--;//10US延时
}
voidtserial(void);//串口serial发送子程序
voidrserial(void);//串口serial接收子程序
voidchvolt(void);//改变输出电压幅值子程序
voidchfre(void);//改变输出电压频率子程序
voidxch(void);//宣告按键存放/显示器阵列disple[]右键滚入子程序
二、主程序清单
main()/*主程序*/
{charI;
TMOD=0X21;/*TIMER0工作在方式MODE1,16位定时器*/
/*TIMER1工作在MODE2,自动重新装载模式*/
/*方式寄存器TMOD*/
/*|定时器1|定时器1|*/
/*|GATE|C/T|M1|M0|GATE|C/T|M1|M0|*/
/*|||*/
TH0=(65536-3000)/256;/*设定每隔3000us中断扫描一次数码管*/
TL0=(65536-3000)%256;
TR0=1;/*启动TEMER0*/
TH1=(65536-9200)/256;/*设TIMER1计数值*/
TL1=(65536-9200)%256;
TR1=1;//启动TEMER1
//显示初始化
disple[7]=0x73;//最左的显示器显示P,表示处于停止态
for(i=2;i<=6;i++)disple[i]=0x00;//第3-7位显示器灭
disple[1]=0x3e;//初态第二位显示器显示U,表示电压
disple[0]=0x06;//初态第一位显示器显示1,表示第一相
P2_0=1;
P1=0XF0;//P1低4位为全0,高4位写入1
COM8155=3;/*8155初始化,设定PA、PB工作在基本输出方式*/
RST=0;
//进行4828初始化;
R0=imi[0];
R1=imi[1];
R2=imi[2];
R3=imi[3];
R4=imi[4];
R5=imi[5];
R14=0;//R0-R5装入初始化寄存器
//向8248写控制数据
R0=con[0];
R1=con[1];
R2=con[2];
R3=con[3];
R4=con[4];
R5=con[5];
R15=0;//RO-R5装入控制寄存器
IP=0x0b;/*中断优先级寄存器IP*/
/*|︱|PT2|PS|PT1|PX1|PT0|PX0|*/
IE=0X9f;/*︱7654︱3210︱*/
/*|EA||ET2|ES|ET1|EX1|ET0|EX0|*/
While
(1);//等中断
}
三、故障中断处理程序
Voidservice_int0()interrupt0using0/*外部中断0,为故障中断*/
{inti;
RST=0;
for(i=0;i<=7;i++)disple[i]=0x31;//显示故障信息
}
四、键盘中断处理程序
Voidexternal_int1()interrupt2using2
//键盘中断,进行按键命令处理
{
chara1=0xf7,i,m,xiantai;/*a1=0XF7行扫描初值,I行*/
bitflag1=0;
IE&=OXFB;
Delay(1000);//延时10ms
FLAG0=0;/*设按键回应旗号为0,键盘扫描计数指标为0*/
ptr=0;
if(P3_2==0)/*按键仍闭合则进行键处理*/
{
For(i=0;i<4;i++)/*键盘4个扫描列*/
{
P1=a1;/*行扫描输出,读入P1存入M,以便侦测列与侦测按键是否按下*/
m=P1;
switch(m&0xf0)/*取P1的高4位元。
侦测那一列被按*/
{
case0x70:
ptr=i*4;/*第一列被按否?
是则扫描指标=列X4*/
FLAG0=1;/*是则设FLAG0=1表有按键输入*/
break;/*跳出此循环*/
case0xb0:
ptr=i*4+1;/*第二列被按否?
是则扫描指标=列X4+1*/
FLAG0=1;/*是则设FLAG0=1表有按键输入*/
break;/*跳出此循环*/
case0xd0:
ptr=i*4+2;/*第三列被按否?
是则扫描指标=列X4+2*/
FLAG0=1;/*是则设FLAG0=1表有按键输入*/
break;/*跳出此循环*/
case0xe0:
ptr=i*4+3;/*第四列被按否?
是则扫描指标=列X4+3*/
FLAG0=1;/*是则设FLAG0=1表有按键输入*/
Default:
break;/*跳出此循环*/
}
if(FLAG0==1)break;/*不为1,则扫描行右移,扫描下一行*/
a1=a1>>1|0x80;/*高位补1*/
}
if(FLAG0==0)return;
switch(tab[ptr])/*是键盘扫描计数器指标至TAB[]取到的键盘码*/
{
case0x0a:
/*是否是第一次按“START”,是则启动SA4828的SPWM输出,最左的显示器显示D,表示SA4828在运行*/
if(flag1==0){RST=1;flag1=1;dispel[7]=duanxuan[0x0D];}break;/*跳出此循环*/
case0x0b:
/*是否按“STOP”是则停止SA4828的SPWM输出*/
RST=0;
flag1=0;
dispel[7]=0x73;//最左的显示器显示P,表示处于停止态
break;/*跳出此循环*/
case0x0e:
/*是否按“调压”,是则进行相应处理*/
if(CHF==0)/*调压与调频互锁,当调频时,按调压键无效*/
{
If(CHA==0)
{CHA=1;
for(i=2;i<=6;i++)dispel[i]=0x00;
/*进入调压状态2位-6位显示器起初为全灭*/
xiantai=disple[7];
disple[1]=0x3e;
dispel[0]=0x00;
}
else
{if(weishu!
=0)chvolt();//进行改变电压控制数据的处理;
If(wuxiao==1)
{for(i=2;i<=6;i++)dispel[i]=0;//调用显示“00000”
for(i=0;i<10;i++)delay(10000);/*延时1秒*/
while(m==p1);delay(1000);
}
weishu=0;dot=0;
disple[7]=xiantai;
if(lia==0)disple[1]=0x3e;
elsedisple[1]=duanxuan[0x0A];
disple[0]=duanxuan[lu+1];
CHA=0;
If(wuxiao==1){wuxiao=0;return;}
}
}
Break;/*跳出此循环*/
case0x0f:
/*是否按“调频”,是则进行相应处理*/
if(CHA==0)/*调压与调频互锁,当调压时,按调频键无效*/
{if(CHF==0)
{CHF=1;
for(i=2;i<=6;i++)disple[i]=0x00;
/*进入调频状态2位-6位显示器起初为全灭*/
xiantai=disple[7];
disple[7]=duanxuan[0x0A];
disple[1]=duanxuan[0x0F];
disple[0]=0x00;
}
else
{
if(weishu!
=0)chfre();//进行改变频率控制数据的处理;
if(wuxiao==1)
{
for(i=2;i<=6;i++)disple[i]=0;//调用显示“00000”;
for(i=0;i<10;i++)delay(10000);/*延时1秒*/
while(m==P1);delay(1000);
}
weishu=0;dot=0;
disple[7]=xiantai;
if(lia==0)disple[1]=0x3e;
elsedisple[1]=duanxuan[0x0A];
disple[0]=duanxuan[lu+1];
CHF=0;
If(wuxiao==1){wuxiao=0;return;}
}
}
break;/*跳出此循环*/
case0x0c:
/*是否按“显示切换及·键”,是则进行相应处理*/
if(CHA==1||CHF==1)
/*当进入数字输入处理时,该键为·键,进行处理*/
{if(dot==0)dot=1;}
else//为显示切换键
{
lia++;
if(lia>1)lia=0;
if(lia==0)disple[1]=0x3e;
elsedisple[1]=duanxuan[0x0A];
}
break;/*跳出此循环*/
case0x0d:
/*是否按“三相切换及退出键”,是则进行相应处理*/
if(CHA==1‖CHF==1)//当进入数字输入处理时,该键为退出键
{
exit=1;
for(i=2;i<=6;i++)disple[i]=0;
disple[7]=xiantai;
if(lia==0)disple[1]=0x3e;
elsedisple[1]=duanxuan[0x0A];
disple[0]=duanxuan[lu+1];
while(m==P1);
delay(1000);//按钮抗机械反弹跳
delay(10000);//延时100ms显示
if(CHA==1){CHA=0;}
if(CHF==1){CHF=0;}
exit=0;
return;
}
else//为三相切换键
{
lu++;
if(lu>3)lu=0;
disple[0]=duanxuan[lu+1];
}
break;//跳出此循环
default:
//以上均不是则为数字键,当进入调压、调频/调速状态才有效
if(CHA==1‖CHF==1)xch();//数字键输入处理
break;//跳出此循环
}
while(m==P1);//等键释放
delay(1000);//按钮抗机械反弹跳
P1=0Xf0;//回复P1低4位为全0,高4位写入1
}
}
五、数字显示向左移动子程序
Voidxch(void)/*数字显示向左移动子程序*/
{charc;
if(dot!
=2)
if(weishu<5)
{weishu++;
for(c=6;c>3;c--)
disple[c]=disple[c-1];/*将显示器disple[]移位交换,disple[3]->disple[4]->disple[5]…*/
}
disple[2]=duanxuan[tab[ptr]];/*新的按键值存入disple[2]*/
if(dot==1)dot=2;
}/*返回主程序*/
六、改变输出电压幅值子程序
Voidchvolt(void)
{charI,j,VA,APE;
intk;
vdataset=0;
for(i=0;i {k=1; for(j=1;j<=I;j++) k*=10; vdataset+=disple[i+2]*k; } if(dot==2)vdataset+=disple[2]/10;/*当有输入小数点且小数点后有输入数字,则加上只有一位的小数部分*/ if(vdataset<=maxvolt&&vdataset>minvolt)//进行输入电压数据是否有效判别 { for(i=0;i<=2;i++)vdata[i]=vdataset; APE=vdataset/maxvolt; VA=APE*255+0.5;//进行向SA4828写调压数据; con[3]=VA; R3=con[3];//只改变输出电压幅值,其他寄存器不用变; R4=con[3]; R5=con[3]; R15=0; } elsewuxiao=1; } 七、改变输出电压频率子程序 Voidchfre(void) {chari,j,fdatain=0,m,k; Uintnpfs; floatfdata=0,fr; for(i=0;i {k=1; for(j=1;j<=i;j++) k*=10; fdatain+=disple[i+2]*k; } if(dot==2)fdata=fdatain+disple[2]/10; /*当有输入小数点且小数点后有输入数字,则加上只有一位的小数部分*/ if(fdata<=maxfre&&fdata>=minfre)//进行输入频率数据是否有效判别 { if(fdata<=50)fr=62.5; if(fdata<=100)fr=125; elseif(fdata<=1000)fr=1000; elseif(fdata<=4000)fr=4000; i=fr*384/fc; j=0;k=1; for(m=0;m<=6;m++) {if(i==k)j=1; if(j==1)break; k=k<<1; } if(j==0){wuxiao=1;return;} //重写初始化数据 for(j=1;j<=5;j++)m=m<<1; ini[0]&=0x0f; ini[0]︱=m; RST=0; R0=ini[0]; R1=ini[1]; R2=ini[2]; R3=ini[3]; R4=ini[4]; R5=ini[5]; R14=0; //重写控制数据 npfs=fdata*65536/fr; con[0]=npfs%256; con[1]=npfs/256; R0=con[0]; R1=con[1]; R2=con[2]; R3=con[3]; R4=con[4]; R5=con[5]; R15=0; RST=1; } elsewuxiao=1; } 八、数码管扫描定时中断程序 Voidservice_timer0()interrupt1using1 {staticcharch=0X01; TH0=(65536-3000)/256;/*每隔3000US扫描一次*/ TL0=(65536-3000)%256; //写8155PA、PB口 PA=ch; PB=disple[ptrl]; if(CHA==1‖CHF==1) { if(wuxiao==0&&exit==0) {if(dot==1){if(ptr1==2)PB︱=0x01;} elseif(dot==2){if(ptr1==3)PB︱=0x01;} } } else { if(lia==0){if(ptr1==3)PB︱=0x01;}//显示电压数据的小数点 elseif(ptr1==4)PB︱=0x01;//显示电流数据的小数点 } ch=ch<<1; if(ch==0)ch=1; ptr1++; if(ptr1>7)ptr1=0; } 九、定时采集、计算、控制中断程序清单 #defineaddress0Xbff8 Charb2=5; Floatvcdata[3][3],verror[3][3],vadjust[3]; Voidservice_timer1()interrupt3using3 /*TIMER1中断程序-50ms计时器,进行定时数据采集、计算、控制及显示*/ { intdispdataint; chari,j,k,n,t,wei=0; floatAPE,dispdata,xiaodata; charVA; TH1=(65536-9200)/256;/*重设TIMER1计数值*/ TL1=(65536-9200)%256; b2--;/*中断次数减1*/ if(b2==0)/*中断次数完成否,是则表50ms到了*/ { b2=5;/*重设中断次数*/ for(i=0,k=0;i<=1;i++)//i=0,测量电压;i=1,测量电流 for(j=0;j<=2;j++)//j表示测量那一路,是0路、1路还是2路 { vcdata[i][j]=0; for(n=1;n<=3;n++)//对一个量进行连续三次采样,取平均值,起滤波作用 { XBYTE[address+k]=k; delay(10); while(P3_4==0); vcdata[i][j]+=XBYTE[0Xbfff]; k++; } if(i==0)vcdata[i][j]=vcdata[i][j]*UM/(255*3); elsevcdata[i][j]=vcdata[i][j]*IM/(255*3); if(i==0)//电压须计算偏移量、调整量,然后向SA4828写控制数据 { verror[j][0]=verror[j][1]; verror[j][1]=verror[j][2]; verror[j][2]=vcdata[i][j]-vdataset; vadjust[j]=KP*(verror[j][2]-verror[j][1]+KI*0.05*verror[j][2]/KP+KD*(verror[j][2]-2*verror[j][1]+verror[j][0])/(KP*0.05)); vdata[j]=vdata[j]+vadjust[j]; //进行向SA4828写调压数据 APE=vdata[j]/maxvolt; if(APE>1)APE=1; VA=APE*255+0.5; if(j==0)R3=VA;//只改变输出电压幅值,其它寄存器不用变; elseif(j==1)R4=VA; elseR5=VA; R15=0; } } /*当满足条件时,将要显示的电量写入显示缓冲区*/ dispdata=vcdata[lia][lu]; dispdataint=(int)dispdata; if(CHA==0&&CHF==0) { if(lia==0)/*为显示电压数据*/ { j=dispdataint/1000; if(j! =0){disple[6]=duanxuan[j];wei=4;} elsedisple[6]=0; dispdataint=dispdatint-j*1000; } K=dispdataint/100; if(wei==0) { if(k! =0){disple[5+lia]=duanxuan[k];wei=3;} elsedisple[5+lia]=0; } Elsedisple[5+lia]=duanxuan[k]; dispdataint=dispdat
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 单片机 主程序
![提示](https://static.bdocx.com/images/bang_tan.gif)