多波形發(fā)生器基本功能:
1、可產(chǎn)生多種波形,如正弦波、三角波、鋸齒波、方波、梯形波等;
2、各種波形可通過(guò)按鍵選擇;
3、可調(diào)節(jié)信號(hào)的頻率參數(shù)。
1方案論證與對(duì)比
1.1 方案1利用STC89C52RC為硬件核心,STC89C52RC具有8KB ROM存儲(chǔ)空間,512字節(jié)數(shù)據(jù)存儲(chǔ)空間,帶有MCS-51系列單片機(jī)完全兼容,STC89C52RC可以通過(guò)串口下載。本次實(shí)驗(yàn)設(shè)計(jì)采用單片機(jī)的PCF8591硬件接口實(shí)現(xiàn)D/A數(shù)模轉(zhuǎn)換設(shè)計(jì)。PCF8591時(shí)一個(gè)單電源低功耗的8位CMOS數(shù)據(jù)采集器件,具有4路模擬輸入,1路模擬輸出和一個(gè)串行I2C總線接口用來(lái)與單片機(jī)通信,符合電路簡(jiǎn)單,方便查找錯(cuò)誤的設(shè)計(jì)理念。
2硬件電路設(shè)計(jì)仔細(xì)分析課題后,并查找了相應(yīng)資料,所學(xué)單片機(jī)中有關(guān)矩陣按鍵、A/D模數(shù)和D/A數(shù)模轉(zhuǎn)換的有關(guān)知識(shí),設(shè)計(jì)出整體硬件原理框圖如圖1所示, 其中晶振通過(guò)自身振蕩為單片機(jī)系統(tǒng)提供基準(zhǔn)時(shí)鐘信號(hào),復(fù)位電路用于單片機(jī)復(fù)位,矩陣按鍵控制波形、頻率切換。
圖1 整體原理框圖
2.1 最小系統(tǒng)的設(shè)計(jì)單片機(jī)最小系統(tǒng)的三要素就是電源、晶振和復(fù)位電路。 本設(shè)計(jì)中選用的STC89C52RC需要5V的供電系統(tǒng),將供電電路接在STC89C52RC的40和20引腳的位置上,40引腳接+5V,即VCC。20引腳接GND,即電源負(fù)極。 晶振為單片機(jī)系統(tǒng)提供基準(zhǔn)時(shí)鐘信號(hào)。STC89C52RC的18引腳和19引腳接一個(gè)11.0592MHz的晶振,外加兩個(gè)20pF的電容,電容用于幫助晶振起振,并維持晶振信號(hào)的穩(wěn)定。 單片機(jī)復(fù)位分為三種情況:上電復(fù)位、手動(dòng)復(fù)位和程序自動(dòng)復(fù)位。 上電復(fù)位即單片機(jī)上電后,單片機(jī)進(jìn)行一個(gè)內(nèi)部的初始化過(guò)程,保證單片機(jī)每次都從一個(gè)固定的相同的狀態(tài)開(kāi)始工作。手動(dòng)復(fù)位即人主動(dòng)去按下復(fù)位按鍵,讓程序重新初始化重新運(yùn)行。程序自動(dòng)復(fù)位即單片機(jī)遇到某些情況自動(dòng)復(fù)位到初始化的狀態(tài)。 具體電路設(shè)計(jì)參見(jiàn)下圖2 :
圖2 單片機(jī)最小系統(tǒng)
2.2PCF8591電路設(shè)計(jì)
圖3 PCF8591電路 其中引腳1、2、3、4是4路模擬輸入,引腳5、6、7是I2C總線的硬件地址,8 腳是數(shù) 字地 GND,9 腳和 10 腳是I2C總線的 SDA 和SCL。12腳是時(shí)鐘選擇引腳,如果接高電平表 示用外部時(shí)鐘輸入,接低電平則用內(nèi)部時(shí)鐘,我們本次設(shè)計(jì)電路用的是內(nèi)部時(shí)鐘,因此12腳直接接 GND,同時(shí) 11腳懸空。13腳是模擬地 AGND。14腳是基準(zhǔn)源,15腳是 DAC 的模擬輸出,16腳是供電電源 VCC。 在軟件編程過(guò)程中單片機(jī)對(duì)PCF8591進(jìn)行初始化,一共發(fā)送三個(gè)字節(jié)即可。第一個(gè)字節(jié),和 EEPROM 類似,是器件地址字節(jié),其中7位代表地址,1位代表讀寫(xiě)方向。地址高4位固定是0b1001,低三位是A2,A1,A0, 這三位我們電路上都接了GND,因此也就是0b000。 圖 4 PCF8591 地址字節(jié) 發(fā)送到 PCF8591 的第二個(gè)字節(jié)將被存儲(chǔ)在控制寄存器,用于控制 PCF8591 的功能。 圖 5 PCF8591 控制字節(jié) 控制字節(jié)的第6位是DA使能位,這一位置1表示DA輸出引腳使能,會(huì)產(chǎn)生模擬電壓輸出功能。 2.3矩陣按鍵電路的設(shè)計(jì)通過(guò)高四位全部輸出低電平,低四位輸出高電平。當(dāng)接收到的數(shù)據(jù),低四位不全為高電平時(shí),說(shuō)明有按鍵按下,然后通過(guò)接收的數(shù)據(jù)值,判斷是哪一列有按鍵按下,然后再反過(guò)來(lái),高四位輸出高電平,低四位輸出低電平,然后根據(jù)接收到的高四位的值判斷是那一行有按鍵按下,從而能夠確定是哪一個(gè)按鍵按下了。電路如圖6示:

圖6 矩陣鍵盤(pán)電路
3系統(tǒng)軟件設(shè)計(jì)及流程圖
3.1主程序工作流程 首先開(kāi)啟總中斷,讓中斷程序能夠正常運(yùn)行,配置T0定時(shí)1ms,初始化波形和頻率,進(jìn)入循環(huán)不斷掃描按鍵動(dòng)態(tài)在中斷中完成按鍵掃描并消抖,主程序調(diào)用按鍵動(dòng)作函數(shù)。當(dāng)檢測(cè)到鍵4按下第一次,顯示三角波;當(dāng)檢測(cè)鍵4按下第二次,顯示鋸齒波;當(dāng)檢測(cè)到鍵4按下第三次,顯示方波;當(dāng)檢測(cè)到鍵4按下第四次,顯示梯形波若無(wú)檢測(cè)到鍵按下,則輸出默認(rèn)正弦波;當(dāng)檢測(cè)到按下鍵8,調(diào)整波形頻率。主程序流程圖如圖7所示: 
圖7 主程序流程圖 3.2中斷子程序設(shè)計(jì)
3.2.1 T0定時(shí)器中斷子程序中,通過(guò)定時(shí)器T0執(zhí)行矩陣按鍵掃描函數(shù)檢測(cè)是否按下按鍵,定時(shí)器中斷流程圖如圖8所示:

圖8 T0中斷子程序流程圖
3.2.2 T1定時(shí)器通過(guò)定時(shí)器T1執(zhí)行波形輸出和頻率轉(zhuǎn)換,改變定時(shí)器T1的時(shí)鐘周期來(lái)改變輸出頻率。定時(shí)器中斷流程圖如圖9所示:
圖9 T1中斷子程序流程圖
附錄一:總電路設(shè)計(jì)圖
單片機(jī)源程序如下:
- #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重載值的高字節(jié)
- unsigned char T0RL = 0; //T0重載值的低字節(jié)
- unsigned char T1RH = 1; //T1重載值的高字節(jié)
- unsigned char T1RL = 1; //T1重載值的低字節(jié)
- unsigned char t;//函數(shù)周期
- 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; //開(kāi)總中斷
- ConfigTimer0(100); //配置T0定時(shí)1ms
- pWave = SinWave; //默認(rèn)正弦波
- SetWaveFreq(5); //默認(rèn)頻率100Hz
- f = 128;
-
- while (1)
- {
- KeyDriver(); //調(diào)用按鍵驅(qū)動(dòng)
- }
- }
- /*改變波形*/
- 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;
- }
- }
- }
- /* 設(shè)置DAC輸出值,val-設(shè)定值 */
- void SetDACOut(unsigned char val)
- {
- I2CStart();
- if (!I2CWrite(0x48<<1)) //尋址PCF8591,如未應(yīng)答,則停止操作并返回
- {
- I2CStop();
- return;
- }
- I2CWrite(0x40); //寫(xiě)入控制字節(jié)
- I2CWrite(val); //寫(xiě)入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;
- }
- /* 配置并啟動(dòng)T0,ms-T0定時(shí)時(shí)間 */
- void ConfigTimer0(unsigned int ms)
- {
- unsigned long tmp; //臨時(shí)變量
-
- tmp = 11059200 / 12; //定時(shí)器計(jì)數(shù)頻率
- tmp = (tmp * ms) / 1000; //計(jì)算所需的計(jì)數(shù)值
- tmp = 65536 - tmp; //計(jì)算定時(shí)器重載值
- tmp = tmp + 28; //補(bǔ)償中斷響應(yīng)延時(shí)造成的誤差
- T0RH = (unsigned char)(tmp>>8); //定時(shí)器重載值拆分為高低字節(jié)
- T0RL = (unsigned char)tmp;
- TMOD &= 0xF0; //清零T0的控制位
- TMOD |= 0x01; //配置T0為模式1
- TH0 = T0RH; //加載T0重載值
- TL0 = T0RL;
- ET0 = 1; //使能T0中斷
- TR0 = 1; //啟動(dòng)T0
- }
- /* T0中斷服務(wù)函數(shù),執(zhí)行按鍵掃描 */
- void InterruptTimer0() interrupt 1
- {
- TH0 = T0RH; //重新加載重載值
- TL0 = T0RL;
- KeyScan(); //按鍵掃描
-
- }
- /* T1中斷服務(wù)函數(shù),執(zhí)行波形輸出 */
- void InterruptTimer1() interrupt 3
- {
- static unsigned char i = 0;
-
- TH1 = T1RH; //重新加載重載值
- TL1 = T1RL;
- //循環(huán)輸出波表中的數(shù)據(jù)
- SetDACOut(pWave[i]);
- if(f == 128)
- {
- i++;
- if (i >= 128)
- {
- i = 0;
- }
- }
- if(f == 64)
- {
- i = i+2;
- if (i >= 128)
- {
- i = 0;
- }
- }
- }
復(fù)制代碼 |