多波形发生器基本功能:
1、可产生多种波形,如正弦波、三角波、锯齿波、方波、梯形波等;
2、各种波形可通过按键选择;
3、可调节信号的频率参数。
1方案论证与对比
1.1 方案1利用STC89C52RC为硬件核心,STC89C52RC具有8KB ROM存储空间,512字节数据存储空间,带有MCS-51系列单片机完全兼容,STC89C52RC可以通过串口下载。本次实验设计采用单片机的PCF8591硬件接口实现D/A数模转换设计。PCF8591时一个单电源低功耗的8位CMOS数据采集器件,具有4路模拟输入,1路模拟输出和一个串行I2C总线接口用来与单片机通信,符合电路简单,方便查找错误的设计理念。
2硬件电路设计仔细分析课题后,并查找了相应资料,所学单片机中有关矩阵按键、A/D模数和D/A数模转换的有关知识,设计出整体硬件原理框图如图1所示, 其中晶振通过自身振荡为单片机系统提供基准时钟信号,复位电路用于单片机复位,矩阵按键控制波形、频率切换。
图1 整体原理框图
2.1 最小系统的设计单片机最小系统的三要素就是电源、晶振和复位电路。 本设计中选用的STC89C52RC需要5V的供电系统,将供电电路接在STC89C52RC的40和20引脚的位置上,40引脚接+5V,即VCC。20引脚接GND,即电源负极。 晶振为单片机系统提供基准时钟信号。STC89C52RC的18引脚和19引脚接一个11.0592MHz的晶振,外加两个20pF的电容,电容用于帮助晶振起振,并维持晶振信号的稳定。 单片机复位分为三种情况:上电复位、手动复位和程序自动复位。 上电复位即单片机上电后,单片机进行一个内部的初始化过程,保证单片机每次都从一个固定的相同的状态开始工作。手动复位即人主动去按下复位按键,让程序重新初始化重新运行。程序自动复位即单片机遇到某些情况自动复位到初始化的状态。 具体电路设计参见下图2 :
图2 单片机最小系统
2.2PCF8591电路设计
图3 PCF8591电路 其中引脚1、2、3、4是4路模拟输入,引脚5、6、7是I2C总线的硬件地址,8 脚是数 字地 GND,9 脚和 10 脚是I2C总线的 SDA 和SCL。12脚是时钟选择引脚,如果接高电平表 示用外部时钟输入,接低电平则用内部时钟,我们本次设计电路用的是内部时钟,因此12脚直接接 GND,同时 11脚悬空。13脚是模拟地 AGND。14脚是基准源,15脚是 DAC 的模拟输出,16脚是供电电源 VCC。 在软件编程过程中单片机对PCF8591进行初始化,一共发送三个字节即可。第一个字节,和 EEPROM 类似,是器件地址字节,其中7位代表地址,1位代表读写方向。地址高4位固定是0b1001,低三位是A2,A1,A0, 这三位我们电路上都接了GND,因此也就是0b000。 图 4 PCF8591 地址字节 发送到 PCF8591 的第二个字节将被存储在控制寄存器,用于控制 PCF8591 的功能。 图 5 PCF8591 控制字节 控制字节的第6位是DA使能位,这一位置1表示DA输出引脚使能,会产生模拟电压输出功能。 2.3矩阵按键电路的设计通过高四位全部输出低电平,低四位输出高电平。当接收到的数据,低四位不全为高电平时,说明有按键按下,然后通过接收的数据值,判断是哪一列有按键按下,然后再反过来,高四位输出高电平,低四位输出低电平,然后根据接收到的高四位的值判断是那一行有按键按下,从而能够确定是哪一个按键按下了。电路如图6示:

图6 矩阵键盘电路
3系统软件设计及流程图
3.1主程序工作流程 首先开启总中断,让中断程序能够正常运行,配置T0定时1ms,初始化波形和频率,进入循环不断扫描按键动态在中断中完成按键扫描并消抖,主程序调用按键动作函数。当检测到键4按下第一次,显示三角波;当检测键4按下第二次,显示锯齿波;当检测到键4按下第三次,显示方波;当检测到键4按下第四次,显示梯形波若无检测到键按下,则输出默认正弦波;当检测到按下键8,调整波形频率。主程序流程图如图7所示: 
图7 主程序流程图 3.2中断子程序设计
3.2.1 T0定时器中断子程序中,通过定时器T0执行矩阵按键扫描函数检测是否按下按键,定时器中断流程图如图8所示:

图8 T0中断子程序流程图
3.2.2 T1定时器通过定时器T1执行波形输出和频率转换,改变定时器T1的时钟周期来改变输出频率。定时器中断流程图如图9所示:
图9 T1中断子程序流程图
附录一:总电路设计图
单片机源程序如下:
- #include <reg52.h>
- unsigned char code SinWave[256] ={ //正弦波
- 127 , 133 , 139 , 146 , 152 , 158 , 164 , 170,
- 176, 181 , 187 , 192 , 198 , 203 , 208, 212 ,
- 217 , 221 , 225 , 229 , 233, 236, 239, 242 ,
- 244 , 247 , 249 , 250 , 252 , 253 , 253 , 254 ,
- 254 , 254 , 253 , 253, 252 , 250 , 249 , 247 ,
- 244, 242 , 239, 236 , 233 , 229 , 225 , 221 ,
- 217 , 212 , 208 , 203 , 198 , 192 , 187 , 181 ,
- 176 , 170 , 164 , 158 , 152 , 146 , 139 , 133 ,
-
- 127 , 121 , 115 , 108 , 102 , 96 , 90 , 84 ,
- 78 , 73 , 67 , 62 , 56 , 51 , 46 , 42 ,
- 37 , 33, 29 , 25 , 21 , 18 , 15 , 12 ,
- 10 , 7 , 5 , 4 , 2 , 1 , 1 , 0 ,
- 0 , 0 , 1 , 1 , 2 , 4 , 5 , 7 ,
- 10 , 12 , 15 , 18 , 21 , 25 , 29 , 33 ,
- 37 , 42 , 46 , 51 , 56 , 62 , 67 , 73 ,
- 78 , 84 , 90 , 96 , 102 , 108 , 115 , 121 ,
- } ;
- unsigned char code SawWave[256] = { //锯齿波
- 0, 2, 4, 6, 8, 10, 12, 14,
- 16, 18, 20, 22, 24, 26, 28, 30,
- 32, 34, 36, 38, 40, 42, 44, 46,
- 48, 50, 52, 54, 56, 58, 60, 62,
-
- 64, 66, 68, 70, 72, 74, 76, 78,
- 80, 82, 84, 86, 88, 90, 92, 94,
- 96, 98, 100,102,104,106,108,110,
- 112,114,116,118,120,122,124,126,
- 128 ,130,132,134,136,138,140,142,
- 144 ,146,148,150,152,154,156,158,
- 160 ,162,164,166,168,170,172,174,
- 176 ,178,180,182,184,186,188,190,
- 192,194 ,196,198,200,202,204,206,
- 208,210 ,212,214,216,218,220,222,
- 224,226 ,228,230,232,234,236,238,
- 240,242 ,244,246,248,250,252,254,
- };
- unsigned char code TriWave[256]= { //三角波
- 0 , 4 , 8, 12 , 16 , 20 , 24 , 28 ,
- 32 , 36 , 40, 44 , 48 , 52 , 56 , 60 ,
- 64 , 68 , 72 , 76 , 80 , 84 , 88 , 92 ,
- 96 ,100 , 104 , 108 , 112 , 116 , 120 , 124 ,
- 128 ,132 , 136, 140 , 144 , 148 , 152 , 156 ,
- 160 , 164 , 168, 172 , 176 , 180, 184 , 188 ,
- 192 , 196 , 200, 204, 208 , 212 , 216 , 220 ,
- 224 , 228 , 232, 236 , 240 , 244 , 248 , 252 ,
- 255 , 251 , 247 , 243, 239 , 235 , 231 , 227 ,
- 223 , 219 , 215, 211 , 207 , 203 , 199 , 195 ,
- 191 , 187 , 183, 179, 175 , 171 , 167 , 163 ,
- 159 , 155 , 151, 147, 143 , 139 , 135 , 131 ,
- 127 , 123 , 119, 115, 111 ,107 , 103 , 99 ,
- 95 , 91 , 87 , 83 , 79 , 75 , 71 , 67 ,
- 63 , 59 , 55 , 51 , 47 ,43 , 39 , 35 ,
- 31 , 27, 23 , 19 , 15 , 11 , 7 , 3 ,
- };
- unsigned char code SquWave[256] = { //方波
- 255,255,255,255,255,255,255,255,
- 255,255,255,255,255,255,255,255,
- 255,255,255,255,255,255,255,255,
- 255,255,255,255,255,255,255,255,
- 255,255,255,255,255,255,255,255,
- 255,255,255,255,255,255,255,255,
- 255,255,255,255,255,255,255,255,
- 255,255,255,255,255,255,255,255,
- };
- unsigned char code TraWave[256] = {//梯形波
- 0 , 6 , 12 , 18 , 24 , 30 , 36 , 42 ,
- 48 , 54 , 60 , 66 , 72 , 78 , 84 , 90 ,
- 96 , 102 , 108, 114 , 120, 126 , 132 , 138 ,
- 144 , 150 , 156, 162 , 168 , 174 , 180 , 186 ,
- 192 , 198 , 204 , 210 , 216 , 222 , 228 , 234 ,
- 240 , 246 , 252 , 255, 255, 255, 255, 255,
- 255, 255, 255, 255, 255, 255, 255, 255,
- 255, 255, 255, 255, 255, 255, 255, 255,
- 255, 255, 255, 255, 255, 255 , 249 , 243 ,
- 237 , 231 , 225 , 219 , 213, 207 , 201 , 195 ,
- 189 , 183 , 177 , 171 , 165 , 159 , 153 , 147 ,
- 141, 135 , 129 , 123 , 117 , 111 , 105 , 99 ,
- 93 , 87 , 81 , 75 , 69 , 63 , 57 , 51 ,
- 45 , 39 ,33 , 27 , 21, 15 , 9 , 3 ,
- };
- unsigned char code *pWave; //波表指针
- unsigned char T0RH = 0; //T0重载值的高字节
- unsigned char T0RL = 0; //T0重载值的低字节
- unsigned char T1RH = 1; //T1重载值的高字节
- unsigned char T1RL = 1; //T1重载值的低字节
- unsigned char t;//函数周期
- unsigned char f;//频率
- void ConfigTimer0(unsigned int ms);
- void SetWaveFreq(unsigned char freq);
- extern void KeyScan();
- extern void KeyDriver();
- extern void I2CStart();
- extern void I2CStop();
- extern bit I2CWrite(unsigned char dat);
- void main()
- {
- EA = 1; //开总中断
- ConfigTimer0(100); //配置T0定时1ms
- pWave = SinWave; //默认正弦波
- SetWaveFreq(5); //默认频率100Hz
- f = 128;
-
- while (1)
- {
- KeyDriver(); //调用按键驱动
- }
- }
- /*改变波形*/
- void KeyAction(unsigned char keycode)
- {
- static unsigned char i = 0;
- if(keycode == 0x26)
- {
- if(i==0)
- {
- i = 1;
- pWave = TriWave;
- }
- else if(i==1)
- {
- i = 2;
- pWave = SawWave;
- }
- else if(i==2)
- {
- i = 3;
- pWave = SquWave;
- }
- else if(i==3)
- {
- i = 4;
- pWave = TraWave;
- }
- else
- {
- i = 0;
- pWave = SinWave;
- }
- }
- }
- /*改变频率*/
- void KeyAction_f(unsigned char keycode)
- {
- static unsigned char i = 0;
- if(keycode == 0x25)
- {
- if(i==0)
- {
- i = 1;
- f = 128;
- }
- else
- {
- i = 0;
- f = 64;
- }
- }
- }
- /* 设置DAC输出值,val-设定值 */
- void SetDACOut(unsigned char val)
- {
- I2CStart();
- if (!I2CWrite(0x48<<1)) //寻址PCF8591,如未应答,则停止操作并返回
- {
- I2CStop();
- return;
- }
- I2CWrite(0x40); //写入控制字节
- I2CWrite(val); //写入DA值
- I2CStop();
- }
- /*改变频率*/
- void SetWaveFreq(unsigned char freq)
- {
- unsigned long tmp;
- tmp = (11059200/12)/(freq * 128);
- tmp = 65536 - tmp;
- tmp = tmp + 33;
- T1RH = (unsigned char)(tmp >> 8);
- T1RL = (unsigned char)tmp;
- TMOD &= 0x0F;
- TMOD |= 0X10;
- TH1 = T1RH;
- TL1 = T1RL;
- ET1 = 1;
- PT1 = 1;
- TR1 = 1;
- }
- /* 配置并启动T0,ms-T0定时时间 */
- void ConfigTimer0(unsigned int ms)
- {
- unsigned long tmp; //临时变量
-
- tmp = 11059200 / 12; //定时器计数频率
- tmp = (tmp * ms) / 1000; //计算所需的计数值
- tmp = 65536 - tmp; //计算定时器重载值
- tmp = tmp + 28; //补偿中断响应延时造成的误差
- T0RH = (unsigned char)(tmp>>8); //定时器重载值拆分为高低字节
- T0RL = (unsigned char)tmp;
- TMOD &= 0xF0; //清零T0的控制位
- TMOD |= 0x01; //配置T0为模式1
- TH0 = T0RH; //加载T0重载值
- TL0 = T0RL;
- ET0 = 1; //使能T0中断
- TR0 = 1; //启动T0
- }
- /* T0中断服务函数,执行按键扫描 */
- void InterruptTimer0() interrupt 1
- {
- TH0 = T0RH; //重新加载重载值
- TL0 = T0RL;
- KeyScan(); //按键扫描
-
- }
- /* T1中断服务函数,执行波形输出 */
- void InterruptTimer1() interrupt 3
- {
- static unsigned char i = 0;
-
- TH1 = T1RH; //重新加载重载值
- TL1 = T1RL;
- //循环输出波表中的数据
- SetDACOut(pWave[i]);
- if(f == 128)
- {
- i++;
- if (i >= 128)
- {
- i = 0;
- }
- }
- if(f == 64)
- {
- i = i+2;
- if (i >= 128)
- {
- i = 0;
- }
- }
- }
复制代码 |