




版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、3.系统软件设计本系统的软件设计采用C51语言和汇编语言混合编程。主体程序采用C51编写,与硬件有关的程序、特别是对时序要求较严格的程序用汇编语言编写,即键盘扫描子程序、写TLC5618子程序、读MC14433子程序、显示缓冲子程序。因为采用了C51和汇编语言混合编程的方式,故大大提高了本系统软件设计的效率和质量。数控电流源的软件开发在 Keil Vision4集成开发环境下完成的。Keil Vision4集成开发环境是基于80C51内核的微处理器软件开发平台,内嵌多种符合当前工业标准的开发流程。可以完成从工程建立、管理、编译连接、目标代码的生成、软件仿真、硬件仿真等完整的开发流程。尤其是C语
2、言编译工具在产生代码的准确性和效率方面达到了较高的水平,而且可以附加灵活的控制选项,在开发大型项目时非常理想。Keil Vision4的使用方法是:1.启动Keil Vision4集成开发环境,创建一个工程文件,并从器件数据库里选择一款CPU芯片(本课题使用AT89C52芯片);2.根据应用要求,在PC上用文本编辑软件编写C语言源程序、汇编语言源程序;利用编译工具软件对源程序进行编译,生成目标文件(.obj文件);利用连接工具对目标程序进行连接定位,生成绝对程序,将程序转化为十六进制代码程序(.hex文件),急可以装载到CPU芯片上运行。3.1主程序3.1.1主程序流程框图及程序主程序流程框图
3、如图3-1所示。由主程序流程框图可知,其中的“扫描键盘”起到了很重要的作用,扫描键盘函数的返回值作为C51主程序中Switch语句的开关变量,根据不同的返回值进行相应的按键处理,因而主程序流程框图相当简单,并且系统软件整体程序的可读性高。主程序是数控电流源软件设计的核心,主要由电流给定值设置功能函数、电流步进值设置功能函数、菜单选择功能函数、数码管定时刷新功能函数以及中断设置等构成。设置电流给定值程序流程框图如图3-2所示,设置电流步进值程序流程框图如图3-3所示。为完成数控电流源整体系统设计,在C51主程序中适时调用键盘扫描汇编语言子程序、写5618汇编语言子程序、读MC14433汇编语言子
4、程序、显示缓冲汇编语言子程序,从而体现了C51语言程序和汇编语言程序相互调用的方便性。图3-1 主程序流程框图#include <reg52.h>#define uchar unsigned char#define uint unsigned intsbit ledbit=P20; /* 功能指示灯控制位 */uchar idata buffer8; /* 定义键盘输入缓冲区 */uchar idata keycode; /* 扫描键盘码变量 */uchar idata stepval=1; /* 步进值变量 */uchar idata showflag=0; /* 当前显示标志,
5、用以决定当前显示内容 */uint idata givecur=0; /* 电流输出给定值控制变量 */uint idata truecur; /* 电流实测值变量 */extern uchar readkey(void); /* 声明扫描键盘函数为外部函数,此函数使用汇编语言编写 */ extern void showbuffer(uchar*); /* 声明缓冲区显示函数为外部函数,入口参数为全局变量数组buffer的首址 */extern void write5618(uint); /* 声明写TLC5618为外部函数,入口参数为要写入的16-bit二进制数据,默认为TLC5618的模拟
6、A通道 */extern uint read14433(void); /* 声明读MC14433为外部函数,无入口参数,出口参数为读出的16-bit二进制数据 */* 函数原型:void de15s(void) */* 功能:信息提示延时显示,按任意键返回 */* 调用函数:readkey( ) */* 入口参数:无 */* 出口参数:无 */void de15s(void) uint m,n; for(m=0;m<=2000;m+) if(readkey()!=0xff)break; /* 按任意键跳出循环*/for(n=0;n<=500;n+) setcur( )setsetp
7、( )/* 函数原型:void menufun(void) */* 功能:菜单选择功能函数,通过菜单选择功能函数,以进行相应的功能操作 */* 调用函数:readkey( ) */* 入口参数:无 */* 出口参数:无 */menufun() uchar idata n; uchar numcount=0; showflag=1; ledbit=1; P0=0xfe; ledbit=0; buffer0=0x0a; /* 初始化8位数码管显示: - 灭 灭 灭 灭 灭 灭 灭 */ for(n=1;n<8;n+) buffern=0x0d; while(showflag=0x01) do
8、 /* 不断扫描键盘,直到有键按下 */ keycode=readkey(); while(keycode=0xff); switch(keycode) /*根据按下的键值,进行相应操作 */ case 0:;case 1:;case 2:;case 3:;case 4:;case 5:;case 6:;case 7:;case 8:;case 9: if(numcount!=1) /* 缓冲区只接收1位电流给定值数据输入 */ buffernumcount=keycode;/* 置入键盘输入数据至键盘输入缓冲区 */ numcount+; /* 每输入一个数据,缓冲区指针自加1 */ bre
9、ak;case 0x0b: showflag=0x00; /* 返回键按下,则返回默认的显示状态 */ ledbit=1; P0=0xff; ledbit=0; break;case 0x0c: if(numcount=0x01) /* 撤销键按下,则往前置入一横杠,以撤 销前面已输入的一位数据 */numcount-; buffer0=0x0a; break;case 0x0d: if(numcount=1) /* 确定键按下,根据键入的1位数据,进行switch(buffer0) 相应操作 */ case 0x01: setcur();/*选择1号功能则进行给定电流值设置 */ showf
10、lag=0; break; case 0x02: setstep();/*选择2号功能则进行给定电流值设置 */ showflag=0; break; default: break; default: break; /* 函数原型:void intt0(void) */* 功能:定时中断函数,用于数码显示定时刷新 */* 调用函数:showbuffer( ) */* 入口参数:无 */* 出口参数:无 */void intt0(void) interrupt 1 uint idata n; TH0=0xb8; /* 重装定时值 */ TL0=0x00; switch(showflag) /*
11、根据刷新标志选择不同的刷新内容 */ case 0: n=givecur; /* 刷新给定电流值千位、百位、十位、各位 */buffer0=(uchar)(n/1000);buffer1=(uchar)(n-(uint)buffer0*1000)/100);buffer2=(uchar)(n-(uint)buffer0*1000-(uint)buffer1*100)/10); buffer3=(uchar)(n-(uint)buffer0*1000-(uint)buffer1*100-(uint)buffer2*10); n=truecur; /* 刷新实际电流值千位、百位、十位、各位 */
12、buffer4=(uchar)(n/1000);buffer5=(uchar)(n-(uint)buffer4*1000)/100);buffer6=(uchar)(n-(uint)buffer4*1000-(uint)buffer5*100)/10);buffer7=(uchar)(n-(uint)buffer4*1000-(uint)buffer5*100-(uint)buffer6*10);showbuffer(buffer);break; case 1: showbuffer(buffer);break;default: break; /* 函数原型:void ext0(void) *
13、/* 功能:外部中断函数,用于读取MC14433的转换数据 */* 调用函数:read14433( ) */ /* 入口参数:无 */* 出口参数:无 */void ext0(void) interrupt 0 uint n; n=read14433(); /* 读取MC14433的转换数据,并转换为十进制 */ n=(n&0xf000)>>12)*1000+(n&0x0f00)>>8)*100+(n&0x00f0)>>4)*10+(n&0x000f); main() /* 主函数 */ uchar idata n; uint
14、 idata m; 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(key
15、code=0xff); switch(keycode) /* 根据按下键值,进行相应操作 */ case 0x0a: menufun(); /* 菜单键按下,进入菜单选择功能 */ break; case 0x0e: m=givecur+stepval; /*“+”键按下,将给定值与步进值相加赋值m*/ if(m<=2000) /* 若m小于等于2000,将累加值赋值给电流给值 变量 */ givecur=m; m=(givecur&0x0fff)*2)|0xc000; /* 合成TLC5618数据写入格式 */ EX0=0; /* TLC对5618串口器件进行操作需要首先关闭
16、ET0=0; 一切中断源 */ write5618(m); /* 将合成数据写入TLC5618 */ EX0=1; /* 串口操作结束之后再回复中断操作 */ ET0=1; break; case 0x0f: if(givecur!=0) /*“-”键按下,将给定值与步进值相减*/ for(n=0;n<stepval;n+) givecur-; if(givecur=0) break; m=(givecur&0x0fff)*2)|0xc000; /* 合成TLC5618数据写入格式 */ EX0=0; /* TLC对5618串口器件进行操作需要首先关闭 ET0=0; 一切中断源
17、*/write5618(m); /* 将合成数据写入TLC5618 */ ET0=1; /* 串口操作结束之后再回复中断操作 */ EX0=1; default: break; 3.1.2设置电流给定值程序框图及程序在菜单选择功能函数中,按下数字键“1”后,再按下“确定”键,显示切换为4个横杠,这是可以通过按数字键,置入电流数值以取代4个横杠,再按下确定键之后,则可将输入的电流给定值设置为当前的输出电流给定值。但是输入的电流值必须在02000mA以内,并且必须置满4位数值,否则会显示出错信息“ERROR”,要求重新输入有效的电流值。错误提示显示大约5秒后会自动返回该操作的初始化显示状态,也可以
18、通过按任意键返回该操作的初始化显示状态。如果中途不想再执行该操作,可以按“返回”键返回默认显示状态;如果输入过程中有错误所输入,可以按“撤销”键撤销前面已输入的电流值数据。设置电流给定值程序框图如图3-2所示。图3-2 设置电流给定值程序框图/* 函数原型:void setcur(void) */* 功能:电流给定值设置功能函数,通过矩阵式键盘可快速设置2000mA以内的任意电流 */* 调用函数:readkey( )、del5s( ) */* 入口参数:无 */* 出口参数:无 */setcur() uint n; uchar numcount=0; ledbit=1; P0=0xfd; l
19、edbit=0; /* 初始化功能指示灯不亮,表示正在进行的是设置电流给定值的操作 */ for(n=0;n<4;n+) /* 初始化8位数码管显示: - - - - 灭 灭 灭 灭 */buffern=0x0a; for(n=4;n<8;n+) buffern=0x0d; while(showflag=0x01) do /* 不断扫描键盘,直到右键按下*/ keycode=readkey( ); while(keycode=0xff); switch(keycode) /* 根据按下的键值,进行相应操作*/ case 0:; case 1:;case 2:;case 3:;cas
20、e 4:;case 5:;case 6:;case 7:;case 8:;case 9:if(numcount!=4) /* 缓冲区只接收4位电流给定值数据输入*/ buffernumcount=keycode;/* 置入键盘输入数据至键盘输入缓冲区 */ numcount+; /* 每输入一个数据,缓冲区指针自加1 */break;case 0x0b: showflag=0x00; /* 返回键按下,则返回默认的显示状态 */ P0=0xff; ledbit=1; ledbit=0; break;case 0x0c: if(numcount!=0x0) /* 撤销键按下,则往前置入一横杠,以
21、撤 销前面已输入的一位数据 */ numcount-; buffernumcount=0x0a; break;case 0x0d: n=(uint)buffer0*1000+(uint)buffer1*100+(uint)buffer2*10+(uint)buffer3; /* 确定键按下,且输入电流值为小于2000if(numcount=4)&&(n<=2000) 的4位数,则将给定电流值合成要写入 TLC5618的16-bit二进制数据 */ givecur=n; n=(givecur&0x0fff)*2)|0xc000; EX0=0; ET0=0; writ
22、e5618(n); /*将合成的数据写入TLC5618 */ EX0=1; ET0=1; showflag=0; ledbit=1; P0=0xff; ledbit=0; /* 恢复默认显示状态 */ else /* 确定键按下,但输入电流值无效,则显示 ERROR的错误提示 */ buffer0=0x0b; buffer1=0x0c; buffer2=0x0c; buffer3=0x00; buffer4=0x0c; buffer5=0x0d; buffer6=0x0d; buffer7=0x0d; de15s(); /* 延时5s自动返回或按任意键返回 */ for(n=0;n<4;
23、n+) /* 重新初始化8位数码管显示: *(buffer+n)=0x0a; - - - - 灭 灭 灭 灭 */ for(n=4;n<8;n+) *(buffer+n)=0x0d; numcount=0x00; /* 恢复缓冲区初始指针 */ break;default: break; 3.1.3设置电流步进值程序流程框图及程序在菜单选择功能函数中,按下数字键“2”后,再按下“确定”键,这时可以通过按数字键,置入电流步进值以取代2个横杠,再按下“确定”键之后,则可将输入的电流步进值设置为当前的电流步进值,可以设置的电流步进值范围为099mA。其他功能按键的操作同上。设置电流步进值程序流
24、程框图如图3-3所示。比较图3-2和图3-3所示,二者很相似,这种相似性有利于程序代码的编写。图3-3 设置电流步进值程序流程框图/* 函数原型:void setsetp(void) */* 功能:步进值设置功能函数,用来设置每次“+”、“”键按下时的步进值 */* 调用函数:readkey( )、del5s */* 入口参数:无 */* 出口参数:无 */setstep() uchar idata n; uchar idata numcount=0; ledbit=1; P0=0xfb; ledbit=0; for(n=0;n<2;n+) /* 初始化8位数码管显示: - - 灭 灭
25、灭 灭 灭 灭 */buffern=0x0a; for(n=2;n<8;n+) buffern=0x0d; while(showflag=0x01) do /* 不断扫描键盘,直到有键按下 */ keycode=readkey(); while(keycode=0xff); switch(keycode) /*根据按下的键值,进行相应操作 */ case 0:;case 1:;case 2:;case 3:;case 4:;case 5:;case 6:;case 7:;case 8:;case 9:if(numcount!=2) /* 缓冲区只接收4位电流给定值数据输入 */ buff
26、ernumcount=keycode;/* 置入键盘输入数据至键盘输入缓冲区 */ numcount+; /* 每输入一个数据,缓冲区指针自加1 */break;case 0x0b: showflag=0x00; /* 返回键按下,则返回默认的显示状态 */ ledbit=1; P0=0xff; ledbit=0; break;case 0x0c: if(numcount!=0x0) /* 撤销键按下,则往前置入一横杠,以撤 销前面已输入的一位数据 */ numcount-; buffernumcount=0x0a; break;case 0x0d: if(numcount=2) /* 确认键
27、按下,且步进电流值为2位,则将 设置的2位步进值赋值给步进值变量 */ stepval=buffer0*10+buffer1; showflag=0; ledbit=1; P0=0xff; ledbit=0; /* 恢复默认显示状态 */ else /* 确定键按下,但输入步进电流值不是2 位,则显示ERROR的错误提示 */ buffer0=0x0b; buffer1=0x0c; buffer2=0x0c; buffer3=0x00; buffer4=0x0c; buffer5=0x0d; buffer6=0x0d; buffer7=0x0d; de15s(); /* 延时5s自动返回或按任
28、意键返回 */ 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矩阵键盘工作在循环扫描工作方式,主要有判断键盘上是否有键按下、去除键的抖动影响、扫描键盘、判断闭合的键是否释放等
29、内容,C51语言程序在调用汇编语言程序时,用过工作寄存器R7完成参数的传递。键盘扫描程序流程框图如图3-4所示。图3-4 键盘扫描程序流程框图NAME READKEY ;汇编语言子程序名称为READKEY?PR?READKEY?READKEY SEGMENT CODE PUBLIC READKEY RSEG ?PR?READKEY?READKEY READKEY: PUSH ACC ;保护现场 PUSH PSW PUSH DPL PUSH DPH PUSH 0 PUSH 1 PUSH 2 PUSH 3 MOV R0,#0F7H ;设置扫描字 MOV R1,#00H ;初始化键码 LP1: MO
30、V A,R0 ;将扫描字送入P1口 MOV P1,A MOV A,P1 ;读出P1口列状态 MOV R2,A ;列状态暂存R2 SETB C MOV R3,#04H LP2: RLC A; JNC KEY; ;判断是否有键按下。有键按下,跳至KEY LP3: INC R1; ;无键按下,键码加1 DJNZ R3,LP2 ;继续扫描列,至4列扫描完毕 MOV A,R0 ;扫描下一行 SETB C RRC A MOV R0,A JC LP1 ;判断4行是否全部扫描完毕 MOV R7,#0FFH ;返回OxFF表示无键按下 LJMP ENDCHECKKEY ;跳至恢复现场,程序结束 KEY: LCA
31、LL DEL10MS ;延时10ms去抖动 MOV A,P1 ;再次扫描原列 XRL A,R2 ;A=0,两次扫描相符;A0,不符 JNZ LP3 ;判断两次扫描值是否相符 LP4: MOV A,P1 ;两次扫描值相符,再次扫描原列 XRL A,R2 ;A0,按键释放;A=0,按键未释放 JZ LP4 ;判断按键是否释放 MOV A,R1 ;按键释放,根据键码查表求键值 MOV DPTR,#KEYTAB ;置键盘码表首地址至DPTR MOVC A,A+DPTR ;查表 MOV R7,A ;扫描值通过R7返回至主程序ENDCHECKKEY:POP 3 ;恢复现场 POP 2 POP 1 POP
32、0 POP DPH POP DPL POP PSW POP ACC RETDEL10MS: MOV R6,#100 ;延时10ms子程序 LOP1: MOV R7,#100 DJNZ R7,$ DJNZ R6,LOP1 RET KEYTAB: ;键盘码表 DB 1H,2H,3H,0AH ;“1”,“2”,“3”,“菜单” DB 4H,5H,6H,0BH ;“4”,“5”,“6”,“返回” DB 7H,8H,9H,0CH ;“7”,“8”,“9”,“撤销” DB 0EH,0H,0FH,0DH ;“+”,“0”,“-”,“确认” END3.3 显示缓冲器汇编语言子程序显示子程序的功能,是把显示缓冲
33、区中的十六进制数据取出,查表后转换成相应的字形码,然后送到数码管中,驱动LED数码管进行显示。所以需要执行显示或更新显示时,必须先向显示缓冲区中送待显示数据,然后在调用显示子程序。NAME SHOWBUFFER ;汇编语言子程序名为SHOWBUFFER?PR?SHOWBUFFER?SHOWBUFFER SEGMENT CODE PUBLIC _SHOWBUFFER RSEG ?PR?SHOWBUFFER?SHOWBUFFER_SHOWBUFFER: PUSH ACC ;保护现场 PUSH PSW PUSH DPL PUSH DPH PUSH 2 PUSH 3 MOV DPTR,#BLEDTAB
34、 ;字型码表的入口 MOV R3,#8 ;显示8个数据 BLOOP2: MOV A,R1 ;取待显示数据首地址 MOVC A,A+DPTR ;查表获得字型码 MOV R2,#8 ;每个字型码有8位 BLOOP1: RLC A ;向串行数据口TXD发送数据 CLR P3.4 MOV P3.1,C SETB P3.4 DJNZ R2,BLOOP1 ;直到每个数据的8位全发送完 DEC R1 ;指针指向下一位,准备取下一个待显示数据 DJNZ R3,BLOOP2 ;直到8个数据全显示完 CLR P3.3 ;触发外部中断1 SETB P3.3 POP 3 ;恢复现场 POP 2 POP DPH POP
35、 DPL POP PSW POP ACC RETBLEDTAB: ;字形码表DB 0fcH,60H,0daH,0f2H ;“0”,“1”,“2”,“3” DB 66H,0b6H,0beH,0e0H ;“4”,“5”,“6”,“7” DB 0feH,0f6H,2H,9eH ;“8”,“9”,“-”,“E” DB 0eeH,00H,0ecH,8eH ;“R”,“ ”,“n”,“F” DB 7cH,7aH,1cH,3eH ;“U”,“d”,“L”,“b” END3.4写TLC5618汇编语言子程序 由键盘输入的给定电流值经MCU控制器处理后为数字量,而外电路只能接受模拟量输入,TLC5618在数控电
36、流源系统中完成DA转换。TLC5618的工作方式及时序为:当片选信号CS为低电平时,输入数据由时钟定时,以最高有效位在前的方式读入16-bit移位寄存器。串行时钟输入SCLK输入的下降沿把数据移入输入寄存器,然后CS的上升沿把数据送到DAC寄存器。所有CS的跳变应当发生在SCLK输入为高电平时。TLC5618的操作时序图如图3-5所示。图3-5 TLC5618操作时序图NAME WRITE5618 ;汇编语言子程序名称为WRITE5618?PR?_WRITE5618?WRITE5618 SEGMENT CODE PUBLIC _WRITE5618 RSEG ?PR?_WRITE5618?WRI
37、TE5618 DADAT BIT P2.1 ;DADAT定义为P2.1位,即5618的DINDACLK BIT P2.2 ;DACLK定义为P2.2位,即5618的SCLKDACS BIT P2.3 ;DACS定义为P2.3位,即5618的CS_WRITE5618: PUSH ACC ;保护现场 PUSH PSW PUSH 2 EXDA1: SETB DACLK ;时钟信号变高 CLR DACS ;TLC5618时钟信号低电平有效 MOV R2,#08H ;设置循环次数8次MOV A,R6 ;将R6中8位数据写入TLC5618,R6中存放一帧数据的高8位 EXDA2: RLC A MOV DADAT,C CLR DACLK ;SCLK下降沿作用,一位数据送入16位移位寄存器 SETB DACLK ;恢复时钟信号高电平 DJNZ R2,EXDA2 MOV A,R7 ;将R7中8位数据写入TLC5618,R6中存放一帧数据的低8位 MOV R2,#08H ;设置循环次数8次 EXDA3: RLC A MOV DADAT,C CLR DACLK ;SCLK下降沿作用,一位数据
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- GB/T 6974.4-2025起重机术语第4部分:臂架起重机
- 小学生安全说课课件
- 象棋特色活动策划方案模板
- 电子厂新员工转正工作总结
- 小学圣诞节趣味活动方案
- 元旦晚会策划活动方案
- 全国课一等奖统编版语文七年级上册《诫子书》公开课课件
- 气象宣传课件视频
- 大庆食品摊贩管理办法
- 地方债务投资管理办法
- 二年级下二升三数学暑假作业(北师大)
- 浙江一般公需课从大模型到智能超算的思考题库及答案
- 2025年南充市中考语文试卷真题(含标准答案解析)
- 2025届广东省东莞中学八下数学期末学业水平测试试题含解析
- 垃圾三轮车保养协议书
- 2024-2025学年辽宁省沈阳市高二数学下学期7月期末考试(附答案)
- 铁路路基路基标准横断面13课件
- 辽宁省劳动合同模板
- 消防驾驶员行车安全课件
- 《WEBGIS编程入门教程》课件
- 预算编制的目标与指标
评论
0/150
提交评论