希望對大家有幫助。。
入門有針對性的解決一些簡單的實際問題,邊理論邊實踐學一樣會一樣
基本實驗:LED流水燈,數碼管顯示,鍵盤控制,音樂播放,繼電器控制I2C通信實驗,串口通信實驗,紅外線遙控信號解碼實驗等
單片機的定義分類和內部組成
1單片機就是中央處理器CPU,隨機存儲器RAM。只讀存儲器ROM。定時、計數器和各種輸入輸出接口I/o接口電路等部件集成在一塊電路芯片上的微型計算機。
2,1分類按制造工藝分:HMOS和CHMOS CHMOS包括80c51等中間加了C功耗要小
適合便攜式手提式和野外作業。
2分類按不同容量的存儲器配置分:51子系列和52子系列
51表示單片機最后一位數字為1作為標志。片內帶有4KbROM或EPROM(Erasable Programmable ROM,可擦除可編程ROM,128BRAM,兩個16位定時器/計數器和5個中段器52系列是增強型各項指標都高。
AT89S51是AT89C51的升級版支持ISP在線更新程序ISP(Internet Service Provider
內部集成看門狗計時器等。
3.1串行接口就是接口數據傳送
3.2中斷控制系統接收中斷請求如定時時間到,需要鳴笛報警類似stop to do 停下來去執行ROM中特定的每段程序,執行完后再繼續執行先前中斷的程序
時鐘電路控制節拍工作。
一個典型的單片機應用系統包括輸入電路,單片機,輸出電路
把他想象成電腦。
單片機的應用:
p5
十六進制A10B11C12D13E14F15
記A10和D13點得13點F15不是F16
十六進制加H
邏輯數據的運算
邏輯與。。。兩個輸入一個輸出中間加一個恒定5v電壓
有0為0,全1出1
邏輯或有1為1,全0出0;
字長通常與計算機內部的寄存器和運算器數據總線的寬度一致
實例1功能感受protues仿真單片機播放《渴望》主題曲
運用protues打開仿真原理圖。
對單片機進行處理編輯edit component,選取目標文件hex
Clock frequency 時鐘頻率
Ok
原理圖編輯窗口沒有滾動條,可通過預覽窗口該表原理圖的可視范圍。
Protues雙擊右鍵刪除
先單擊鼠標右鍵,可通過鼠標左鍵可以編輯元器件的屬性
鼠標右鍵來刪除畫錯的連線
中鍵縮放原理圖
新建即保存新建設計文件
Junction dot mode連接點 Subcircuit mode 子電路 lab用總線時會用到 Terminals mode 終端接口,有VCC地輸出輸入等接口 Device pins mode 器件引腳用于繪制各種引腳。 Graph mode 仿真圖表,用于各種分析,如noise analysis Tape recorder mode錄音機 Generator mode 信號發生器 Voltage probe mode 電壓探針仿真圖表用 Current probe mode 電流探針仿真圖表用 Virtual instruments mode虛擬儀表有示波器可顯示工作波形 Resistors 電阻 Capacitors電容 Crystal晶振 Radianl electrolytic圓柱形電解電容
Keywords輸入resistors 470r或功率先選擇元器件后放元器件
Led+yellow
Drag object 拖動對象
Editi properties 編輯屬性
Rotate clockwise 順時針旋轉90°
Rotate anti-clockwise 逆時針旋轉90°
X-mirror 水平翻轉
Y-mirror 垂直翻轉
刪可以右鍵雙擊
雙擊鼠標左鍵編輯label
放置電源和地必須編輯正確的label如VCC地GND
各元器件引腳通過總線的連接并不表示真正意義上的電氣連接,需要添加網絡標號。
要運行雙擊單片機
基本
電源5V
振蕩電路:單片機是一種時序電路,必須施加脈沖信號才能工作。在它的內部有一個時鐘產生電路,只要接上兩個電容和一個晶振即可正常工作。P30
復位電路;啟動后讓單片機從初始狀態開始執行程序。
EA一橫:接正電源端,表示使用內部程序存儲器。
注意:觀察仿真效果時,晶振電路,復位電路和EA引腳和電路的連接可以省略。
Keil軟件源程序后綴。C必須手工輸入,表示為c語言程序,讓keilc51采用對應的c語言的方式來編譯源程序。
#include<reg51.h>包含51單片機寄存器定義的頭文件
將新建的源程序文件加載到項目管理器右擊source group文件add c文件
單片機不能處理c,必須將c轉換成二進制或十六進制代碼,匯編或編譯。
用鼠標右鍵點擊target 進入options fortarget 確認output選項中create hex
file:///Z:\TEMP\msohtmlclip1\01\clip_image002.jpg重新構造所有目標
程序燒錄器及燒錄軟件的使用
單片機軟硬件系統仿真成功后,要真正投入實際應用,必須將程序燒寫入單片機芯片,A51程序燒錄器和
先將COM接口(用作數據通信)與計算機的COM接口(RS-232)連接好,然后將單片機安插在燒錄器的插座中,再用一根USB線將USB接口與計算機的USB接口連接,讓計算機通過這根USB線向燒錄器提供+5V電源
使用燒錄器前,手動設置一些,參數標簽頁,根據COM口,設置好串口,波特率設置為28800;
點擊自動擦除器件命令,點擊打開文件命令選擇單片機文件十六進制文件hex 再點擊打開點擊自動寫器件。
實例4用單片機控制一個燈閃爍
Led燈亮存在電壓差和正向偏置
延遲函數
Void main(void)// 兩個void分別表示無須返回值和沒有參數傳遞
{
Unsignedint i;// 定義無符號整數,最大65535
For(i=0;i<20000;i++)
; 只有一個分號表示什么都不做,等待一個機器周期
}
0x中的0是數字0,而不是字母O
郁悶一編寫keil時,
文檔第一行必須是#include<reg51.h>
虛擬儀表
示波器oscilloscope
Protues示波器面板?及使用
單片機需要一個時鐘信號送給內部個電路,才能使他們有節拍的工作,時鐘信號的頻率由外部振蕩電路的晶振頻率決定,51系列單片機的機器周期是由12個振蕩周期組成。
指令周期:單片機執行一條指令的時間。
時鐘頻率越低,延時的時間就越長,燈閃爍的速度就越慢。
實例5 將p1口狀態送入p0口p2口p3口
利用單片機工作速度快的特點,無限循環可以讓單片機不停地把p1口的電平狀態送到p0口p2口和p3口。
引腳接地低電平被輸入到p口
實例6使用p3口流水點亮8位led
記憶,0xfe 11111110 0xfd11111101 0xfb 11111011 0xf7 11110111 0xef 111011110xdf 11011111 0xbf10111111 0x7f 01111111 實例7通過對p3口地址的操作流水點亮8位led
單片機都有固定的地址,記憶:張三在教室的第2排第5列
老師可以說清張三回答問題也可以說請第2排第5列的同學答題。
Sfr x=0xb0; 通過關鍵字sfr將x定義為p2的地址0xb0
定義后,程序中對x的操作就相當于對地址0xb0即p3的操作
類似于指針
P3口的固定地址是BOH
MCS-51單片機存儲器的基本結構
它有兩種1即程序存儲器和2數據存儲器
從物理MSC-51有4個存儲地址空間,即片內程序存儲器和片外程序存儲器
程序存儲器受EA一橫外接電平的控制。
1當EA一橫接地時,單片機只能使用外部程序存儲器
2當EA一橫接+5v是單片機先使用內部程序存儲器,容量不夠時自動使用外部程序存儲器。
特殊功能寄存器
ACC 累加器
標識符
| 名稱
| 地址
| ACC
| 累加器
| E0H
| B
| b寄存器
| F0H
| PSW
| 程序狀態字
| D0H
| SP
| 堆棧指針
| 81H
| DRTR
| 數據指針
| 83H 82H
| P0
|
| 80H
| P1
|
| 90H
| P2
|
| A0H
| P3
|
| B0H
| IP
| 中斷優先級控制
| B8H
|
IE
| 允許中斷控制
| A8H
| TMOD
| 定計方式控制
| 89H
| TCON
| 定計控制
| 88H
| TH0
| 定計0高位字節
| 8CH
| TL0
| 定計0低位字節
| 8AH
| TH1
| 定計1高位字節
| 8DH
| TL1
| 定計1低位字節
| 8BH
| SCON
| 串行控制
| 98H
| SBUF
| 串行數據緩沖器
| 99H
| PCON
| 電源控制
| 87H
|
|
|
|
單片機的復位電路
P54頁???
單片機C語言開發基礎
#include<reg51.h>
C注釋
1種采用/*。。。*/可以注釋多行內容
2種采用//但只能注釋一行
ANSI標準定義的關鍵字
P57記憶思考
P58跳過
數據類型表p59頁
指針型數據
位類型數據
空類型數據
延時函數不需要返回值。
X++先用x的值,再讓x加1
邏輯與&&邏輯或||邏輯非!
按位與& 25&77=9
按位或| 25|77=93
按位異或^ 相異為1,相同出0
按位取反~ 有0出1,有1出0
左移運算符<< 將一個二進制數的各位全部左移若干位,移動的過程中,高位丟棄,低位補0. w=0x3a 00111010Bw<<2,w=11101000B
>>低位丟棄,高位補0
賦值運算符
逗號運算符
條件運算符
強制轉換運算符???
實例8用不同數據類型的數據控制led的閃爍
使用無符號整型數據和無符號字符數據來設計延時函數。
由于整型數據占兩個字節,而無符號字符型數據僅占一個字節,因此對無符號整型數據進行操作花費的時間就要長一些,整型數據要實現100次循環,消耗的時間約800個機器周期。無符號100占300個。為了提高運行效率,盡可能用無符號字符型數據。
實例9 用p0口和p1口分別顯示加法和減法運算結果
其實就是利用二進制的單位數值進行亮1不亮0的表示
乘法除法就是利用二進制轉化為十進制再進行處理
實例12用自增運算控制p0口8位ked的閃爍花樣
只要送到p0口的數值發生變化,p0口8位led點亮的狀態就會發生變化?梢韵葘⒆兞康某踔邓偷絧0口延遲一段時間,再利用自增運算使變量加1,然后將新的變量值送到p0口并延時一段時間,即可使8位led的閃爍花樣不斷變化,
Unsigned char I;定義無符號字符型變量,其值不超過255
運用變量的值變化和將變量的值送到p口用來變化。
For(i=0;i<255;i++)
實例13用p0口顯示邏輯與的運算
P0=(4>0)&&(9>0xab)=1&&0=0;將運算結果送到p0口
實例14用p0口顯示條件運算的結果
P0=(8>4)?8:4; P0=8=00001000B
實例15;用p0口顯示按位異或運算結果
異或相異出1,相同出0;記憶異性才能很火熱的做出子女
P0=0xa2^0x3c 異或要做必須上頂^ 很公平應用
實例16 用p0口顯示左移的運算結果
實例17萬能邏輯電路
F=EY+Z邏輯函數p77圖
1專門設計數字電路,實現邏輯功能
2通過單片機編程來實現邏輯功能軟件即硬件
//實例17:"萬能邏輯電路"實驗
#include<reg51.h> //包含單片機寄存器的頭文件
sbit F=P1^4; //將F位定義為 P1.4
sbit X=P1^5; //將X位定義為 P1.5
sbit Y=P1^6; //將Y位定義為 P1.6
sbit Z=P1^7; //將Z位定義為 P1.7
void main(void)
{
while(1)
{
F=((~X)&Y)|Z; //將邏輯運算結果賦給F
;
}
}
實例18用右移實現流水燈
前提設p口為0xff八次右移一位高位丟棄低位補0
延遲用的變量因為要取大數所以必須用int
后面因為要快所以取char型變量
因為單片機運行快。所以led燈閃后要延遲。
C語言語句
If(S1==0)
P1=0x00;如果按鍵s按下接地(相應位為低電平),
Swich 整型 break 三者緊密
While語句花括號運用和 一般情況下,在循環體中應該有讓循環停止的語句。??
Do while 語句注意;
Do和while連用 while后面的分號不能丟,它表示整個循環語句的結束
Do循環語句 while(循環式)
盡量避免使用goto語句
P87頁的程序軟件即硬件
實例21用for語句實現鳴笛報警
T=1/f,所以要讓蜂鳴器發出頻率f的聲音,只要讓單片機輸送周期為t的脈沖方波電平即可,讓單片機沒半個周期取反一次。半周期可通過延時來實現。可以通過循環的方式來實現延時,
P90一重循環消耗的機器數近似N=3*n
二重循環消耗的機器數近似N=3*n*m
例子,如果單片機的晶振頻率為11.0592MHz,則機器的周期為1.085μs,要發出1600Hz的聲音,就讓單片機每半個周期312μs將輸出電平取反一次,而延時312μs需要消耗機器周期數N=312/1.085≈286可以取300循環次數300/3=100次
Void delay(void)
{
Unsigned char I;
For(i=0;i<100;i++)
;
}形成1600Hz的音頻
相對應800Hz的音頻可以i取200
Sbit sound=P1^5;
Sound=0; 即可執行
Unsigned char i;
While(1)
i=0;??
數組是同類型的一組變量?
Unsigned char code tab[]
應用卻是tab【】??
字符型數組中的個字符數據在單片機中是以字符的ASCII 存放的,
正確的使用指針,可以有效地表示復雜的數據類型,動態分配內存,方便的使用字符串,有效地使用數組。
指針本身就具有地址還存在一個地址,
Unsigned char*p;
Unsigned char a;
P=&a;
指針數組
Unsigned chara[]={0,1,2,3};
Unsigned char*a[]={&a[0],&a[1],&a[2],&a[3]};
數組的指針
Unsigned chara[]={0,1,2,3};
Unsignde *p;
P=&a[0];
P[ i]+j 為P[ i][j]
實例26未細看
返回值是通過return語句獲得的。
如果函數無返回值,需要用void來聲明。
數組作為函數參數
一個數組的名字表示該數組的首地址,所以用數組名作為函數的參數時。被傳遞的數組的首地址,被調用函數的參數的形式須是定義為指針型變量。
用數組名作為函數的參數時,應該在主調函數和被調函數中都進行數組定義。定義的數組類型必須一致。編譯器不檢查形參數組的長度p109函數??
函數型指針
一個函數在編譯時,就分配了一個入口地址,這個入口地址就是函數的指針,
類型說明符 (*指針變量名)(形參列表)
Int (*p)(int a,int b)
(*p)(a,b)
這些需要思考p110頁
。
P1=z/256;取得z的高八位
P2=z/256;取得z的低八位????
While(1)
;無限循環防止程序跑飛。
實例30用有參函數控制p0口8位流水燈的流水速度
P113實例31不實用??、
實例32 實例33是不錯的c語言程序函數調用。練習c語言p115p116
實例34不錯c語言程序p118
指針數組適合用來指向若干個字符串,尤其是各列字符串長度不一致的情形,這對于字符的液晶顯示等很有意義。
實際運用液晶等顯示器顯示字符時,如果液晶的接口通過P0口和單片機連接,將各字符串送入p0口,實際上就是送入液晶顯示器。
實例35
#include<ctype.h>
P0=isalpha(’_’)?0xf0:0x0f;
內部函數文件instrins.h中有_crol_()函數
實例36;應用內部函數文件instrins.h中有_crol_()函數來點亮P3口8位流水燈
_crol_(15,2)
的返回值為00111100B=0x3c思考他的應用
實例37實例38感覺像是介紹函數以后????c語言應用程序卡那可可能看看
C語言編譯預處理
宏定義c語言允許一個標示符來表示一個字符串,稱為宏。
P125宏定義不是c語句,所以不需加分號。
可以用#undef命令來終止宏定義的作用域。即對#undef后面的無用。為防止歧義應加括號及時
帶參數的函數宏和函數不同,函數是先求出實參表達式的值,然后代入形參,而帶參數的宏只是進行簡單的字符替換。
實例40文件包含應用舉例
使用頭文件為#include<AT89X51.h>中有關特殊功能寄存器的定義
已將P3_0定義為P3.0引腳,直接應用P3_0就可以對P3口進行操作了。
實例41條件編譯應用舉例
常用的條件編譯是根據某常量表達式的值的是否為真來控制編譯
即#if 常量表達式
程序段1
#else
程序段2
#endif??思考好的應用
第五章單片機的定時器計數器
當加在
定時器計數器T0或T1用作計數器時,對外接晶振產生的振蕩信號經12分頻后,提供給計數器,作為計數器的脈沖輸入,計數器以12分頻后的脈沖周期為基本計數單位,對輸入的脈沖進行計數,直至產生溢出。???
P136頁到p140頁有點不懂。工作方式
圖p135T0或T1引腳上的外部脈沖信號出現一個由1到0的負跳變時,計數器加1,直至計數器溢出。
CPU是按順序進行工作的。
實例42用計時器T0查詢方式控制P2口的8位LED閃爍
T0工作于方式1,LED燈的閃爍周期為100ms,即亮50ms,熄滅50ms;
12分頻即頻率被12等分,周期即12除頻率
定時器的初值設定需要進行計算,總而言之,就是定時器必須達到頂值即65536.
初值需要T0的高八位寄存器TH0和低八位寄存器TL0分別存儲
存儲方法及
TH0= /256;
TL0= %256;
溢出標志位是否為1若為1表示時間已到,否則,等待。
//實例42:用定時器T0查詢方式P2口8位控制LED閃爍
#include<reg51.h> // 包含51單片機寄存器定義的頭文件
/**************************************************************
函數功能:主函數
**************************************************************/
void main(void)
{
// EA=1; //開總中斷
// ET0=1; //定時器T0中斷允許
TMOD=0x01; //使用定時器T0的模式1
TH0=(65536-46083)/256; //定時器T0的高8位賦初值
TL0=(65536-46083)%256; //定時器T0的高8位賦初值
TR0=1; //啟動定時器T0
TF0=0;
P2=0xff;
while(1)//無限循環等待查詢
{
while(TF0==0)//查詢標志位是否溢出
;
TF0=0;
P2=~P2;按位取反,實現led燈的閃爍
TH0=(65536-46083)/256; //定時器T0的高8位賦初值
TL0=(65536-46083)%256; //定時器T0的高8位賦初值
}
}
TFO 記憶flow溢出
TRO 記憶trigger引起啟動
THO 記憶high高八位
TMOD 記憶mode 方式
實例43,用定時器t1查詢方式控制單片機發出1kHz音頻
//實例43:用定時器T1查詢方式控制單片機發出1KHz音頻
#include<reg51.h> // 包含51單片機寄存器定義的頭文件
sbit sound=P3^7; //將sound位定義為P3.7引腳
/**************************************************************
函數功能:主函數
**************************************************************/
void main(void)
{
// EA=1; //開總中斷
// ET0=1; //定時器T0中斷允許
TMOD=0x10; //使用定時器T1的模式1
TH1=(65536-921)/256; //定時器T1的高8位賦初值
TL1=(65536-921)%256; //定時器T1的高8位賦初值
TR1=1; //啟動定時器T1
TF1=0;
while(1)//無限循環等待查詢
{
while(TF1==0)
;
TF1=0;
sound=~sound; //將P3.7引腳輸出電平取反
TH1=(65536-921)/256; //定時器T0的高8位賦初值
TL1=(65536-921)%256; //定時器T0的高8位賦初值
}
}
//實例44:將計數器T0計數的結果送P1口8位LED顯示
#include<reg51.h> // 包含51單片機寄存器定義的頭文件
sbit S=P3^4; //將S位定義為P3.4引腳
/**************************************************************
函數功能:主函數
**************************************************************/
void main(void)
{
// EA=1; //開總中斷
// ET0=1; //定時器T0中斷允許
TMOD=0x02; //使用定時器T0的模式2
TH0=256-156; //定時器T0的高8位賦初值
TL0=256-156; //定時器T0的高8位賦初值
TR0=1; //啟動定時器T0
while(1)//無限循環等待查詢
{
while(TF0==0) //如果未計滿就等待
{
if(S==0) //按鍵S按下接地,電平為0
P1=TL0; //計數器TL0加1后送P1口顯示
}
TF0=0; //計數器溢出后,將TF0清0
}
}
第六章單片機的中斷系統
中斷系統
類似寫作業
定時器計時器實際上就是中斷源。
MCS51單片機提供5個中斷源。
外部中斷INT0一橫 編號0 由P3.2引腳輸入
定時器T0 編號1
外部中斷INT1一橫 編號2 由P3.3引腳輸入
定時器T1 編號3
串行口通信中斷RI或TI 編號4
自然優先級從上到下逐級遞減。
P150 p151頁未看
void Time(void) interrupt1 using 0
{
}
//實例46:用定時器T0的中斷實現長時間定時
#include<reg51.h> // 包含51單片機寄存器定義的頭文件
sbit D1=P2^0; //將D1位定義為P2.0引腳
unsigned char Countor; //設置全局變量,儲存定時器T0中斷次數
/**************************************************************
函數功能:主函數
**************************************************************/
void main(void)
{
EA=1; //開總中斷
ET0=1; //定時器T0中斷允許
TMOD=0x01; //使用定時器T0的模式2
TH0=(65536-46083)/256; //定時器T0的高8位賦初值
TL0=(65536-46083)%256; //定時器T0的高8位賦初值
TR0=1; //啟動定時器T0
Countor=0; //從0開始累計中斷次數
while(1)//無限循環等待中斷
;
}
/**************************************************************
函數功能:定時器T0的中斷服務程序
**************************************************************/
void Time0(void)interrupt 1 using 0 //“interrupt”聲明函數為中斷服務函數
//其后的1為定時器T0的中斷編號;0表示使用第0組工作寄存器
{
Countor++; //中斷次數自加1
if(Countor==20) //若累計滿20次,即計時滿1s
{
D1=~D1; //按位取反操作,將P2.0引腳輸出電平取反
Countor=0; //將Countor清0,重新從0開始計數
}
TH0=(65536-46083)/256;//定時器T0的高8位重新賦初值
TL0=(65536-46083)%256; //定時器T0的高8位重新賦初值
}
定時器T0工作于方式1時,最大可計脈沖數次數為65536,對于11。0592MHz的時鐘頻率。一個脈沖的寬度為1.085μs,則最大計時長度只有1.085×65536=71107μs即大約71ms,
要想計時更長時間,采用 軟件計時的方法
設置一個變量counter 來存儲定時器T0的中斷次數,即每產生一次中斷,使變量counter自加1,如果T0每50ms中斷一次,那當counter自加20次時,所及時間為1s。
中斷一次就要重新賦值一次
控制兩個LED燈以不同的周期閃爍,第一個LED亮滅時間為100ms,第二個LED亮滅時間為400ms,所以需要設置兩個變量counter1 和counter2來分別統計中斷次數,且都為最小的整數倍。
//實例47:用定時器T1中斷控制兩個LED以不同周期閃爍
#include<reg51.h> // 包含51單片機寄存器定義的頭文件
sbit D1=P2^0; //將D1位定義為P2.0引腳
sbit D2=P2^1; //將D2位定義為P2.1引腳
unsigned char Countor1;//設置全局變量,儲存定時器T1中斷次數
unsigned char Countor2;//設置全局變量,儲存定時器T1中斷次數
/**************************************************************
函數功能:主函數
**************************************************************/
void main(void)
{
EA=1; //開總中斷
ET1=1; //定時器T1中斷允許
TMOD=0x10; //使用定時器T1的模式1
TH1=(65536-46083)/256; //定時器T1的高8位賦初值
TL1=(65536-46083)%256; //定時器T1的高8位賦初值
TR1=1; //啟動定時器T1
Countor1=0; //從0開始累計中斷次數
Countor2=0; //從0開始累計中斷次數
while(1)//無限循環等待中斷
;
}
/**************************************************************
函數功能:定時器T1的中斷服務程序
**************************************************************/
void Time1(void)interrupt 3 using 0 //“interrupt”聲明函數為中斷服務函數
//其后的3為定時器T1的中斷編號;0表示使用第0組工作寄存器
7
Countor1++; //Countor1自加1
Countor2++; //Countor2自加1
if(Countor1==2) //若累計滿2次,即計時滿100ms
{
D1=~D1; //按位取反操作,將P2.0引腳輸出電平取反
Countor1=0; //將Countor1清0,重新從0開始計數
}
if(Countor2==8) //若累計滿8次,即計時滿400ms
{
D2=~D2; //按位取反操作,將P2.1引腳輸出電平取反
Countor2=0; //將Countor1清0,重新從0開始計數
}
TH1=(65536-46083)/256;//定時器T1的高8位重新賦初值
TL1=(65536-46083)%256; //定時器T1的高8位重新賦初值
}
實現方法
先開總中斷EA 分支中斷ET?,選擇方式,賦初值 ,啟動定時器T?,聲明
音調與頻率的關系
音調
| 低1
| 低2
| 低3
| 低4
| 低5
| 低6
| 低7
| 頻率
| 262
| 294
| 330
| 349
| 392
| 440
| 494
| 音調
| 中1
| 中2
| 中3
| 中4
| 中5
| 中6
| 中7
| 頻率
| 523
| 587
| 659
| 698
| 784
| 880
| 988
| 音調
| 高1
| 高2
| 高3
| 高4
| 高5
| 高6
| 高7
| 頻率
| 1046
| 1175
| 1318
| 1397
| 1568
| 1760
| 1967
|
由于單片機的輸入輸出口只有高電平1和低電平0,因此向蜂鳴器輸送的電平信號實際是就是該音頻的方波。例如中音頻率523Hz,他的周期為1÷523秒,即1。93ms只要向蜂鳴器輸送周期為1.91ms的脈沖方波電平信號就能發出523Hz的音調,該方波的半周期為1.91÷2=0.995ms。為此,需要利用定時器的中斷,讓輸送給蜂鳴器的電平信號每0。955ms取反一次即可,由于本書使用的單片機晶振為11.0952mhz,他的機器周期為12×(1÷11。0592)=1.085μs。因此需要的機器周期總數為
995μs÷1.085μs=880
定時器的定時常數為880
C=10^6μs除2f÷1.085μs=460830÷頻率
THO=(8192-C)÷32???
每分鐘為72節拍,每節拍1000×60ms÷72=833ms
//實例49:用定時器T0的中斷實現"渴望"主題曲的播放
#include<reg51.h> //包含51單片機寄存器定義的頭文件
sbit sound=P3^7; //將sound位定義為P3.7
unsigned int C; //儲存定時器的定時常數
//以下是C調低音的音頻宏定義
#define l_dao 262 //將“l_dao”宏定義為低音“1”的頻率262Hz
#define l_re 286 //將“l_re”宏定義為低音“2”的頻率286Hz
#define l_mi 311 //將“l_mi”宏定義為低音“3”的頻率311Hz
#define l_fa 349 //將“l_fa”宏定義為低音“4”的頻率349Hz
#define l_sao 392 //將“l_sao”宏定義為低音“5”的頻率392Hz
#define l_la 440 //將“l_a”宏定義為低音“6”的頻率440Hz
#define l_xi 494 //將“l_xi”宏定義為低音“7”的頻率494Hz
//以下是C調中音的音頻宏定義
#define dao 523 //將“dao”宏定義為中音“1”的頻率523Hz
#define re 587 //將“re”宏定義為中音“2”的頻率587Hz
#define mi 659 //將“mi”宏定義為中音“3”的頻率659Hz
#define fa 698 //將“fa”宏定義為中音“4”的頻率698Hz
#define sao 784 //將“sao”宏定義為中音“5”的頻率784Hz
#define la 880 //將“la”宏定義為中音“6”的頻率880Hz
#define xi 987 //將“xi”宏定義為中音“7”的頻率523H
//以下是C調高音的音頻宏定義
#define h_dao 1046 //將“h_dao”宏定義為高音“1”的頻率1046Hz
#define h_re 1174 //將“h_re”宏定義為高音“2”的頻率1174Hz
#define h_mi 1318 //將“h_mi”宏定義為高音“3”的頻率1318Hz
#define h_fa 1396 //將“h_fa”宏定義為高音“4”的頻率1396Hz
#define h_sao 1567 //將“h_sao”宏定義為高音“5”的頻率1567Hz
#define h_la 1760 //將“h_la”宏定義為高音“6”的頻率1760Hz
#define h_xi 1975 //將“h_xi”宏定義為高音“7”的頻率1975Hz
/*******************************************
函數功能:1個延時單位,延時200ms
******************************************/
void delay()
{
unsigned char i,j;
for(i=0;i<250;i++)
for(j=0;j<250;j++)
;
}
/*******************************************
函數功能:主函數
******************************************/
void main(void)
{
unsigned char i,j;
//以下是《渴望》片頭曲的一段簡譜
unsigned int code f[]={re,mi,re,dao,l_la,dao,l_la, //每行對應一小節音符
l_sao,l_mi,l_sao,l_la,dao,
l_la,dao,sao,la,mi,sao,
re,
mi,re,mi,sao,mi,
l_sao,l_mi,l_sao,l_la,dao,
l_la,l_la,dao,l_la,l_sao,l_re,l_mi,
l_sao,
re,re,sao,la,sao,
fa,mi,sao,mi,
la,sao,mi,re,mi,l_la,dao,
re,
mi,re,mi,sao,mi,
l_sao,l_mi,l_sao,l_la,dao,
l_la,dao,re,l_la,dao,re,mi,
re,
l_la,dao,re,l_la,dao,re,mi,
re,
0xff}; //以0xff作為音符的結束標志
//以下是簡譜中每個音符的節拍
//"4"對應4個延時單位,"2"對應2個延時單位,"1"對應1個延時單位
unsigned char code JP[]={4,1,1,4,1,1,2,
2,2,2,2,8,
4,2,3,1,2,2,
10,
4,2,2,4,4,
2,2,2,2,4,
2,2,2,2,2,2,2,
10,
4,4,4,2,2,
4,2,4,4,
4,2,2,2,2,2,2,
10,
4,2,2,4,4,
2,2,2,2,6,
4,2,2,4,1,1,4,
10,
4,2,2,4,1,1,4,
10
};
EA=1; //開總中斷
ET0=1; //定時器T0中斷允許
TMOD=0x00; // 使用定時器T0的模式1(13位計數器)
while(1) //無限循環
{
i=0; //從第1個音符f[0]開始播放
while(f[ i]!=0xff) //只要沒有讀到結束標志就繼續播放
{
C=460830/f[ i];
TH0=(8192-C)/32; //可證明這是13位計數器TH0高8位的賦初值方法
TL0=(8192-C)%32; //可證明這是13位計數器TL0低5位的賦初值方法
TR0=1; //啟動定時器T0
for(j=0;j<JP[ i];j++) //控制節拍數
delay(); //延時1個節拍單位
TR0=0; //關閉定時器T0
i++; //播放下一個音符
}
}
}
/***********************************************************
函數功能:定時器T0的中斷服務子程序,使P3.7引腳輸出音頻的方波
************************************************************/
void Time0(void ) interrupt 1 using 1
{
sound=!sound; //將P3.7引腳輸出電平取反,形成方波
TH0=(8192-C)/32; //可證明這是13位計數器TH0高8位的賦初值方法
TL0=(8192-C)%32; //可證明這是13位計數器TL0低5位的賦初值方法
}
、
實例51
本例用單片機U1從P1。4引腳輸出正脈寬為250μs的方波,再利用單片機U2的into引腳檢測,驗證方波的正脈沖寬度,有點沒看懂
//實例51-2:定時器T0的模式2測量正脈沖寬度
#include<reg51.h> //包含51單片機寄存器定義的頭文件
sbitui=P3^2; //將ui位定義為P3.0(INT0)引腳,表示輸入電壓
/*******************************************
函數功能:主函數
******************************************/
void main(void)
{
TMOD=0x0a; // TMOD=0000 1010B,使用定時器T0的模式2,GATE置1
EA=1; //開總中斷
ET0=0; //不使用定時器T0的中斷
TR0=1; //啟動T0
TH0=0; //計數器T0高8位賦初值
TL0=0; //計數器T0低8位賦初值
while(1) //無限循環,不停地將TL0計數結果送P1口
{
while(ui==0) //INT0為低電平,T0不能啟動
;
TL0=0; //INT0為高電平,啟動T0計時,所以將TL0清0
while(ui==1) //在INT0高電平期間,等待,計時
;
P1=TL0; //將計時結果送P1口顯示
}
}
//實例51-1:輸出正脈寬為250微秒的方波
#include<reg51.h> //包含51單片機寄存器定義的頭文件
sbit u=P1^4; //將u位定義為P1.4
/*******************************************
函數功能:主函數
******************************************/
void main(void)
{
TMOD=0x02; //TMOD=0000 0010B,使用定時器T0的模式2
EA=1; //開總中斷
ET0=1; //定時器T0中斷允許
TH0=256-250; //定時器T0的高8位賦初值
TL0=256-250; //定時器T0的高8位賦初值
TR0=1; //啟動定時器T0
while(1) //無限循環,等待中斷
;
}
/**************************************************************
函數功能:定時器T0的中斷服務程序
**************************************************************/
void Time0(void)interrupt 1 using 0 //"interrupt"聲明函數為中斷服務函數
{
u=~u; //將P1.4引腳輸出電平取反,產生方波
}
第7章
MCS51單片機串行4中工作方式??、
為了能夠在計算機端看到單片機發出的數據,較好的方法是借助于調試軟件“串口調試助手”
第8章
P197頁圖
第9章
I^2C總線是Inter Integrated Circuit Bus 內部集成電路總線
千萬不要認為只要程序對了,單片機就可以永遠正確運行,實際工作環境的各種干擾會導致單片機死機。
X5045
具有上電復位和降壓管理的功能,還具有看門狗定時器和具有塊保護功能的串行EEPROM。
上電復位;上電就產生復位信號,
看門狗; 規定時間沒有電平信號 就產生復位信號,利用該功能可以讓單片機死機后自動重新復位
第10章
A/D轉換器;逐次逼近(常用) 雙積分牛但慢 并行
紅外信號接收
紅外發射部分包括鍵盤矩陣,編碼調制 LED紅外發送器 接收器包括光電轉換放大器
解調電路 解碼電路
中斷定時器程序其實隱藏了調用。
定時中斷一次還需重新賦值一次。
void Time0(void)interrupt 1 using 1每個字符都要空格
LED0=!LED0; //P3.0引腳取反
While(1)前面賦值確定原先的狀態
判斷端口是否是低電平應該這樣if(S1==0)
而不是if(S1=0)
函數功能:鍵盤掃描子程序
**************************************************/
void key_scan(void)
{
if((P1&0xf0)!=0xf0) //第一次檢測到有鍵按下
{
delay30ms(); //延時20ms再去檢測
if(S1==0) //按鍵S1被按下
keyval=1;
if(S2==0) //按鍵S2被按下
keyval=2;
if(S3==0) //按鍵S3被按下
keyval=3;
if(S4==0) //按鍵S4被按下
keyval=4;
sbit S1=P1^4; //將S1位定義為P1.4引腳
sbit S2=P1^5; //將S2位定義為P1.5引腳
sbit S3=P1^6; //將S3位定義為P1.6引腳
sbit S4=P1^7; //將S4位定義為P1.7引腳
有零則與邏輯與一起必然為零 }
完整的Word格式文檔51黑下載地址:
51單片機c語言總結.doc
(143.5 KB, 下載次數: 40)
2018-9-25 08:58 上傳
點擊文件名下載附件
下載積分: 黑幣 -5
|