基于单片机的数控恒流源设计软件设计.docx
《基于单片机的数控恒流源设计软件设计.docx》由会员分享,可在线阅读,更多相关《基于单片机的数控恒流源设计软件设计.docx(27页珍藏版)》请在冰豆网上搜索。
![基于单片机的数控恒流源设计软件设计.docx](https://file1.bdocx.com/fileroot1/2023-1/29/55a9760a-eba3-418c-8d8a-7ec6c3fcb163/55a9760a-eba3-418c-8d8a-7ec6c3fcb1631.gif)
基于单片机的数控恒流源设计软件设计
3.系统软件设计
本系统的软件设计采用C51语言和汇编语言混合编程。
主体程序采用C51编写,与硬件有关的程序、特别是对时序要求较严格的程序用汇编语言编写,即键盘扫描子程序、写TLC5618子程序、读MC14433子程序、显示缓冲子程序。
因为采用了C51和汇编语言混合编程的方式,故大大提高了本系统软件设计的效率和质量。
数控电流源的软件开发在KeilμVision4集成开发环境下完成的。
KeilμVision4集成开发环境是基于80C51内核的微处理器软件开发平台,内嵌多种符合当前工业标准的开发流程。
可以完成从工程建立、管理、编译连接、目标代码的生成、软件仿真、硬件仿真等完整的开发流程。
尤其是C语言编译工具在产生代码的准确性和效率方面达到了较高的水平,而且可以附加灵活的控制选项,在开发大型项目时非常理想。
KeilμVision4的使用方法是:
1.启动KeilμVision4集成开发环境,创建一个工程文件,并从器件数据库里选择一款CPU芯片(本课题使用AT89C52芯片);2.根据应用要求,在PC上用文本编辑软件编写C语言源程序、汇编语言源程序;利用编译工具软件对源程序进行编译,生成目标文件(.obj文件);利用连接工具对目标程序进行连接定位,生成绝对程序,将程序转化为十六进制代码程序(.hex文件),急可以装载到CPU芯片上运行。
3.1主程序
3.1.1主程序流程框图及程序
主程序流程框图如图3-1所示。
由主程序流程框图可知,其中的“扫描键盘”起到了很重要的作用,扫描键盘函数的返回值作为C51主程序中Switch语句的开关变量,根据不同的返回值进行相应的按键处理,因而主程序流程框图相当简单,并且系统软件整体程序的可读性高。
主程序是数控电流源软件设计的核心,主要由电流给定值设置功能函数、电流步进值设置功能函数、菜单选择功能函数、数码管定时刷新功能函数以及中断设置等构成。
设置电流给定值程序流程框图如图3-2所示,设置电流步进值程序流程框图如图3-3所示。
为完成数控电流源整体系统设计,在C51主程序中适时调用键盘扫描汇编语言子程序、写5618汇编语言子程序、读MC14433汇编语言子程序、显示缓冲汇编语言子程序,从而体现了C51语言程序和汇编语言程序相互调用的方便性。
图3-1主程序流程框图
#include
#defineucharunsignedchar
#defineuintunsignedint
sbitledbit=P2^0;/*功能指示灯控制位*/
ucharidatabuffer[8];/*定义键盘输入缓冲区*/
ucharidatakeycode;/*扫描键盘码变量*/
ucharidatastepval=1;/*步进值变量*/
ucharidatashowflag=0;/*当前显示标志,用以决定当前显示内容*/
uintidatagivecur=0;/*电流输出给定值控制变量*/
uintidatatruecur;/*电流实测值变量*/
externucharreadkey(void);/*声明扫描键盘函数为外部函数,此函数使用
汇编语言编写*/
externvoidshowbuffer(uchar*);/*声明缓冲区显示函数为外部函数,入口参数
为全局变量数组buffer的首址*/
externvoidwrite5618(uint);/*声明写TLC5618为外部函数,入口参数为要
写入的16-bit二进制数据,默认为TLC5618
的模拟A通道*/
externuintread14433(void);/*声明读MC14433为外部函数,无入口参数,
出口参数为读出的16-bit二进制数据*/
/*函数原型:
voidde15s(void)*/
/*功能:
信息提示延时显示,按任意键返回*/
/*调用函数:
readkey()*/
/*入口参数:
无*/
/*出口参数:
无*/
voidde15s(void)
{
uintm,n;
for(m=0;m<=2000;m++)
{
if(readkey()!
=0xff)break;/*按任意键跳出循环*/
for(n=0;n<=500;n++){}
}
}
setcur()
setsetp()
/*函数原型:
voidmenufun(void)*/
/*功能:
菜单选择功能函数,通过菜单选择功能函数,以进行相应的功能操作*/
/*调用函数:
readkey()*/
/*入口参数:
无*/
/*出口参数:
无*/
menufun()
{
ucharidatan;
ucharnumcount=0;
showflag=1;
ledbit=1;
P0=0xfe;
ledbit=0;
buffer[0]=0x0a;/*初始化8位数码管显示:
-灭灭灭灭灭灭灭*/
for(n=1;n<8;n++)
{
buffer[n]=0x0d;
}
while(showflag==0x01)
{
do/*不断扫描键盘,直到有键按下*/
{
keycode=readkey();
}while(keycode==0xff);
switch(keycode)/*根据按下的键值,进行相应操作*/
{
case0:
;
case1:
;
case2:
;
case3:
;
case4:
;
case5:
;
case6:
;
case7:
;
case8:
;
case9:
if(numcount!
=1)/*缓冲区只接收1位电流给定值数据输入*/
{
buffer[numcount]=keycode;/*置入键盘输入数据至键盘输入缓冲区*/
numcount++;/*每输入一个数据,缓冲区指针自加1*/}
break;
case0x0b:
showflag=0x00;/*返回键按下,则返回默认的显示状态*/
ledbit=1;
P0=0xff;
ledbit=0;
break;
case0x0c:
if(numcount==0x01)/*撤销键按下,则往前置入一横杠,以撤
{销前面已输入的一位数据*/
numcount--;
buffer[0]=0x0a;
}
break;
case0x0d:
if(numcount==1)/*确定键按下,根据键入的1位数据,进行
switch(buffer[0])相应操作*/
{
case0x01:
setcur();/*选择1号功能则进行给定电流值设置*/
showflag=0;
break;
case0x02:
setstep();/*选择2号功能则进行给定电流值设置*/
showflag=0;
break;
default:
break;
}
default:
break;
}
}
}
/*函数原型:
voidintt0(void)*/
/*功能:
定时中断函数,用于数码显示定时刷新*/
/*调用函数:
showbuffer()*/
/*入口参数:
无*/
/*出口参数:
无*/
voidintt0(void)interrupt1
{
uintidatan;
TH0=0xb8;/*重装定时值*/
TL0=0x00;
switch(showflag)/*根据刷新标志选择不同的刷新内容*/
{
case0:
n=givecur;/*刷新给定电流值千位、百位、十位、各位*/
buffer[0]=(uchar)(n/1000);
buffer[1]=(uchar)((n-(uint)buffer[0]*1000)/100);
buffer[2]=(uchar)((n-(uint)buffer[0]*1000-(uint)buffer[1]*100)/10);
buffer[3]=(uchar)(n-(uint)buffer[0]*1000-(uint)buffer[1]*100
-(uint)buffer[2]*10);
n=truecur;/*刷新实际电流值千位、百位、十位、各位*/
buffer[4]=(uchar)(n/1000);
buffer[5]=(uchar)((n-(uint)buffer[4]*1000)/100);
buffer[6]=(uchar)((n-(uint)buffer[4]*1000-(uint)buffer[5]*100)/10);
buffer[7]=(uchar)(n-(uint)buffer[4]*1000-(uint)buffer[5]*100
-(uint)buffer[6]*10);
showbuffer(buffer);
break;
case1:
showbuffer(buffer);break;
default:
break;
}
}
/*函数原型:
voidext0(void)*/
/*功能:
外部中断函数,用于读取MC14433的转换数据*/
/*调用函数:
read14433()*/
/*入口参数:
无*/
/*出口参数:
无*/
voidext0(void)interrupt0
{
uintn;
n=read14433();/*读取MC14433的转换数据,并转换为十进制*/
n=((n&0xf000)>>12)*1000+((n&0x0f00)>>8)*100+((n&0x00f0)>>4)*10+(n&0x000f);
}
main()/*主函数*/
{
ucharidatan;
uintidatam;
SP=0x40;/*修改堆栈指针*/
for(m=0;m<1000;m++)/*延时*/
{
}
EA=1;/*CPU开中断*/
ET0=0;/*允许定时器0定时中断*/
EX0=0;/*允许外部中断0中断*/
IT0=0;/*外部中断采用负边沿触发方式*/
TMOD=0X01;/*定时器采用16位定时工作方式*/
TH0=0XB8;/*设置等时期计数初值*/
TL0=0X00;
TR0=1;/*启动定时器0*/
while
(1)
{
do/*不断扫描按键,直到有键按下*/
{
keycode=readkey();
}while(keycode==0xff);
switch(keycode)/*根据按下键值,进行相应操作*/
{
case0x0a:
menufun();/*菜单键按下,进入菜单选择功能*/
break;
case0x0e:
m=givecur+stepval;/*“+”键按下,将给定值与步进值相加赋值m*/
if(m<=2000)/*若m小于等于2000,将累加值赋值给电流给值
{变量*/
givecur=m;
m=((givecur&0x0fff)*2)|0xc000;/*合成TLC5618数据写入格式*/
EX0=0;/*TLC对5618串口器件进行操作需要首先关闭
ET0=0;一切中断源*/
write5618(m);/*将合成数据写入TLC5618*/
EX0=1;/*串口操作结束之后再回复中断操作*/
ET0=1;
}
break;
case0x0f:
if(givecur!
=0)/*“-”键按下,将给定值与步进值相减*/
{
for(n=0;n{
givecur--;
if(givecur==0)
break;
}
m=((givecur&0x0fff)*2)|0xc000;/*合成TLC5618数据写入格式*/
EX0=0;/*TLC对5618串口器件进行操作需要首先关闭
ET0=0;一切中断源*/
write5618(m);/*将合成数据写入TLC5618*/
ET0=1;/*串口操作结束之后再回复中断操作*/
EX0=1;
}
default:
break;
}
}
}
3.1.2设置电流给定值程序框图及程序
在菜单选择功能函数中,按下数字键“1”后,再按下“确定”键,显示切换为4个横杠,这是可以通过按数字键,置入电流数值以取代4个横杠,再按下确定键之后,则可将输入的电流给定值设置为当前的输出电流给定值。
但是输入的电流值必须在0~2000mA以内,并且必须置满4位数值,否则会显示出错信息“ERROR”,要求重新输入有效的电流值。
错误提示显示大约5秒后会自动返回该操作的初始化显示状态,也可以通过按任意键返回该操作的初始化显示状态。
如果中途不想再执行该操作,可以按“返回”键返回默认显示状态;如果输入过程中有错误所输入,可以按“撤销”键撤销前面已输入的电流值数据。
设置电流给定值程序框图如图3-2所示。
图3-2设置电流给定值程序框图
/*函数原型:
voidsetcur(void)*/
/*功能:
电流给定值设置功能函数,通过矩阵式键盘可快速设置2000mA以内的任意电流*/
/*调用函数:
readkey()、del5s()*/
/*入口参数:
无*/
/*出口参数:
无*/
setcur()
{
uintn;
ucharnumcount=0;
ledbit=1;
P0=0xfd;
ledbit=0;/*初始化功能指示灯不亮,表示正在进行的是
设置电流给定值的操作*/
for(n=0;n<4;n++)/*初始化8位数码管显示:
{----灭灭灭灭*/
buffer[n]=0x0a;
}
for(n=4;n<8;n++)
{
buffer[n]=0x0d;
}
while(showflag==0x01)
{
do/*不断扫描键盘,直到右键按下*/
{
keycode=readkey();
}while(keycode==0xff);
switch(keycode)/*根据按下的键值,进行相应操作*/
{
case0:
;
case1:
;
case2:
;
case3:
;
case4:
;
case5:
;
case6:
;
case7:
;
case8:
;
case9:
if(numcount!
=4)/*缓冲区只接收4位电流给定值数据输入*/
{
buffer[numcount]=keycode;/*置入键盘输入数据至键盘输入缓冲区*/
numcount++;/*每输入一个数据,缓冲区指针自加1*/
}
break;
case0x0b:
showflag=0x00;/*返回键按下,则返回默认的显示状态*/
P0=0xff;
ledbit=1;
ledbit=0;
break;
case0x0c:
if(numcount!
=0x0)/*撤销键按下,则往前置入一横杠,以撤
{销前面已输入的一位数据*/
numcount--;
buffer[numcount]=0x0a;
}
break;
case0x0d:
n=(uint)buffer[0]*1000+(uint)buffer[1]*100+(uint)buffer[2]*
10+(uint)buffer[3];/*确定键按下,且输入电流值为小于2000
if((numcount==4)&&(n<=2000))的4位数,则将给定电流值合成要写入
{TLC5618的16-bit二进制数据*/
givecur=n;
n=((givecur&0x0fff)*2)|0xc000;
EX0=0;
ET0=0;
write5618(n);/*将合成的数据写入TLC5618*/
EX0=1;
ET0=1;
showflag=0;
ledbit=1;
P0=0xff;
ledbit=0;/*恢复默认显示状态*/
}
else/*确定键按下,但输入电流值无效,则显示{ERROR的错误提示*/
buffer[0]=0x0b;
buffer[1]=0x0c;
buffer[2]=0x0c;
buffer[3]=0x00;
buffer[4]=0x0c;
buffer[5]=0x0d;
buffer[6]=0x0d;
buffer[7]=0x0d;
de15s();/*延时5s自动返回或按任意键返回*/
for(n=0;n<4;n++)/*重新初始化8位数码管显示:
*(buffer+n)=0x0a;----灭灭灭灭*/
for(n=4;n<8;n++)
*(buffer+n)=0x0d;
numcount=0x00;/*恢复缓冲区初始指针*/
}
break;
default:
break;
}
}
}
3.1.3设置电流步进值程序流程框图及程序
在菜单选择功能函数中,按下数字键“2”后,再按下“确定”键,这时可以通过按数字键,置入电流步进值以取代2个横杠,再按下“确定”键之后,则可将输入的电流步进值设置为当前的电流步进值,可以设置的电流步进值范围为0~99mA。
其他功能按键的操作同上。
设置电流步进值程序流程框图如图3-3所示。
比较图3-2和图3-3所示,二者很相似,这种相似性有利于程序代码的编写。
图3-3设置电流步进值程序流程框图
/*函数原型:
voidsetsetp(void)*/
/*功能:
步进值设置功能函数,用来设置每次“+”、“—”键按下时的步进值*/
/*调用函数:
readkey()、del5s*/
/*入口参数:
无*/
/*出口参数:
无*/
setstep()
{
ucharidatan;
ucharidatanumcount=0;
ledbit=1;
P0=0xfb;
ledbit=0;
for(n=0;n<2;n++)/*初始化8位数码管显示:
{--灭灭灭灭灭灭*/
buffer[n]=0x0a;
}
for(n=2;n<8;n++)
{
buffer[n]=0x0d;
}
while(showflag==0x01)
{
do/*不断扫描键盘,直到有键按下*/
{
keycode=readkey();
}while(keycode==0xff);
switch(keycode)/*根据按下的键值,进行相应操作*/
{
case0:
;
case1:
;
case2:
;
case3:
;
case4:
;
case5:
;
case6:
;
case7:
;
case8:
;
case9:
if(numcount!
=2)/*缓冲区只接收4位电流给定值数据输入*/
{
buffer[numcount]=keycode;/*置入键盘输入数据至键盘输入缓冲区*/
numcount++;/*每输入一个数据,缓冲区指针自加1*/
}
break;
case0x0b:
showflag=0x00;/*返回键按下,则返回默认的显示状态*/
ledbit=1;
P0=0xff;
ledbit=0;
break;
case0x0c:
if(numcount!
=0x0)/*撤销键按下,则往前置入一横杠,以撤
{销前面已输入的一位数据*/numcount--;
buffer[numcount]=0x0a;
}
break;
case0x0d:
if(numcount==2)/*确认键按下,且步进电流值为2位,则将
{设置的2位步进值赋值给步进值变量*/
stepval=buffer[0]*10+buffer[1];
showflag=0;
ledbit=1;
P0=0xff;
ledbit=0;/*恢复默认显示状态*/
}
else/*确定键按下,但输入步进电流值不是2
{位,则显示ERROR的错误提示*/
buffer[0]=0x0b;
buffer[1]=0x0c;
buffer[2]=0x0c;
buffer[3]=0x00;
buffer[4]=0x0c;
buffer[5]=0x0d;
buffer[6]=0x0d;
buffer[7]=0x0d;
de15s();/*延时5s自动返回或按任意键返回*/
for(n=0;n<2;n++)/*重新初始化8位数码管显示:
*(buffer+n)=0x0a;--灭灭灭灭灭灭*/
for(n=4;n<8;n++)
*(buffer+n)=0x0d;
numcount=0x00;/*恢复缓冲区初始指针*/
}
break;
default:
break;
}
}
}
3.2键盘扫描程序流程框图及程序
数控电流源主程序中频繁调用键盘扫描子程序,键盘扫描子程序主要完成键入数值、返回、撤销、确认等功能。
本设计中,4*4矩阵键盘工作在循环扫描工作方式,主要有判断键盘上是否有键按下、去除键的抖动影响、扫描键盘、判断闭合的键是否释放等内容,C51语言程序在调