多波形發生器基本功能:
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;
- }
- }
- }
復制代碼 |