2 Keil C51程序
单片机程序采用Keil C51编程语言编写,经编译后生成HEX文件即可固化在AT89C2051中。一个C,51工程(project)的源程序由C文件和H头文件等组成。本文下面给出的C文件wave.c中有主程序"void main(void)"、DA转换输出函数"void da.out(void)"和定时器中断函数"void timer0(void)interrupt 1 using 2"组成。两次DA转换之间采用定时器0进行定时。在产生基频正弦信号或倍频正弦信号时不改变定时器的定时时间,而是通过传送给DA不同的数字量来实现,即头文件中的产生基频正弦信号的wavel数组和产生倍频信号的waveh数组的长度一样,均为128,但wavel是一个周期内正弦波的数字量,waveh是两个周期内的数字量,前64个数值与后64个数值相同。这样可以避免执行重置定时常数的指令而引起的时间误差,从而得到精确的双倍频关系。另外,wavel数组中的峰-峰值(最大值-最小值)约为waveh数组中峰-峰值的一半,这样使得经RC滤波后两种频率的正弦波幅度近似相等,以满足使用要求。如程序中的定时常数(TH0=0xff,TL0=0x00),在晶振为20MHz时,测得基频为50.6Hz,倍频为101.2Hz。以下是C51源程序wave.c和H头文件wave.h,在Keil C51 V6.12下编译通过生成HEX文件。
C51源程序wave.c
- #include<reg51.h>
- #include<intrins.h>
- #include "wave.h"
- void da_out(void); //声明函数
- sbit DIN=0x97; //P1.7位定义
- sbit SCLK=0x96; //P1.6位定义
- sbit DACS=0x95; //P1.5位定义
- sbit SWF1 =0x94; //P1.4位定义
- sbit SWF0 =0x93; //P1.3位定义
- sbit WDI =0x92; //P1.2位定义
- sbit FLAG = 0x90;
- IUI word; //IUI即idata unsigned int,在wave.h中预定义
- void main(void)
- {
- IUI i;
- TMOD =0x01; //定时器0方式1;
- TH0=0xff;TL0=0x00; //置定时器0常数;
- TR0=1; //启动定时器0
- ET0=1;EA=1; //开定时器中断及总中断
- SWF0=1;SWF1=1; //设P1.3,P1.4为输入
- WDI=1; //看门狗输入置高电平
- while(1)
- {
- for(i=0;i<128;i++)
- {
- FLAG=1; //置标志,FLAG在定时器0中断程序中被清除
- WDI=0;_nop_();WDI= 1;//看门狗复位
- if(SWF1) word=512; //SWF1=1时,DA输出同一量,无正弦信号输出
- else
- {
- if(SWF0) word=waveh[i];//取倍频数字量
- else word=wavel[i]; //取基频数字量
- }
- word=word<<6; //10位数字量移至高位
- while(FLAG); //等待,直至定时器中断程序中清FLA G
- da_out(); //调用DA输出子程序
- }
- }
- }
- void timer0(void) interrupt 1 using 2
- {
- TH0=0xff;TL0=0x00;//重置定时器常数
- FLAG=0;//清主程序中的等待标志
- }
- void da_out(void){
- IUI i;
- SCLK =0;_nop_();DACS=0; //准备传送数据
- for(i=0;i<10;i++)
- {
- DIN= (bit)(word&Ox80); //取最高位送数据线
- word = word << 1; //左移,准备下一位传送
- SCLK =1;_nop_();SCLK =0; //一个CLK信号
- }
- DACS= 1;_nop_();SCLK=1; //传送结束
- }
H头文件(wave.h):
- typedef idata unsigned int IUI;
- int code wavel[]=
- {
- 512,524,537,550,563,698,707,715,723,731,775,775,774,772,770,698,689,679,669,658,
- 512,499,486,473,460,325,316,308,300,292,248,248,249,251,253,325,334,344,354,365,
- };
- int code waveh[]=
- {
- 512,562,611,660,707,753,796,836,874,907,937,963,985,1001,1014,1021,
- 1023,1021,1014,1001,985,963,937,907,874,836,796,753,707,660,611,562,
- 512,46l,412,363,316,270,227,187,149,116,86,60,38,22,9,2,
- 0,2,9,22,38,60,86,116,149,187,227,270,316,363,412,461,
- 512,562,611,660,707,753,796,836,874,907,937,963,985,1001,1014,1021,
- 1023,1021,1014,1001,985,963,937,907,874,836,796,753,707,660,611,562,
- 512,461,412,363,316,270,227,187,149,116,86,60,38,22,9,2,
- 0,2,9,22,38,60,86,116,149,187,227,270,316,363,412,461
- };
3 小结
笔者有多年的单片机汇编语言编程经历,改用Keil C51后感觉很好,编程效率大为提高。本文是Keil C51在正弦波产生中的应用,由C源程序可见,程序较汇编语言程序可读性大为提高,非常简炼。本文介绍的倍频正弦波信号发生电路已用于某型电导率表中,效果很好。