1、第7章 软件设计技术 7.1 软件的总体功能2 软件运行于微处理器,其功能由微处理器来决定。微处理器功能由系统的功能结构、与微处理器相连的三个子系统和控制算法所决定。这些功能也可以分成两部分:控制算法功能和一般控制功能 3软件功能的实时性 意义:强调在规定的时间里执行相应的操作,误时操作会导致严重的后果。软件的实时性要满足两方面的要求:一是实时动作响应。二是实时数据处理。472 机电一体化系统软件的任务和任务管理 为了便于分析和编程,把各种软件功能化分为小的、单元式的子功能。软件功能是由子功能某种方式组合在一起的。由此,从学术的角度,把子功能提练为任务(类似:进程),软件功能就是任务的组合。软
2、件的编程就包含两个技术,任务的编程和任务的管理。5任务的划分原则 1每个任务必须是独立的;2 每个任务不再可分;3 所有任务的集合能满足整个系统的功能要求。4 划分得到的任务常常按程序运行方式来加以分类描述,如驱动程序、初始化程序、中断程序、控制算法程序、显示程序和键盘(或触摸)输入程序等。5 还可以按分层结构来理解。6基于任务的编程方法 1 前后台编程方法:如果编程人员将全部程序都自行编制,即把任务和任务的管理看做后台程序,中断处理看做前台程序,就是前后台程序编程方法。这是初级的、然而应用很多的编程方法。2.操作系统编程方法:如果任务的管理有通用的、现成的程序,即操作系统,而编程人员只编制任
3、务程序,就称为操作系统编程方法。但是有时也需要 编写驱动程序。7 3.设定式编程方法:这是一种近几年刚刚出现的编程方法,如联发科技推出的MTK平台的软件编程方法。任务和任务的管理均已完成,方便地提供给了开发人员。设定式编程方法编程简单、节省开发时间、程序系统稳定可靠和功能强大,是今后程序编制方法的发展方向。73 机电一体化系统的程序设计方法731 程序设计方法9 1确定程序功能:根据控制系统设计方案确定控制软件功能,根据系统的功能结构确定前面没有提到的其它软件功能。2划分任务:将各类软件功能划分成具体的任务。3确定软件编程要素:任务的组合方式 和编程方法 使用和前边类似的产生和选择方法。(产生
4、与选择)10732 模块化编程技术 应用领域:单片机、操作系统和S7-300 分成不同的程序,即不同的模块 由单独的程序(头文件)组合到一起。有全局变量问题 优点:模块不用更改,结构清晰 区分:子程序在一个程序。733 运水机器人编程实例1 软件功能12运水机器人功能结构(用文字简单叙述)主要事件是将水装入容器、微处理器控制电机驱动轮式行走机构运输容器和从容器卸水。使用锂电池作为能源输入,分别为驱动电机和电控部分提供电能,有克服摩擦力和电气部件能耗等能量损失。有循迹和开关机等输入信号送微处理器处理,显示水量和时间等。13外围部件软件功能 使用C8051F020单片机。控制162字符点阵液晶显示
5、器显示水容量和运水时间。以PWM方式控制电机驱动芯片L298N驱动两路直流减速电机,以开关方式控制微型继电器卸水。对循迹开关信号进行采集。14控制算法功能 对运水机器人行走轨迹进行闭环控制,采用比例(P)调节。15任务划分 任务划分为:初始化配置(config),延时(delay1ms),PCA初始化(PCA_Init),产生PWM脉宽调制的两个任务(PWM0_set、PWM1_set),电机正反转及速度的控制的六个任务(L_FORD、R_FORD、L_BACK、R_BACK、L_BREAK、R_BREAK),八路寻迹(Founding_Line),给lcd送命令(sendc),给lcd送数据
6、(sendd),显示地址定位函数(lcd_pos),lcd初始化函数(lcd_ini),第一次水量显示(lcddisplay1),第二次水量显示(lcddisplay2),显示时间(lcddisplay3)。16任务的组合 在八路寻迹(Founding_Line)中根据取入的八路传感数字信号调用产生PWM脉宽调制的两个任务(PWM0_set、PWM1_set)和电机正反转及速度的控制的六个任务(L_FORD、R_FORD、L_BACK、R_BACK、L_BREAK、R_BREAK),并按控制问题的要求调用第一次水量显示(lcddisplay1)、第二次水量显示(lcddisplay2)和显示时
7、间(lcddisplay3)。17 第一次水量显示(lcddisplay1)、第二次水量显示(lcddisplay2)和显示时间(lcddisplay3)中使用给lcd送命令(sendc)、给lcd送数据(sendd)和显示地址定位函数(lcd_pos)。加入延时(delay1ms)以保证外围部件的响应。任务管理进行初始化配置(config)、PCA初始化(PCA_Init)、电机正转(L_FORD、R_FORD)和调用八路寻迹(Founding_Line)。18编程方法 使用前后台编程方法。195具体编程(1)资源分配 P00电机 1 PWM输出 左轮 P01电机 2 PWM输出 右轮 L_
8、DIR1A=P22左轮电机方向控制 L_DIR1B=P21左轮电机方向控制 R_DIR1A=P25右轮电机方向控制 R_DIR1B=P26右轮电机方向控制20 P10-水泵控制 P11蜂鸣器控制 PCA0CPM0 电机 1 PWM 输出,工作在8位定时器模式,允许比较器匹配中断,每次中断加载新的比较值,实现电机输出的脉宽控制。PCA0CPM1 电机 2 PWM 输出,工作在8位定时器模式,允许比较器匹配中断,每次中断加载新的比较值,实现电机输出的脉宽控制。P6.0-P6.7;传感器接口 lcdrw=P32;-读写控制5 lcdcs=P37;-E使能 6 lcdrs=P36;-命令数据选择控制
9、4 21传感器规定 前四个传感器在低四位,后四个传感器在高四位 左右各两个传感器 不压黑线为低电平头:低四位尾:高四位22记录行走情况 遇垂直黑线次数:int fb=0 微偏:0100/0010 中偏:1100/0011 大偏:1000/000123(2)引用与定义#include#include#include typedef unsigned char uchar;typedef unsigned long ulong;typedef unsigned int uint;#define L_MOTO_BREAK L_DIR1A=L_DIR1B#define L_MOTO_BACK L_DI
10、R1A=0;L_DIR1B=1#define L_MOTO_FORD L_DIR1A=1;L_DIR1B=0#define R_MOTO_BREAK R_DIR1A=R_DIR1B#define R_MOTO_BACK R_DIR1A=0;R_DIR1B=1#define R_MOTO_FORD R_DIR1A=1;R_DIR1B=024 sbit L_DIR1A=P22;sbit L_DIR1B=P21;sbit R_DIR1A=P25;sbit R_DIR1B=P26;sbit P1_0=P10;sbit P1_1=P11;sbit P1_2=P12;25 int fb=0;/控制前后方向
11、 sbit lcdrw=P32;/5 sbit lcdcs=P37;/6 sbit lcdrs=P36;/4 void lcddisplay3(void);void lcddisplay1(void);void lcddisplay2(void);26 此部分包括头文件的定义、宏定义、位定义等,此部分包括头文件的定义、宏定义、位定义等,例如定义例如定义#define L_MOTO_BREAK L_DIR1A=L_DIR1B,即表示在程序中以,即表示在程序中以L_MOTO_BREAK来表示来表示L_DIR1A=L_DIR1B;L_DIR1A代表代表P22口,表示左轮电机方向的控口,表示左轮电机方
12、向的控制;制;L_DIR1B代表代表P21口,亦表示左轮电机方口,亦表示左轮电机方向控制;当向控制;当L_DIR1A=L_DIR1B,即,即L_DIR1A与与L_DIR1B都为都为1或都为或都为0时,即以时,即以L_MOTO_BREAK来表示。下面还有液晶显示屏来表示。下面还有液晶显示屏的的I/O配置以及液晶显示屏的显示等。配置以及液晶显示屏的显示等。27(3)初始化配置,以保证单片机控制功能工作 void config(void)WDTCN=0 x07;WDTCN=0 xde;/看门狗禁止 WDTCN=0 xad;/看门狗禁止 XBR0=0 x50;/配置交叉开关,XBR1=0 x00;XB
13、R2=0 x40;/交叉开关允许P0MDOUT=0 x00;/p0.4p0.5为推挽输出28 P1MDOUT=0 xff;P2MDOUT=0 xff;P3MDOUT=0 xFF;P74OUT=0 x00;/p4-p6 P6=0 xff;OSCXCN=0 x00;OSCICN=0 x16;/采用内部晶振,频率为 8MHZ 29 此部分主要进行初始化配置,以保证单片机的控此部分主要进行初始化配置,以保证单片机的控制功能制功能 WDTCN即为看门狗定时器控制寄存器,此处通即为看门狗定时器控制寄存器,此处通过过WDTCN各位的设置使看门狗禁止各位的设置使看门狗禁止 XBR0、XBR1、XBR2是用来配
14、置交叉开关是用来配置交叉开关的特殊功能寄存器。的特殊功能寄存器。XBR0=0 x50即把即把XBR0的的位位6和位和位4置置1,表示,表示PCA0外部计数器输入连接端外部计数器输入连接端口引脚及口引脚及CEX0和和CEX1链接两个端口引脚;链接两个端口引脚;XBR1=0 x00表示此特殊功能寄存器各位全置表示此特殊功能寄存器各位全置0,即各使能位不连接端口引脚;即各使能位不连接端口引脚;XBR2=0 x40表示表示位位6置置1,即交叉开关使能。,即交叉开关使能。30 P0MDOUT是端口是端口0输出方式寄存器,输出方式寄存器,P0MDOUT=0 x00表示端口引脚的输出方式为漏表示端口引脚的输
15、出方式为漏极开路方式。极开路方式。P1MDOUT、P2MDOUT、P2MDOUT分别是端分别是端口口1、2、3输出方式寄存器,各端口设置为输出方式寄存器,各端口设置为0 xff表示端口引脚的输出方式为推挽方式。表示端口引脚的输出方式为推挽方式。P74OUT是端口是端口47的输出方式寄存器,各位置的输出方式寄存器,各位置0即表示输出方式配置为漏极开路输出方式即表示输出方式配置为漏极开路输出方式 此处表示采用内部振荡器作为系统时钟,此处表示采用内部振荡器作为系统时钟,OSCICN=0 x16表示对内部振荡器使能,并使内表示对内部振荡器使能,并使内部振荡器典型频率为部振荡器典型频率为8MHZ。31(
16、4)延时 void delay1ms(uint time)/延迟子程序0.5MSuint ii;uint jj;for(ii=0;iitime;ii+)for(jj=0;jj=4)P1_0=1;lcddisplay2();delay1ms(210);/延时4s P1_0=0;P1_1=1;lcddisplay3();43 当满足当满足fb=4时时,执行下面的程序执行下面的程序,先进行水先进行水泵放水泵放水,然后进行第二次液晶显示屏显示然后进行第二次液晶显示屏显示,延延时时4s,关闭水泵关闭水泵,P1_1=1表示蜂鸣器响表示蜂鸣器响,然然后再进行延时后再进行延时44 if(fb=1)|(fb=3
17、)P1_2=1;delay1ms(600);P1_2=0;delay1ms(25);R_FORD(229);delay1ms(1);L_FORD(236);delay1ms(50);/延时0.5s 45 当当fb=1或者是或者是fb=3时时,小车回到起点位置小车回到起点位置,P1_2=1表示对小车进行注水表示对小车进行注水,然后延时一然后延时一段时间段时间,注水停止注水停止,再延时再延时25ms,小车前进小车前进46 if(fb=2)L_BACK(240);R_BACK(249);delay1ms(50);/延时0.5s 47 else if(fb=1)|(fb=3)if(P6=0 x00)R
18、_FORD(229);L_FORD(236);此语句与前面此语句与前面if(P6&0 x0F)=0 x0F)对应对应,当不满足条件时当不满足条件时,执行下面的程序执行下面的程序48 P6=0 x00,用二进制表示即为用二进制表示即为00000000,即即各路传感器返回值均为各路传感器返回值均为0,表示表示8路传感器均路传感器均未压黑线未压黑线,小车前进未跑偏小车前进未跑偏49 if(P6&0 x02)PWM0_set(245);PWM1_set(220);当当P6=0 x02,用二进制表示为用二进制表示为00000010时时,即前四即前四路传感器的右边第二位压黑线路传感器的右边第二位压黑线,此
19、种情况下即表示此种情况下即表示小车左小偏小车左小偏,然后重新调整然后重新调整PWM值对小车进行调值对小车进行调整整50 if(P6&0 x04)PWM0_set(235);PWM1_set(230);if(P6&0 x02)PWM0_set(245);PWM1_set(220);51 当当P6=0 x04,用二进制表示为用二进制表示为00000100时时,即前四路传感器的右边第三位压黑线即前四路传感器的右边第三位压黑线,此种此种情况下即表示小车右小偏情况下即表示小车右小偏,然后重新调整然后重新调整PWM值对小车进行调整值对小车进行调整52 if(P6&0 x04)&(P6&0 x08)PWM0
20、_set(235);PWM1_set(245);if(P6&0 x02)&(P6&0 x01)PWM0_set(255);PWM1_set(215);53(P6&0 x04)&(P6&0 x08)即表示前四路寻即表示前四路寻迹的右边第三、四位寻迹压黑线,此种情迹的右边第三、四位寻迹压黑线,此种情况下即表示小车右中偏况下即表示小车右中偏,然后重新调整然后重新调整PWM值对小车进行调整值对小车进行调整54 if(P6&0 x02)&(P6&0 x01)PWM0_set(255);PWM1_set(215);(P6&0 x02)&(P6&0 x01)即表示前四路寻迹的右即表示前四路寻迹的右边第一、二
21、位寻迹压黑线,此种情况下即表示小边第一、二位寻迹压黑线,此种情况下即表示小车左中偏车左中偏,然后重新调整然后重新调整PWM值对小车进行调整值对小车进行调整55 if(P6&0 x08)PWM0_set(215);PWM1_set(240);if(P6&0 x01)PWM0_set(255);PWM1_set(200);56 当当P6=0 x08,用二进制表示为用二进制表示为00001000时时,即前四路传感器的右边第四位压黑线即前四路传感器的右边第四位压黑线,此种此种情况下即表示小车右大偏情况下即表示小车右大偏,然后重新调整然后重新调整PWM值对小车进行调整值对小车进行调整57 if(P6&0
22、 x01)PWM0_set(255);PWM1_set(200);当当P6=0 x01,用二进制表示为用二进制表示为00000001时时,即前四即前四路传感器的右边第一位压黑线路传感器的右边第一位压黑线,此种情况下即表示此种情况下即表示小车左大偏小车左大偏,然后重新调整然后重新调整PWM值对小车进行调值对小车进行调整整58 if(fb=2)if(P6=0 x00)L_BACK(240);R_BACK(250);if(P6&0 x40)PWM0_set(230);PWM1_set(250);59 P6=0 x00,用二进制表示即为用二进制表示即为00000000,即即各路传感器返回值均为各路传感
23、器返回值均为0,表示表示8路传感器均路传感器均未压黑线未压黑线,小车后退未跑偏小车后退未跑偏 当当P6=0 x40,用二进制表示为用二进制表示为01000000时时,即后四路传感器的右边第三位压黑线即后四路传感器的右边第三位压黑线,此种此种情况下即表示小车右小偏情况下即表示小车右小偏,然后重新调整然后重新调整PWM值对小车进行调整值对小车进行调整60 if(P6&0 x20)PWM0_set(250);PWM1_set(250);if(P6&0 x40)&(P6&0 x80)PWM0_set(220);PWM1_set(250);61 当当P6=0 x20,用二进制表示为用二进制表示为0010
24、0000时时,即后四路传感器的右边第二位压黑线即后四路传感器的右边第二位压黑线,此种此种情况下即表示小车左小偏情况下即表示小车左小偏,然后重新调整然后重新调整PWM值对小车进行调整值对小车进行调整(P6&0 x40)&(P6&0 x80)即表示后四路寻即表示后四路寻迹的右边第三、四位寻迹压黑线,此种情迹的右边第三、四位寻迹压黑线,此种情况下即表示小车右中偏况下即表示小车右中偏,然后重新调整然后重新调整PWM值对小车进行调整值对小车进行调整62 if(P6&0 x20)&(P6&0 x10)PWM0_set(250);PWM1_set(240);if(P6&0 x80)PWM0_set(200)
25、;PWM1_set(250);63(P6&0 x20)&(P6&0 x10)即表示后四路寻即表示后四路寻迹的右边第一、二位寻迹压黑线,此种情迹的右边第一、二位寻迹压黑线,此种情况下即表示小车左中偏况下即表示小车左中偏,然后重新调整然后重新调整PWM值对小车进行调整值对小车进行调整 当当P6=0 x80,用二进制表示为用二进制表示为10000000时时,即后四路传感器的右边第四位压黑线即后四路传感器的右边第四位压黑线,此种此种情况下即表示小车右大偏情况下即表示小车右大偏,然后重新调整然后重新调整PWM值对小车进行调整值对小车进行调整64 if(P6&0 x10)PWM0_set(240);PWM
26、1_set(210);65 当当P6=0 x10,用二进制表示为用二进制表示为00010000时时,即前四路传感器的右边第一位压黑线即前四路传感器的右边第一位压黑线,此种此种情况下即表示小车左大偏情况下即表示小车左大偏,然后重新调整然后重新调整PWM值对小车进行调整值对小车进行调整66循迹反馈形成分析b=1b=2b=3b=467垂线检测偏移检测占空比L298驱动车轮轨迹TCRT循迹68(9)LCD控制 void sendc(uchar c)/给lcd送命令 P4=c;lcdrs=0;/RS=Llcdrw=0;/RW=LEA=0;/关中断 delay1ms(1);lcdcs=0;/E的高脉冲lc
27、dcs=1;/E的高脉冲69 delay1ms(1);lcdrw=1;P4=0 xff;/先置1,后读取delay1ms(1);EA=1;/开中断 70 void sendd(uchar c)/给lcd送数据 EA=0;P4=c;lcdrs=1;lcdrw=0;delay1ms(1);lcdcs=1;lcdcs=0;lcdcs=1;delay1ms(1);71 lcdrw=1;P4=0 xff;/先置1,后读取lcdrs=0;delay1ms(1);while(P4=0 x80);lcdcs=0;lcdcs=1;EA=1;/*if(c=c)delay1ms(3);*/72 void lcd_p
28、os(uchar pos)/显示地址定位函数 sendc(pos|0 x80);73 void lcd_ini(void)/lcd初始化函数 delay1ms(100);lcdcs=1;delay1ms(5);lcdrs=0;delay1ms(5);lcdrw=0;delay1ms(5);74 sendc(0 x38);/8位,2行,5*7字体delay1ms(30);sendc(0 x38);/8位,2行,5*7字体 delay1ms(30);sendc(0 x38);/8位,2行,5*7字体delay1ms(30);sendc(0 x08);/显示开,光标关;不闪delay1ms(30);
29、sendc(0 x01);/清屏delay1ms(30);75/sendc(0 x01);/清屏/delay1ms(30);sendc(0 x06);/delay1ms(30);sendc(0 x0C);/delay1ms(30);76(10)第一次显示 void lcddisplay1(void)/显示主函数 uchar i=0;uchar line1=once:550ml;uchar line2=all:550ml;sendc(0 x01);i=0;lcd_pos(0 x00);/容量显示 delay1ms(5);77 while(line1i!=0)sendd(line1i+);dela
30、y1ms(10);i=0;lcd_pos(0 x40);/容量显示 delay1ms(5);while(line2i!=0)sendd(line2i+);delay1ms(10);78(11)第二次显示 void lcddisplay2(void)/显示主函数 uchar i=0;uchar line1=twice:550ml;uchar line2=all:1100ml;sendc(0 x01);lcd_pos(0 x00);/容量显示 delay1ms(5);while(line1i!=0)sendd(line1i+);delay1ms(10);i=0;79 lcd_pos(0 x40);
31、/容量显示 delay1ms(5);while(line2i!=0)sendd(line2i+);delay1ms(10);80(12)显示时间 void lcddisplay3(void)/显示主函数 uchar i=0;uchar line1=time:00:35;uchar line2=rate:31.4%;sendc(0 x01);lcd_pos(0 x00);/时间显示 delay1ms(10);81 while(line1i!=0)sendd(line1i+);delay1ms(10);i=0;lcd_pos(0 x40);/时间显示 delay1ms(10);while(line2i!=0)sendd(line2i+);delay1ms(10);82(13)管理程序(主程序),调用子程序进行电机控制和寻迹 void main()config();P1_0=0;P1_1=0;P1_2=0;PCA_Init();PCA0_Init();lcd_ini();EA=1;83 while(1)if(fb=0)R_FORD(179);delay1ms(1);L_FORD(186);Founding_Line();