WSGR=Ox0007H; /*产生等待状态,协调DSP与慢速外设通信*/

OCRA=Ox180BH;/*设定端口A.B的ADCINB,ADCINO,ADCINI,T1PWM/T1CMP, T2PWMlT2CMP引脚*/ OCRB=Ox0000H; /*设定除XF和/BIO外,端口C其它为普通I/O*I PADATDIR=Ox0000H; PBDATDIR=OxFF00H; PCDATDIR=Ox0000H; /*设定IOPCO, IOPC4,IOPCS.IOPC6,IOPC7引脚为输入引脚*/ }

4.3按键处理和复位看门狗子程序

上述功能配置的OCRB=Ox0000H和PCDATDIR=Ox0000H两条语句已完成键盘按键资源设置,以下是开关时的消抖处理,具体做法是加上延时消除机械跳动,及等待按键松开再进行其它操作,如下面程序所示:

if(PCDATDIR&OxEF00H) /*有2号键按下*/ {count=100; while(count>0) count--; /*延时消除机械跳动’/ noise(void); /*转到2号键对应的功能模块*/ while(! (PCDATDIR&OxFF00H)) /*检查是否已经松开按键*/ {count=100;while(count>0) count--;} }

对其它按键的处理与上面完全类似。

对看门狗控制寄存器(WDCR)设定了计时时间为1秒以及响应了计时操作,必须在每一个程序分支开头处复位看门狗:

void KICK_DOG(void)

{WDKEY=Ox55H; WDKEY=OxAAH;}

仅有SSH之后跟随AAH才能清除看门狗计时器WDCNTR的内容,写入其他任何值都将导致系统复位。在每段执行时间不超过1秒的程序中,以及程序里的等待状态中均插入上述KICK DOG子程序,防止WD溢出复位系统。

4.4温度信号PWM方波输出子程序

以20ms内占空比可调的温控PWM方波输出由F240的计时比较(TimeCMP )/脉宽调变(PWM)器来实现。程序实现思想是:首先根据第对计时比较(Time CMP )/脉宽调变(PWM)器进行设置;程序每隔5秒(温度信号的采样间隔)获取一次温度AlD数值就用于智能PID算法,得出实际的PID参数代入增量型PID算式,求得本次以具体温度表示的控制增量△u (t):为了根据不同的△u (t)进行PWM定脉调宽,把控温脉宽分成5档:0%即关断(pz)、较小(ps )、中等(pm)、较大(pb), 100%即全通(pw);中等脉宽用于维持恒温,较小和较大脉宽分别取0%和100%脉宽与中等脉宽的和平均;通过实际经验把△u (t)的取值范围划分成5个区间(t1, t2, t3, t4, t5)}分别对应5档脉宽;当△u (t)落入某个区间就取对应的脉宽值写入比较寄存器TxCMPR (x=1, 2);计时器Tx通过在上数计时过程中与预设在TxCMPR (x=1, 2)及TxPR (x=1, 2)的内容比较,一旦匹配就改变TxCMP/TxPWM(x=1, 2)引脚输出的PWM方波为低电平(当计时值二TxCMPR (x=1, 2))或高电平(当计时值=0或TxPR (x=1, 2) ),从而完成温度控制的智能PWM波形输出。以下给出部分程序代码和注解以及仿真实验PWM输出波形。 void PWM_OUT()

{initDSP( ); /*DSP初始化,设置PLL模块*/

- 8 -

OCRB=Ox0000H; /*设定端口C为一般IIO * I disable(); /*禁止所有中断*/ KICK_ DOG(); IFR=OxFFFFH; /*清除所有中断标志*/ IMR=Ox20H; /*使能INT6中断*/ initEV( ); /*设置事件管理EV模块*/ enable( ); /*使能所有中断*/ while(1) { }; /*等待产生AID转换中断*/ }

void initEV( ) /*事件管理EV模块设置子程序*/ { TICNT=0; /*初始化计数寄存器*/ T1CMPR=0; /*初始化定时L匕较寄存器*/ T1CON=Ox130AH; /*内部基本计时=CPUCLK/8=0.4us,连续上数*/ T1PR=50000; /*T1周期=50000*0.4us=20ms*/ GPTCON=Ox0055H;} /*响应TxCMP} PWM输出低有效*/ PWM_ ISR()

{tout=PID(temp); /*作智能PID运算*/ case(tout) /*计算输出PWM波的占空比,并加载 {t1;T1CMPR=pw;break; /*到计时比较寄存器里*/ t2:T1CMPR=pb;break; t3:T1CMPR=pm;break; t4:T1CMPR=ps;break; t5:T1CMPR=pz;break;}} 在实际硬件调试里,从示波器己经可以观察到PWM波形,但由于使用的DSP硬件仿真器TDS510不支持波形上传,所以把上述F240的PWM波形产生器工作过程在硬件仿真软件MAX+plus II进行仿真实验,图4-2就是对应的FLC在线调整PID的恒温控制PWM输出仿真实验结果,图中的width是计算得到的每个控制周期(5s)的脉宽值,addrctr 1指示的是20ms的定脉PWM周期数,而dir对应的就是实际的占空比可调的PWM输出波形。

4.5液晶显示子程序

液晶显示子程序包括对T6963C控制芯片的初始化和应用程序。通过T6963C的指令系统可完成数据显示功能。DSP与T6963C通讯时要先检查T6963 C的状态,不忙才可以进行操作,忙则等待。T6963 C的其它操作特点和指令系统可查阅相关数据手册。液晶OCM12864显示点阵是128X64,因为本系统只需要显示8*8的字符和个别汉字,所以显示尺寸是8行16列,使用OCM12864的片内字符产生器CGROM和CGRAM便可,无需外扩。液晶数据口为dataportxbyte [Ox8000h],命令口是comport xbyte[Ox8001h],以下给出液晶显示部分关键程序。 液晶状态查询函数: void rwcheck( ) /*数据和指令读写允许查询*/

{unsigned char sta; do{sta=comport&Ox03h;}while(sta!=0x03 h);} void autorcheck() /*数据自动读允许查询*/

{unsigned char sta; do{sta=comport&Ox04h;}while(sta!=Ox04h);} void autowcheck( ) /*数据自动写允许查询*/

{unsigned char sta; do{sta=comport&Ox08h;}while(sta!=Ox08h);} DSP与T6963C通讯的函数:

- 9 -

outdata(dat) /*DSP向数据口发数据*/ {rwcheck();dataport=dat;}

outcoml(command) /*DSP向命令口写带一个参数的命令*/ {rwcheck( );comport=command;}

outcom2(dat,command) /*DSP向命令口写带两个参数的命令*/ {outdata(dat); outcoml(command);}

outcom3(datal,data2,command) /*DSP向命令口写带三个参数的命令*/ {outdata(datal);outdata(data2);outcom 1(command);} unsigned char indata( ) /*DSP接收数据*/ {rwcheck();return(dataport);}

初始化中T6963C各命令的宏定义是:设置文本区首地址一txhome Ox40h; 设置文本区宽度一txwide 0x41 h;设置图形区首地址一grhome Ox42h;设置图形 区宽度一grwide Ox43h;设置字符产生器偏移量一offset Ox22h;设置地址指针 - adpset Ox24h;开自动读写一awron OxbOh;关自动读写一awroff Oxb2ho T6963C 初始化函数具体如下: void InitLCD()

{ outcom 1(Oxa7h); /*选择8*8的光标形状*/ delay(Oxff);

outcoml (Ox80h); /*选用内部CG ROM*/ delay(Oxff);

outcoml(Ox9ch); /*选择文本和图形的显示模式*/ delay(Oxff);

outcom3 (Ox0000,Ox0000,txhome); /*文本显示首地址=x:Ox0000,y:Ox0000*/ delay(Oxff);

outcom3(Ox0008,Ox00,txwide /*文本宽度=8列*/ delay(Oxff);

outcom3(Ox0000,Ox0008,grhome); /*图形显示首地址=x:Ox0000,y:Ox0008*/ delay(Oxff);

outcom3(Ox0008,Ox00,grwide) /*图形宽度=8列*/ delay(Oxff);

outcom3(Ox0001,Ox0000,offset /*CG RAM开始地址为0800-Offf*I clearscreen( ); /*清屏*/ delay((Oxff); }

void clearscreen( ) /*清屏函数*/ { unsigned int i;

outcom3 (Ox00,Ox00,adpset); /*设置地址指针=Ox0000h*/ delay(Oxff);

outcom 1(awron); /*设置数据自动写*/ delay(Oxff);

for(i=Ox0000h;i

outcom 1(awroff); /*关自动读写*/ delay(Oxff); }

- 10 -

本系统需显示字符使用OCM12864片内CGROM的128个标准ASC II码字符点阵己足够。字符采用文本方式显示,于是8*8字符的显示函数具体如下(其中ch是欲显示字符的ASC II码,X和Y分别是字符在液晶屏上的行列位置):

void showchar(unsigned char x,unsigned char y,unsigned char ch) {unsigned char i; unsigned char dat; unsigned int startaddr;

startaddr=Ox0000h+x* 16+y; /*计算欲显示字符在显存中的首地址*/ dat=ch-Ox20h; /*OCM12864字符代码=字符ASC II码一20h*/ outcom3((unsigned char)(startaddr&0x00ff) /*设置地址指针=startaddr* / (unsigned char)((startaddr;8)&0x00均,adpset); outcom2(dat,OxcOh); /*取出字符代码送指定的行列位置显示*/ }

本系统需显示“温”、“度”、“噪”、“声”等几个16*16的汉字,采用图形方式显示。首先把需显示的汉字字模代码(共32个字节)写入OCM12864的32K CGRAM中,使用时再取出。16*16汉字的显示函数如下(其中hzcode是欲显示汉字在自定义的汉字字模表中的位置,hztable是汉字字模表的首地址): void showhz(unsigned int x,unsigned int y,unsigned int hzcode) { unsigned char i;

unsigned int startaddr; unsigned char hz_l,hz_r; unsigned char *hz_ptr;

startaddr=Ox0800h+x* 16+y; /*计算欲显示汉字在显存中的首地址*/ hz_ptr=hztable+hzcode*32; /*计算欲显示汉字在字模表中的首地址*/ for(i=O;i<16;i++) /*汉字共需每行2个、共16行的显示单元*/ { outcom3((unsigned char)(startaddr&0x00ff) /*设置地址指针=startaddr*/ (unsigned char)((startaddr;8)&0x00 adpset); hz_1=* hz_ptr; /*取汉字左边8个象素点在字模表的首地址*/ outcom2(hz_l,OxcO); /*汉字左边8个象素点送显示*/ hz_ptr++;

hz_r=*hz-ptr; /*取汉字右边8个象素点在字模表的首地址*/ outcom2(hz_r,OxcO); /*汉字右边8个象素点送显示*/ startaddr=startaddr+l6; /*计算汉字下一行显示单元的地址*/

} }

4.6 SCI通信子程序

SCI通信子程序完成测试数据经过RS-232串行接口的输出。' 3.7节具体介绍过TMS320F240的串行通信接口SCI相关寄存器的设置,为了验证通信数据的传送,以下以SCI自我传输即将SCITXD和SCIRXD引脚相接为例,发射和接收分别采用查询和中断方式,给出部分关键程序代码和注解。 #define RXINT Ox0006H /*SCI接收中断向量*/ int i;

static const char table[n] /*存放n个通信数据的数组*/ void comm( ) /*SCI自我传输程序*/ { initDSP();

- 11 -