单片机主程序.docx

上传人:b****7 文档编号:26031776 上传时间:2023-06-17 格式:DOCX 页数:20 大小:20.19KB
下载 相关 举报
单片机主程序.docx_第1页
第1页 / 共20页
单片机主程序.docx_第2页
第2页 / 共20页
单片机主程序.docx_第3页
第3页 / 共20页
单片机主程序.docx_第4页
第4页 / 共20页
单片机主程序.docx_第5页
第5页 / 共20页
点击查看更多>>
下载资源
资源描述

单片机主程序.docx

《单片机主程序.docx》由会员分享,可在线阅读,更多相关《单片机主程序.docx(20页珍藏版)》请在冰豆网上搜索。

单片机主程序.docx

单片机主程序

一、程序的预处理和外部变量、函数定义

#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

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 高等教育 > 文学

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1