文章目錄
- 前言
- 單片機信號發生器程式
- 最后
前言
不少同學選擇單片機專案作為自己的畢業設計,比較適合自動化、通信、電器、還有物聯網的同學;由于較多同學向學長詢問和咨詢單片機專案問題,學長單獨開一個博客向大家詳細的全面的介紹單片機畢設專案,從單片機的基礎知識,到完整的單片機系統設計~
單片機信號發生器程式
有了 D/A 這個武器,我們就不僅僅可以輸出方波信號了,可以輸出任意波形了,比如正弦波、三角波、鋸齒波等等,以正弦波為例,首先我們要建立一個正弦波的波表,這些不需要大家去逐一計算,可以通過搜索找到正弦波資料表,然后可以根據時間引數自己選取其中一定量資料作為我們程式的正弦波表,我們的程式代碼選取了32個點,
#include <reg52.h>
unsigned char code SinWave[] = { //正弦波波表
127, 152, 176, 198, 217, 233, 245, 252,
255, 252, 245, 233, 217, 198, 176, 152,
127, 102, 78, 56, 37, 21, 9, 2,
0, 2, 9, 21, 37, 56, 78, 102
};
unsigned char code TriWave[] = { //三角波波表
0, 16, 32, 48, 64, 80, 96, 112,
128, 144, 160, 176, 192, 208, 224, 240,
255, 240, 224, 208, 192, 176, 160, 144,
128, 112, 96, 80, 64, 48, 32, 16
};
unsigned char code SawWave[] = { //鋸齒波表
0, 8, 16, 24, 32, 40, 48, 56,
64, 72, 80, 88, 96, 104, 112, 120,
128, 136, 144, 152, 160, 168, 176, 184,
192, 200, 208, 216, 224, 232, 240, 248
};
unsigned char code *pWave; //波表指標
unsigned char T0RH = 0; //T0 多載值的高位元組
unsigned char T0RL = 0; //T0 多載值的低位元組
unsigned char T1RH = 1; //T1 多載值的高位元組
unsigned char T1RL = 1; //T1 多載值的低位元組
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(1); //配置 T0 定時 1ms
pWave = SinWave; //默認正弦波
SetWaveFreq(10); //默認頻率 10Hz
while (1){
KeyDriver(); //呼叫按鍵驅動
}
}
/* 按鍵動作函式,根據鍵碼執行相應的操作,keycode-按鍵鍵碼 */
void KeyAction(unsigned char keycode){
static unsigned char i = 0;
if (keycode == 0x26){ //向上鍵,切換波形
//在 3 種波形間回圈切換
if (i == 0){
i = 1;
pWave = TriWave;
}else if (i == 1){
i = 2;
pWave = SawWave;
}else{
i = 0;
pWave = SinWave;
}
}
}
/* 設定 DAC 輸出值,val-設定值 */
void SetDACOut(unsigned char val){
I2CStart();
if (!I2CWrite(0x48<<1)){ //尋址 PCF8591,如未應答,則停止操作并回傳
I2CStop();
return;
}
I2CWrite(0x40); //寫入控制位元組
I2CWrite(val); //寫入 DA 值
I2CStop();
}
/* 設定輸出波形的頻率,freq-設定頻率 */
void SetWaveFreq(unsigned char freq){
unsigned long tmp;
tmp = (11059200/12) / (freq*32); //定時器計數頻率,是波形頻率的 32 倍
tmp = 65536 - tmp; //計算定時器多載值
tmp = tmp + 33; //修正中斷回應延時造成的誤差
T1RH = (unsigned char)(tmp>>8); //定時器多載值拆分為高低位元組
T1RL = (unsigned char)tmp;
TMOD &= 0x0F; //清零 T1 的控制位
TMOD |= 0x10; //配置 T1 為模式 1
TH1 = T1RH; //加載 T1 多載值
TL1 = T1RL;
ET1 = 1; //使能 T1 中斷
PT1 = 1; //設定為高優先級
TR1 = 1; //啟動 T1
}
/* 配置并啟動 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]);
i++;
if (i >= 32){
i = 0;
}
}
這個程式可以通過“向上”按鍵來實作波形輸出切換,波形輸出的定時重繪由定時器 T1定時來完成,改變 T1 的定時周期即可改變波形的輸出頻率,D/A 輸出沒有辦法接到顯示界面,所以我們用示波器抓出來波形給大家看一下



這幾張圖可以直觀的看到我們程式輸出的波形,細心的同學會發現我們波形上有很多小鋸齒,沒有平滑的連起來,這是因為我們 DA 最多只能輸出 0~Vref 之間的256個離散的電壓值,而不是連續的任意值,所以每個離散值都會持續一定的時間,然后跳變到下一個離散值,于是就呈現出了波形上的這種鋸齒,在實際開發中,我們只需要在 DA 后級加一級低通濾波電路,就可以讓帶鋸齒的波形變得平滑起來,
最后
我能給你提供哪些幫助
本人計算機研究生,擁有豐富的計算機專案經驗和知識維度,幫助你順利畢業!
個人兼職,非中介,實力可測,可先進行免費技術講解!
任何關于技術的問題,都可以問學長,有空都會給同學們解答的,歡迎打擾!
祝各位同學順利畢業!
[關鍵詞]
單片機畢設 單片機畢業設計 畢業設計 畢業設計幫助 單片機設計 畢業設計單片機 畢設 物聯網 嵌入式 嵌入式畢設 嵌入式畢業設計 樹莓派 arduino stm32畢業設計 畢業設計stm32 開發板
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/290354.html
標籤:其他
