找什么人做公司網(wǎng)站小小課堂seo自學(xué)網(wǎng)
一. 定時器
1. 簡介
C51中的定時器和計數(shù)器是同一個硬件電路支持的,通過寄存器配置不同,就可以將他當(dāng)做定時器或者計數(shù)器使用。
確切的說,定時器和計數(shù)器區(qū)別是致使他們背后的計數(shù)存儲器加1的信號不同。當(dāng)配置為定時器使用時,每經(jīng)過1個機(jī)器周期,計數(shù)存儲器的值就加1。而當(dāng)配置為計數(shù)器時,每來一個負(fù)跳變信號(信號從P3.4 或者P3.5引腳輸入),就加1,以此達(dá)到計數(shù)的目的。
標(biāo)準(zhǔn)C51有2個定時器/計數(shù)器:T0和T1。他們的使用方法一致。C52相比C51多了一個T2
1.1 概念解讀
- 定時器和計數(shù)器,電路一樣
- 定時或者計數(shù)的本質(zhì)就是讓單片機(jī)某個部件數(shù)數(shù)
- 當(dāng)定時器用的時候,靠內(nèi)部震蕩電路數(shù)數(shù)
- 當(dāng)計數(shù)器用的時候,數(shù)外面的信號,讀取針腳的數(shù)據(jù)
在51單片機(jī)中,定時器和計數(shù)器的主要區(qū)別在于它們的工作方式和用途:
- 定時器(Timer):
-
- 工作方式:定時器使用內(nèi)部時鐘源(例如晶振)進(jìn)行計數(shù)。
- 用途:用于計時,例如生成精確的時間延遲、實現(xiàn)周期性中斷等。
- 例子:設(shè)定一個定時器來每隔一秒觸發(fā)一次中斷,用于更新系統(tǒng)時鐘。
- 計數(shù)器(Counter):
-
- 工作方式:計數(shù)器通過外部信號(例如外部引腳上的脈沖信號)進(jìn)行計數(shù)。
- 用途:用于計數(shù)外部事件或脈沖,例如計數(shù)輸入脈沖的次數(shù)。
- 例子:連接一個傳感器到單片機(jī)的計數(shù)器引腳,計數(shù)傳感器發(fā)出的脈沖信號。
1.2 定時器怎么定時
定時器的本質(zhì)原理: 每經(jīng)過一個機(jī)器周期,就加1 :寄存器
思考:
- 什么是晶振
晶振(晶體震蕩器),又稱數(shù)字電路的“心臟”,是各種電子產(chǎn)品里面必不可少的頻率元器件。數(shù)字電
路的所有工作都離不開時鐘,晶振的好壞、晶振電路設(shè)計的好壞,會影響到整個系統(tǒng)的穩(wěn)
- 什么是時鐘周期
時鐘周期也稱為振蕩周期,定義為時鐘頻率的倒數(shù)。時鐘周期是計算機(jī)中最基本的、最小的時間單
位。在一個時鐘周期內(nèi),CPU僅完成一個最基本的動作。時鐘周期是一個時間的量。更小的時鐘周
期就意味著更高的工作頻率
- 什么是機(jī)器周期
機(jī)器周期也稱為CPU周期。在計算機(jī)中,為了便于管理,常把一條指令的執(zhí)行過程劃分為若干個階
段(如取指、譯碼、執(zhí)行等),每一階段完成一個基本操作。完成一個基本操作所需要的時間稱為
機(jī)器周期。一般情況下,一個機(jī)器周期由若干個時鐘周期組成
- 加1經(jīng)過了多少時間
當(dāng)晶振頻率是11.0592MHz的時候,等于11059.2KHz = 11059200Hz
跳一次等于一個機(jī)器周期
一個機(jī)器周期等于12個時鐘周期
一個時鐘周期等于晶振的倒數(shù):1/11059200秒
那么跳一次就是:12/11059200秒 = 12000000/11059200 微秒= 1.085微妙
機(jī)器周期 = 12 x 時鐘周期
= 12 x (1/時鐘頻率) 秒 = 12 / 時鐘頻率 秒 = 12 / 11059200 秒 = 12 000 000 / 11059200 微秒 = 1.085 微秒
1.3 定時器編程
相關(guān)寄存器:
- 在哪里加1,最大計數(shù)時間,也就是爆表了能計算多長
在T8H0/1和TL0/1寄存器中加1,默認(rèn)是從0開始數(shù)數(shù),最多能數(shù)65536下,累計計時71ms ,71毫秒
- 如何算出10ms定時器的初值
就不讓他從0開始數(shù)數(shù),10ms需要數(shù)9216下,你讓他從65536-9126=56320(16進(jìn)制表示為
0xDC00)開始數(shù)數(shù)
這樣TL0=0x00;TH0=0xDC
- 關(guān)于TCON
- 怎么知道爆表
TCON寄存器的bit5(TF0)能表示爆表:當(dāng)爆表的時候,硬件會修改bit5(TF0)位上面的數(shù)據(jù),改成 1(置1),如果不用中斷,我們代碼清零。
- 怎么開始計時
TCON寄存器的bit4,TRO通過編程讓這個位為1的時候,開始計時,相當(dāng)于按下了鬧鐘
- 定時器使用是有很多種模式的
定時器模式寄存器:TMOD來選擇定時器模式,選擇工作方式1,TMOD的bit0 bit1配置成0 1 :16 位的定時器功能
- 四個二進(jìn)制數(shù)表示一位的16進(jìn)制數(shù)
8421法進(jìn)制的轉(zhuǎn)換,二進(jìn)制轉(zhuǎn)16進(jìn)制(方便人類來看,對計算機(jī)底層來說,不關(guān)心二進(jìn)制010101010)。
配寄存器推薦用按位操作,清零的時候,對應(yīng)的需要清零的位與上0,不需要清零的位與上1
置1的時候,需要置1的位置或1,不需要置一的位置或0
AUXR,降低單片機(jī)時鐘對外界的輻射。
- 定時器控制led燈每隔一秒滅一次
#include "reg52.h"sbit led1 = P3^6; // 定義 led1 變量,指向 P3.6 引腳
sbit led2 = P3^7; // 定義 led2 變量,指向 P3.7 引腳void main()
{// 1.配置定時器0工作模式為16位計數(shù)器模式int cnt = 0; // 定義一個整數(shù)變量 'cnt' 用于計數(shù)led1 = 1; // 初始化 led1 為高電平(假設(shè)高電平點亮)led2 = 0; // 初始化 led2 為低電平(假設(shè)低電平熄滅)TMOD = 0x01; // 配置定時器0為模式1(16位定時器模式)// 2.設(shè)置定時器初值,使其每10ms產(chǎn)生一次溢出TL0 = 0x00; // 設(shè)置定時器0低8位初值為 0x00TH0 = 0xDC; // 設(shè)置定時器0高8位初值為 0xDC// 3.啟動計時TR0 = 1; // 啟動定時器0TF0 = 0; // 清除定時器0溢出標(biāo)志位while(1) { // 無限循環(huán)if(TF0 == 1) { // 如果定時器0溢出 爆表TF0 = 0; // 清除定時器0溢出標(biāo)志位cnt++; // 增加計數(shù)器 'cnt' 的值// 重新設(shè)置定時器初值TL0 = 0x00; TH0 = 0xDC;if(cnt == 100) { // 如果計數(shù)器 'cnt' 達(dá)到 100(即經(jīng)過1秒)cnt = 0; // 重置計數(shù)器 'cnt'led1 = !led1; // 翻轉(zhuǎn) led1 的狀態(tài)led2 = !led2; // 翻轉(zhuǎn) led2 的狀態(tài)}}}
}
1.4 定時器中斷方式控制 (相當(dāng)于多線程)
中斷寄存器
- 定時器中斷方式控制led
#include "reg52.h" // 包含51系列單片機(jī)寄存器定義文件sbit led = P3^6; // 定義一個位變量led,連接到P3端口的第6位(LED1)
sbit led1 = P3^7; // 定義一個位變量led1,連接到P3端口的第7位(LED2)
int cnt = 0; // 定義一個整數(shù)變量cnt,用來統(tǒng)計定時器溢出的次數(shù)// 定義定時器0初始化函數(shù)
void Time0Init()
{// 1. 配置定時器0工作模式為16位計時模式TMOD = 0x01; // 設(shè)置TMOD寄存器為0x01,定時器0為16位定時器模式// 2. 設(shè)置定時器初值,以生成大約10ms的定時TL0 = 0x00; // 設(shè)置定時器0低8位初值為0x00TH0 = 0xDC; // 設(shè)置定時器0高8位初值為0xDC(即0xDC00)// 3. 啟動定時器0TR0 = 1; // 啟動定時器0,使其開始計時TF0 = 0; // 清除定時器0的溢出標(biāo)志位(初始為0)// 4. 啟用定時器0中斷ET0 = 1; // 使能定時器0中斷,使單片機(jī)能夠響應(yīng)定時器0的中斷請求// 5. 啟用總中斷EA = 1; // 啟用全局中斷,使單片機(jī)能夠響應(yīng)所有中斷請求
}void main()
{led = 1; // 將LED1點亮(即將P3^6置為高電平)led1 = 0; // 將LED2熄滅(即將P3^7置為低電平)Time0Init(); // 調(diào)用定時器初始化函數(shù),設(shè)置定時器0并啟動定時器while(1) {// 無限循環(huán),程序在這里等待中斷事件發(fā)生// 這部分代碼可以執(zhí)行其他任務(wù),但本例中為空}
}// 定時器0中斷處理函數(shù) interrupt 1 定時器0的優(yōu)先級
void Time0Handler() interrupt 1
{cnt++; // 每次定時器0溢出時,計數(shù)器cnt增加1// 重新設(shè)置定時器0的初值,保持定時周期不變TL0 = 0x00; // 重新加載定時器0低8位初值為0x00TH0 = 0xDC; // 重新加載定時器0高8位初值為0xDC(即0xDC00)if (cnt == 30) { // 如果定時器0溢出30次(約300ms)cnt = 0; // 重置計數(shù)器cnt為0// 翻轉(zhuǎn)LED的狀態(tài)led = !led; // 每300ms翻轉(zhuǎn)LED1的狀態(tài)led1 = !led1; // 每300ms翻轉(zhuǎn)LED2的狀態(tài)}
}
這段代碼是用來在51系列單片機(jī)中配置定時器0,使其每隔1秒鐘翻轉(zhuǎn)一個LED的狀態(tài)。下面是對每一部分的詳細(xì)解釋:
1. 頭文件和變量定義
#include "reg52.h"sbit led = P3^6; // 定義一個位變量led,連接到P3端口的第6位(LED1)
sbit led1 = P3^7; // 定義一個位變量led1,連接到P3端口的第7位(LED2)
int cnt = 0; // 定義一個整數(shù)變量cnt,用來統(tǒng)計定時器溢出次數(shù)
#include "reg52.h"
:包含51系列單片機(jī)的寄存器定義文件。sbit led = P3^6;
:將單片機(jī)的P3端口的第6位定義為led
,用于控制LED的開關(guān)。sbit led1 = P3^7;
:將P3端口的第7位定義為led1
,雖然在代碼中沒有使用。int cnt = 0;
:定義一個計數(shù)器cnt
,用于跟蹤定時器0的溢出次數(shù)。
2. Time0Init
函數(shù)
void Time0Init()
{//1. 配置定時器0工作模式位16位計時TMOD = 0x01;//2. 給初值,定一個10ms出來TL0=0x00;TH0=0xDC;//3. 開始計時TR0 = 1;TF0 = 0;//4. 打開定時器0中斷ET0 = 1;//5. 打開總中斷EAEA = 1;
}
TMOD = 0x01;
:將TMOD
寄存器的值設(shè)置為0x01
,將定時器0配置為模式1(16位定時器模式)。低4位0001
表示定時器0的工作模式。TL0 = 0x00;
和TH0 = 0xDC;
:設(shè)置定時器0的初始值。TH0
和TL0
設(shè)置為0xDC00
,這樣定時器從0xDC00
開始計數(shù)。TR0 = 1;
:啟動定時器0。TF0 = 0;
:清除定時器0的溢出標(biāo)志位。ET0 = 1;
:允許定時器0的中斷。EA = 1;
:允許總中斷,使單片機(jī)能夠響應(yīng)所有中斷請求。
3. main
函數(shù)
void main()
{led = 1; // 初始時點亮LEDTime0Init(); // 初始化定時器0while(1){// 無限循環(huán),等待中斷發(fā)生}
}
led = 1;
:在程序開始時,將led
設(shè)為1,點亮LED。Time0Init();
:調(diào)用初始化定時器0的函數(shù)。while(1){}
:無限循環(huán),程序在這里等待中斷事件發(fā)生。實際的操作由中斷處理函數(shù)完成。
4. 定時器0中斷處理函數(shù)
void Time0Handler() interrupt 1
{cnt++; // 統(tǒng)計溢出次數(shù)// 重新設(shè)置定時器初值TL0=0x00;TH0=0xDC;if(cnt == 100) { // 每100次溢出表示1秒cnt = 0; // 重置計數(shù)器led = !led; // 翻轉(zhuǎn)LED狀態(tài)}
}
void Time0Handler() interrupt 1
:定義了一個中斷服務(wù)函數(shù),用于處理定時器0的中斷。interrupt 1
表示這是定時器0的中斷處理函數(shù)。cnt++;
:每次定時器0溢出時,計數(shù)器cnt
增加1。TL0 = 0x00;
和TH0 = 0xDC;
:重新加載定時器初值,保持定時器周期不變。if(cnt == 100)
:檢查cnt
是否達(dá)到100。每100次溢出表示1秒(因為10毫秒 × 100 = 1000毫秒,即1秒)。
-
cnt = 0;
:重置cnt
以開始新的計時周期。led = !led;
:每秒鐘翻轉(zhuǎn)LED的狀態(tài)。
總結(jié)
- 初始化:
Time0Init
函數(shù)設(shè)置定時器0的工作模式和初值,并開啟定時器中斷。 - 主程序:
main
函數(shù)設(shè)置LED初始狀態(tài),并無限循環(huán)等待中斷。 - 中斷處理:
Time0Handler
函數(shù)在每次定時器0溢出時執(zhí)行,統(tǒng)計溢出次數(shù),并每1秒翻轉(zhuǎn)一次LED的狀態(tài)。
- 定時器中斷方式控制led,led燈多線程 控制
#include "reg52.h"// 定義LED控制的位變量
sbit led = P3^6; // LED1 連接到P3端口的第6位
sbit led1 = P3^7; // LED2 連接到P3端口的第7位int cnt = 0; // 用于計數(shù)定時器溢出次數(shù)的變量// 定時器0初始化函數(shù)
void Time0Init()
{// 1. 配置定時器0工作模式為16位計時模式TMOD = 0x01; // 設(shè)置定時器0為16位計時器模式(模式1)// 2. 給定初值,設(shè)置一個10ms的定時周期TL0 = 0x00; // 設(shè)置定時器0的低8位初值TH0 = 0xDC; // 設(shè)置定時器0的高8位初值// (0xDC00 是 16位定時器初值,用來生成10ms的定時周期)// 3. 開始計時TR0 = 1; // 啟動定時器0TF0 = 1; // 設(shè)置定時器0的溢出標(biāo)志位(啟動時應(yīng)清零,但此處設(shè)為1可能是為確保中斷服務(wù)函數(shù)能被觸發(fā))// 4. 打開定時器0中斷ET0 = 1; // 使能定時器0中斷// 5. 打開總中斷EAEA = 1; // 使能總中斷,允許所有中斷請求
}// 延時函數(shù)
void Delay300ms() //@11.0592MHz
{unsigned char i, j, k;i = 3; // 外循環(huán)計數(shù)j = 26; // 中循環(huán)計數(shù)k = 223; // 內(nèi)循環(huán)計數(shù)do{do{while (--k); // 內(nèi)循環(huán)延時} while (--j); // 中循環(huán)延時} while (--i); // 外循環(huán)延時
}// 主函數(shù)
void main()
{led = 1; // 初始化時將LED1點亮led1 = 0; // 初始化時將LED2熄滅Time0Init(); // 調(diào)用定時器0初始化函數(shù)while(1) {// 無限循環(huán)led1 = 0; // LED2熄滅Delay300ms(); // 延時300msled1 = 1; // LED2點亮Delay300ms(); // 延時300ms}
}// 定時器0中斷服務(wù)函數(shù)
void Time0Handler() interrupt 1
{cnt++; // 每次定時器0溢出時,計數(shù)器cnt增加1// 重新給定時器0初值,以保持定時周期TL0 = 0x00; // 重新加載定時器0的低8位初值TH0 = 0xDC; // 重新加載定時器0的高8位初值if(cnt == 30) { // 每30次溢出表示約1秒(10ms * 30 = 300ms)cnt = 0; // 重置計數(shù)器cnt,以開始新的計時周期led = !led; // 翻轉(zhuǎn)LED1的狀態(tài)}
}
當(dāng)然,下面是對你提供的代碼的詳細(xì)解釋,逐步解釋每一部分的功能和目的:
1. 頭文件和變量定義
#include "reg52.h"// 定義LED控制的位變量
sbit led = P3^6; // LED1 連接到P3端口的第6位
sbit led1 = P3^7; // LED2 連接到P3端口的第7位int cnt = 0; // 用于計數(shù)定時器溢出次數(shù)的變量
#include "reg52.h"
:包括一個頭文件,這個文件通常包含對51系列單片機(jī)寄存器的定義。sbit led = P3^6;
和sbit led1 = P3^7;
:將led
和led1
分別定義為 P3 端口的第6位和第7位,控制對應(yīng)的LED燈。sbit
是位變量的定義方式,用于操作單片機(jī)的特定位。int cnt = 0;
:定義一個全局變量cnt
,用來計數(shù)定時器溢出次數(shù)。
2. 定時器0初始化函數(shù)
void Time0Init()
{// 1. 配置定時器0工作模式為16位計時模式TMOD = 0x01; // 設(shè)置定時器0為16位定時器模式(模式1)// 2. 給定初值,設(shè)置一個10ms的定時周期TL0 = 0x00; // 設(shè)置定時器0的低8位初值TH0 = 0xDC; // 設(shè)置定時器0的高8位初值// (0xDC00 是 16位定時器初值,用來生成10ms的定時周期)// 3. 開始計時TR0 = 1; // 啟動定時器0TF0 = 1; // 設(shè)置定時器0的溢出標(biāo)志位(啟動時應(yīng)清零,但此處設(shè)為1可能是為確保中斷服務(wù)函數(shù)能被觸發(fā))// 4. 打開定時器0中斷ET0 = 1; // 使能定時器0中斷// 5. 打開總中斷EAEA = 1; // 使能總中斷,允許所有中斷請求
}
- 配置定時器模式:
-
TMOD = 0x01;
:設(shè)置定時器0為模式1(16位定時器模式)。TMOD
寄存器的低4位設(shè)置定時器0的模式,0x01
表示模式1,即16位計時器。
- 設(shè)置定時初值:
-
TL0 = 0x00;
和TH0 = 0xDC;
:設(shè)置定時器0的低8位(TL0)和高8位(TH0)的初值。這里的初值0xDC00
(16位)用來生成一個10ms的定時周期。具體的10ms周期計算基于單片機(jī)的時鐘頻率(11.0592 MHz)。
- 啟動定時器和中斷:
-
TR0 = 1;
:啟動定時器0,開始計時。TF0 = 1;
:設(shè)置溢出標(biāo)志位。這通常在定時器啟動時應(yīng)清除,但此處設(shè)為1可能是為了確保中斷服務(wù)函數(shù)能被觸發(fā)。ET0 = 1;
:使能定時器0的中斷,允許定時器溢出時觸發(fā)中斷。EA = 1;
:使能所有中斷,允許中斷請求的處理。
3. 延時函數(shù)
void Delay300ms() //@11.0592MHz
{unsigned char i, j, k;i = 3; // 外循環(huán)計數(shù)j = 26; // 中循環(huán)計數(shù)k = 223; // 內(nèi)循環(huán)計數(shù)do{do{while (--k); // 內(nèi)循環(huán)延時} while (--j); // 中循環(huán)延時} while (--i); // 外循環(huán)延時
}
- 延時函數(shù):
-
Delay300ms()
用來實現(xiàn)一個大約300ms的延時。- 使用嵌套的
do-while
循環(huán)來耗費時間。外層循環(huán)i
控制循環(huán)次數(shù),中層循環(huán)j
和內(nèi)層循環(huán)k
控制每次循環(huán)的延時。具體的延時時間取決于單片機(jī)的時鐘頻率(11.0592 MHz)。
4. 主函數(shù)
void main()
{led = 1; // 初始化時將LED1點亮led1 = 0; // 初始化時將LED2熄滅Time0Init(); // 調(diào)用定時器0初始化函數(shù)while(1) {// 無限循環(huán)led1 = 0; // LED2熄滅Delay300ms(); // 延時300msled1 = 1; // LED2點亮Delay300ms(); // 延時300ms}
}
- 主函數(shù):
-
- 初始化時將LED1點亮 (
led = 1;
),LED2熄滅 (led1 = 0;
)。 - 調(diào)用
Time0Init()
初始化定時器0。 - 進(jìn)入無限循環(huán),在其中交替點亮和熄滅LED2,每次切換后調(diào)用
Delay300ms()
實現(xiàn)300ms的延時。
- 初始化時將LED1點亮 (
5. 定時器0中斷服務(wù)函數(shù)
void Time0Handler() interrupt 1
{cnt++; // 每次定時器0溢出時,計數(shù)器cnt增加1// 重新給定時器0初值,以保持定時周期TL0 = 0x00; // 重新加載定時器0的低8位初值TH0 = 0xDC; // 重新加載定時器0的高8位初值if(cnt == 30) { // 每30次溢出表示約1秒(10ms * 30 = 300ms)cnt = 0; // 重置計數(shù)器cnt,以開始新的計時周期led = !led; // 翻轉(zhuǎn)LED1的狀態(tài)}
}
- 定時器0中斷服務(wù)函數(shù):
-
void Time0Handler() interrupt 1
:這是定時器0的中斷服務(wù)函數(shù)。interrupt 1
表示它處理定時器0的中斷請求。cnt++
:每次定時器0溢出時,計數(shù)器cnt
增加1。- 重新設(shè)置定時器0的初值 (
TL0
和TH0
),以保持定時器的計時周期。 - 當(dāng)
cnt
達(dá)到30時(每30次10ms溢出約300ms),重置cnt
并翻轉(zhuǎn)LED1的狀態(tài)。
二、PWM開發(fā)SG90
2.1 簡介
PWM,英文名Pulse Width Modulation,是脈沖寬度調(diào)制縮寫,它是通過對一系列脈沖的寬度進(jìn) 行調(diào)制,等效出所需要的波形(包含形狀以及幅值),對模擬信號電平進(jìn)行數(shù)字編碼,也就是說通過調(diào)節(jié)占空比的變化來調(diào)節(jié)信號、能量等的變化,占空比就是指在一個周期內(nèi),信號處于高電平的 時間占據(jù)整個信號周期的百分比,例如方波的占空比就是50%.
- 脈沖寬度調(diào)制
- 通過占空比編碼模擬信號
- 占空比 一個周期內(nèi),高電平占據(jù)時長的百分比
4毫秒為一個(波形)周期,其中3ms為低電平,1ms為高電平
什么是占空比 :一個周期內(nèi),高電平占據(jù)時長的百分比,為25%。
2.2 如何實現(xiàn)PWM信號輸出
1. 通過芯片內(nèi)部模塊輸出,一般觀察手冊或者芯片IO口都會標(biāo)明這個是否是PWM口
如下圖增強(qiáng)51,STC15w的
2. 如果沒有集成PWM功能,可以通過IO口軟件模擬,相對硬件PWM來說精準(zhǔn)度略差 ,怎么模擬;
搞個50HZ頻率的pwm;
2.3 控制舵機(jī)
1. 什么是舵機(jī)
如下圖所示,最便宜的舵機(jī)sg90,常用三根或者四根接線,黃色為PWM信號控制
用處:垃圾桶項目開蓋用、智能小車的全比例轉(zhuǎn)向、攝像頭云臺、機(jī)械臂等
常見的有0-90°、0-180°、0-360°
2. 怎么控制舵機(jī)
向黃色信號線“灌入”PWM信號。
PWM波的頻率不能太高,大約50HZ,即周期=1/頻率=1/50=0.02s,20ms左右
數(shù)據(jù):
0.5ms-------------0度; 2.5% 對應(yīng)函數(shù)中占空比為250
1.0ms------------45度; 5.0% 對應(yīng)函數(shù)中占空比為500
1.5ms------------90度; 7.5% 對應(yīng)函數(shù)中占空比為750
2.0ms-----------135度; 10.0% 對應(yīng)函數(shù)中占空比為1000
2.5ms-----------180度; 12.5% 對應(yīng)函數(shù)中占空比為1250
定時器需要定時20ms, 關(guān)心的單位0.5ms, 40個的0.5ms,初值0.5m cnt++
1s = 10ms * 100
20ms = 0.5ms * 40 \
- 編程實現(xiàn)
#include "reg52.h"sbit sg90_con = P1^1; // 定義一個名為 sg90_con 的引腳,與 P1 端口的第 1 位連接int jiaodu ; // 定義一個整數(shù)變量 jiaodu,用于表示角度
int cnt = 0; // 定義一個計數(shù)器變量 cnt,用于統(tǒng)計定時器溢出次數(shù)// 延時 2000 毫秒函數(shù)
void Delay2000ms() //@11.0592MHz
{unsigned char i, j, k;i = 15;j = 2;k = 235;do{do{while (--k); // 內(nèi)層循環(huán),k 減到 0} while (--j); // 中層循環(huán),j 減到 0} while (--i); // 外層循環(huán),i 減到 0
}// 定時器0初始化函數(shù)
void Time0Init()
{//1. 配置定時器0工作模式為16位計時TMOD = 0x01;//2. 設(shè)置初值,定時10msTL0=0x33;TH0=0xFE;//3. 開始計時TR0 = 1;TF0 = 0;//4. 打開定時器0中斷ET0 = 1;//5. 打開總中斷EAEA = 1;
}// 延時 300 毫秒函數(shù)
void Delay300ms() //@11.0592MHz
{unsigned char i, j, k;i = 3;j = 26;k = 223;do{do{while (--k); // 內(nèi)層循環(huán),k 減到 0} while (--j); // 中層循環(huán),j 減到 0} while (--i); // 外層循環(huán),i 減到 0
}void main()
{Delay300ms(); // 讓硬件穩(wěn)定一下Time0Init(); // 初始化定時器jiaodu = 1; // 初始角度是 0 度,高電平時間為 0.5mscnt = 0;sg90_con = 1; // 一開始從高電平開始// 每隔兩秒切換一次角度while(1){jiaodu = 3; // 90度,高電平時間為 1.5mscnt = 0;Delay2000ms();jiaodu = 1; // 0度,高電平時間為 0.5mscnt = 0;Delay2000ms();}
}// 定時器0中斷處理函數(shù)
void Time0Handler() interrupt 1
{cnt++; // 統(tǒng)計溢出次數(shù)// 重新設(shè)置定時器初值TL0=0x33;TH0=0xFE;// 控制PWM波if(cnt < jiaodu){ sg90_con = 1; // 設(shè)置高電平}else{sg90_con = 0; // 設(shè)置低電平} if(cnt == 40){ // 溢出40次,經(jīng)過20mscnt = 0; // 重新開始計數(shù)sg90_con = 1; // 開始新的PWM周期,從高電平開始}
}
詳細(xì)解釋
- 頭文件和變量定義:
-
#include "reg52.h"
:包含51單片機(jī)的頭文件。sbit sg90_con = P1^1;
:定義舵機(jī)控制引腳,連接到P1.1。int jiaodu;
和int cnt = 0;
:用于控制舵機(jī)角度和計數(shù)器的變量。
- 延時函數(shù):
-
Delay2000ms()
和Delay300ms()
:這兩個函數(shù)通過嵌套的空循環(huán)實現(xiàn)延時,用于產(chǎn)生約2000毫秒和300毫秒的延時。
- 定時器初始化函數(shù):
-
Time0Init()
:配置定時器0為16位計時模式,設(shè)置初始值,啟動定時器,并開啟定時器中斷和全局中斷。
- 主函數(shù):
-
main()
:主函數(shù)初始化定時器,并在一個無限循環(huán)中每隔2秒切換舵機(jī)的角度。jiaodu
設(shè)置為1表示0度,設(shè)置為3表示90度。
- 定時器中斷處理函數(shù):
-
Time0Handler()
:定時器0溢出時調(diào)用此函數(shù)。每次溢出時計數(shù)器cnt
增加,設(shè)置新的初始值,并根據(jù)cnt
和jiaodu
控制舵機(jī)信號引腳sg90_con
的高低電平,從而產(chǎn)生PWM波。
工作原理
- PWM信號生成:
-
- 中斷處理函數(shù)通過計數(shù)器
cnt
控制sg90_con
的高低電平時間,從而生成PWM信號。每個PWM周期為20ms,其中高電平時間由jiaodu
控制。
- 中斷處理函數(shù)通過計數(shù)器
- 舵機(jī)控制:
-
- 主函數(shù)通過設(shè)置
jiaodu
控制舵機(jī)角度,每隔2秒改變一次角度。通過Delay2000ms()
函數(shù)實現(xiàn)延時。
- 主函數(shù)通過設(shè)置
- 中斷處理:
-
- 每次定時器0溢出時,進(jìn)入中斷處理函數(shù)。計數(shù)器
cnt
增加,并根據(jù)cnt
的值控制PWM波的高低電平。當(dāng)cnt
達(dá)到40次溢出時(相當(dāng)于20ms),重置cnt
并開始新的PWM周期。
- 每次定時器0溢出時,進(jìn)入中斷處理函數(shù)。計數(shù)器
主函數(shù)和中斷一起執(zhí)行 ,如果cnt 大于角度的時候,是低電壓,中斷函數(shù)cnt繼續(xù)加加,直到加到等于40的時候,這個周期結(jié)束,進(jìn)入下一個周期,
三、 超聲波測距
3.1 簡介
型號:HC-SR04
接線參考:模塊除了兩個電源引腳外,還有TRIG,ECHO引腳,這兩個引腳分別接我們開發(fā)板的P1.5和
P1.6端口
超聲波測距模塊是用來測量距離的一種產(chǎn)品,通過發(fā)送和收超聲波,利用時間差和聲音傳播速度, 計算出模塊到前方障礙物的距離。
- 怎么讓它發(fā)送波
Trig ,給Trig端口至少10us的高電平
- 怎么知道它開始發(fā)了
Echo信號,由低電平跳轉(zhuǎn)到高電平,表示開始發(fā)送波
- 怎么知道接收了返回波
Echo,由高電平跳轉(zhuǎn)回低電平,表示波回來了
- 怎么算時間
Echo引腳維持高電平的時間!
波發(fā)出去的那一下,開始啟動定時器
波回來的拿一下,我們開始停止定時器,計算出中間經(jīng)過多少時間
- 怎么算距離
距離 = 速度 (340m/s)* 時間/2
3.2 超聲波的時序圖
3.3 超聲波測距代碼實現(xiàn)
#include "reg52.h"//距離小于10cm ,D5 亮,6滅,反之想反sbit D5 = P3^7;//根據(jù)原理圖(電路圖),設(shè)備變量led1指向P3組IO口的第7口
sbit D6 = P3^6;//根據(jù)原理圖(電路圖),設(shè)備變量led2指向P3組IO口的第6口sbit Trig = P1^5; // 發(fā)送聲波
sbit Echo = P1^6; // 接收聲波void Delay10us() //@11.0592MHz //聲波的持續(xù)時間 10微妙
{unsigned char i;i = 2;while (--i);
}
/*
十進(jìn)制2左移1位,變成20。相當(dāng)于乘以10
二禁止1左移1位,變成10(2)。相當(dāng)于乘以2,左移8位,乘以2的8次方=256;*/
void startHC() //Trig 輸出10ms的高電平 啟動發(fā)波
{Trig = 0; //發(fā)聲波 低電壓 Trig = 1; //發(fā)聲波 高電壓 維持10秒Delay10us();Trig = 0; //發(fā)聲波 低電壓 }//設(shè)置定時器0工作模式1,初始值設(shè)定0開始數(shù)數(shù),不著急啟動定時器void Time0Init() //不用關(guān)心初值 定時器
{TMOD &= 0xF0; //設(shè)置定時器模式TMOD |= 0x01; //設(shè)置定時器模式TH0 = 0; //16進(jìn)制計時TL0 = 0;// 設(shè)置定時器-0工作模塊1.初值為0,不著急啟動定時器、}
double get_distance()
{double time;//定時器數(shù)據(jù)清零,以便下一次測距TH1 = 0;TL1 = 0;startHC(); //調(diào)用超聲波函數(shù),啟動發(fā)波;while(Echo == 0); // 當(dāng)接收端由低電壓轉(zhuǎn)換至高電壓時,循環(huán)結(jié)束 表示聲波發(fā)出// 啟動定時器TR0 = 1; // 開始計時// 3、Echo,由高電平跳轉(zhuǎn)回低電平,表示波回來了 // 停止計時while(Echo == 1); // 當(dāng)接收端由高電壓轉(zhuǎn)換至低電壓時,循環(huán)結(jié)束,表示聲波返回TR0 = 0; // 停止計時//4. 計算出中間經(jīng)過多少時間 (公式)time = (TH0 * 256 + TL0)*1.085;//us為單位//5. 距離 = 速度 (340m/s)* 時間/2dis = time * 0.017;double dis; //返回一個數(shù)值
}
void openStatusLight() // 開啟狀態(tài)燈
{D5 = 0;D6 = 1;
}
void closeStatusLight() // 關(guān)閉狀態(tài)燈
{D5 = 1;D6 = 0;
}
void main()
{double dis; // 距離Time0Init(); //初始化定時器while(1){dis = get_distance(); // 計算距離// 判斷距離是否小于10cmif(dis < 10){ // 如果小于10cm openStatusLight(); // 調(diào)用開啟函數(shù)}else{ // 否則。其他情況closeStatusLight(); // 調(diào)用關(guān)閉函數(shù)}}
}
四、本節(jié)項目感應(yīng)開關(guān)蓋垃圾桶
4.1 項目概述
- 功能描述
-
-
- 檢測靠近時,垃圾桶自動開蓋并伴隨滴一聲,2秒后關(guān)蓋
- 發(fā)生震動時,垃圾桶自動開蓋并伴隨滴一聲,2秒后關(guān)蓋
- 按下按鍵時,垃圾桶自動開蓋并伴隨滴一聲,2秒后關(guān)蓋
-
- 硬件說明
-
-
- SG90舵機(jī),超聲波模塊,震動傳感器,蜂鳴器
-
- 接線說明
舵機(jī)控制口 P1.1;超聲波Trig接 P1.5 ,Echo接 P1.6 ;蜂鳴器接 P2.0 口; 震動傳感器接 P3.2`口(外部 中斷0)
4.2 編程實現(xiàn)
- 開發(fā)步驟:
1. 舵機(jī)和超聲波代碼整合
-
- 舵機(jī)用定時器0
- 超聲波用定時器1
- 實現(xiàn)物體靠近后,自動開蓋,2秒后關(guān)蓋
2. 查詢的方式添加按鍵控制
3. 查詢的方式添加震動控制
4. 使用外部中斷0配合震動控制
代碼:
#include "reg52.h"sbit sg90_con = P1^1;
sbit D5 = P3^7;//根據(jù)原理圖(電路圖),設(shè)備變量led1指向P3組IO口的第7口
sbit D6 = P3^6;//根據(jù)原理圖(電路圖),設(shè)備變量led2指向P3組IO口的第6口sbit Trig = P1^5;
sbit Echo = P1^6;int jiaodu ; // 舵機(jī)的角度
int cnt = 0; //爆表的累計次數(shù)void Delay2000ms() //@11.0592MHz // 延遲2秒
{unsigned char i, j, k;i = 15;j = 2;k = 235;do{do{while (--k);} while (--j);} while (--i);
}void Delay10us() //@11.0592MHz
{unsigned char i;i = 2;while (--i);
}void startHC() //Trig 輸出10ms的高電平 啟動發(fā)波
{Trig = 0;Trig = 1;Delay10us();Trig = 0;}
void Time0Init1() // 初始化定時器0,用于舵機(jī)控制
{//1. 配置定時器0工作模式位16位計時TMOD &= 0xF0; //設(shè)置定時器模式TMOD |= 0x01;//2. 給初值,定一個10ms出來TL0=0x33;TH0=0xFE;//3. 開始計時TR0 = 1;TF0 = 0;//4. 打開定時器0中斷ET0 = 1;//5. 打開總中斷EAEA = 1;
}void Time0Init2() // 初始化定時器1,用于超聲波控制
{TMOD &= 0x0F; //設(shè)置定時器模式TMOD |= 0x10; //設(shè)置定時器模式TH1 = 0;TL1 = 0;// 設(shè)置定時器-0工作模塊1.初值為0,不著急啟動定時器、}
void Delay300ms() //@11.0592MHz
{unsigned char i, j, k;i = 3;j = 26;k = 223;do{do{while (--k);} while (--j);} while (--i);
}void initSG90_0()
{jiaodu = 1; //初始角度是0度,0.5ms,溢出1就是0.5,高電平cnt = 0;sg90_con = 1; //一開始從高電平開始
}
double get_distance()
{double time;double dis;//定時器數(shù)據(jù)清零,以便下一次測距TH1 = 0;TL1 = 0;//1. Trig ,給Trig端口至少10us的高電平startHC();// 2、Echo信號,由低電平跳轉(zhuǎn)到高電平,表示開始發(fā)送波// 波發(fā)出去的那一下,開始啟動定時器while(Echo == 0);// 啟動定時器TR1 = 1;// 3、Echo,由高電平跳轉(zhuǎn)回低電平,表示波回來了 // 停止計時while(Echo == 1);TR1 = 0;//4. 計算出中間經(jīng)過多少時間time = (TH1 * 256 + TL1)*1.085;//us為單位//5. 距離 = 速度 (340m/s)* 時間/2dis = time * 0.017;return dis;
}
void openStatusLight() {D5 = 0; // 點亮D5D6 = 1; // 熄滅D6
}void closeStatusLight() {D5 = 1; // 熄滅D5D6 = 0; // 點亮D6
}void openlajitong() {jiaodu = 3; // 90度,1.5ms高電平cnt = 0;Delay2000ms();
}void closelajitong() {jiaodu = 1; // 0度,0.5ms高電平cnt = 0;Delay2000ms();
}
void main()
{double dis;Delay300ms(); // 讓硬件穩(wěn)定一下Time0Init1(); // 初始化定時器1Time0Init2(); // 初始化定時器2initSG90_0(); // 初始化舵機(jī)的角度// 每隔兩秒切換一次角度while(1){dis = get_distance(); // 計算距離if(dis < 10){ // 判斷距離 // 如果距離小于10 調(diào)用開啟函數(shù)openStatusLight(); //openlajitong();}else{ // 如果距離大于10 調(diào)用關(guān)閉函數(shù)closeStatusLight();closelajitong();}}
}
void Time0Handler() interrupt 1 // 定時器中斷
{cnt++; //統(tǒng)計爆表的次數(shù),cnt = 1的時候,報表了1//重新給初值TL0=0x33;TH0=0xFE;// 控制PWM波if(cnt < jiaodu){ sg90_con = 1 ;}else{sg90_con = 0 ;} if(cnt == 40){//爆表40次,經(jīng)過了20mscnt = 0; //當(dāng)100次表示1s,重新讓cnt從0開始,計算下一次的1ssg90_con = 1 ;}}
- 測距開關(guān)蓋添加按鍵開蓋功能
-
- 51單片機(jī)KY1 按鍵
- 遙控發(fā)送接收433M
-
-
- https://wenku.baidu.com/view/8fe8f444bed5b9f3f80f1c33.html
- 默認(rèn)低電平,按鍵之后是高電平。
- 遙控控制開關(guān)
-
#include "reg52.h"// 定義各個IO口
sbit D5 = P3^7; // LED D5連接到P3.7口
sbit D6 = P3^6; // LED D6連接到P3.6口
sbit SW1 = P2^1; // 開關(guān) SW1連接到P2.1口
sbit Trig = P1^5; // 超聲波傳感器Trig引腳連接到P1.5口
sbit Echo = P1^6; // 超聲波傳感器Echo引腳連接到P1.6口
sbit sg90_con = P1^1; // SG90舵機(jī)控制引腳連接到P1.1口
sbit D0_ON = P1^2; // LED D0_ON連接到P1.2口
sbit D1_OFF = P1^3; // LED D1_OFF連接到P1.3口int jiaodu ; // 舵機(jī)的角度
int cnt = 0; //爆表的累計次數(shù)void Delay2000ms() //@11.0592MHz // 延遲2秒
{unsigned char i, j, k;i = 15;j = 2;k = 235;do{do{while (--k);} while (--j);} while (--i);
}
void Delay10us() //@11.0592MHz
{unsigned char i;i = 2;while (--i);
}
void startHC() //Trig 輸出10ms的高電平 啟動發(fā)波
{Trig = 0;Trig = 1;Delay10us();Trig = 0;}
void Time0Init1() // 初始化定時器0,用于舵機(jī)控制
{//1. 配置定時器0工作模式位16位計時TMOD &= 0xF0; //設(shè)置定時器模式TMOD |= 0x01;//2. 給初值,定一個10ms出來TL0=0x33;TH0=0xFE;//3. 開始計時TR0 = 1;TF0 = 0;//4. 打開定時器0中斷ET0 = 1;//5. 打開總中斷EAEA = 1;
}
void Time0Init2() // 初始化定時器1,用于超聲波控制
{TMOD &= 0x0F; //設(shè)置定時器模式TMOD |= 0x10; //設(shè)置定時器模式TH1 = 0;TL1 = 0;// 設(shè)置定時器-0工作模塊1.初值為0,不著急啟動定時器、}
void Delay300ms() //@11.0592MHz
{unsigned char i, j, k;i = 3;j = 26;k = 223;do{do{while (--k);} while (--j);} while (--i);
}
void initSG90_0()
{jiaodu = 1; //初始角度是0度,0.5ms,溢出1就是0.5,高電平cnt = 0;sg90_con = 1; //一開始從高電平開始
}
double get_distance()
{double time;double dis;//定時器數(shù)據(jù)清零,以便下一次測距TH1 = 0;TL1 = 0;//1. Trig ,給Trig端口至少10us的高電平startHC();// 2、Echo信號,由低電平跳轉(zhuǎn)到高電平,表示開始發(fā)送波// 波發(fā)出去的那一下,開始啟動定時器while(Echo == 0);// 啟動定時器TR1 = 1;// 3、Echo,由高電平跳轉(zhuǎn)回低電平,表示波回來了 // 停止計時while(Echo == 1);TR1 = 0;//4. 計算出中間經(jīng)過多少時間time = (TH1 * 256 + TL1)*1.085;//us為單位//5. 距離 = 速度 (340m/s)* 時間/2dis = time * 0.017;return dis;
}
void openStatusLight() {D5 = 0; // 點亮D5D6 = 1; // 熄滅D6
}
void closeStatusLight() {D5 = 1; // 熄滅D5D6 = 0; // 點亮D6
}
void openlajitong() {jiaodu = 3; // 90度,1.5ms高電平cnt = 0;Delay2000ms();
}
void closelajitong() {jiaodu = 1; // 0度,0.5ms高電平cnt = 0;Delay2000ms();
}
void main()
{double dis;Delay300ms(); // 讓硬件穩(wěn)定一下Time0Init1(); // 初始化定時器1Time0Init2(); // 初始化定時器2initSG90_0(); // 初始化舵機(jī)的角度// 每隔兩秒切換一次角度while(1){dis = get_distance(); // 計算距離if(dis < 10 || SW1 == 0 || D0_ON == 1){openStatusLight();openDusbin();}else if (D1_OFF == 1){//關(guān)蓋,燈狀態(tài),D5滅closeStatusLight();closeDusbin();}else{closeStatusLight();closeDusbin();}}
}
void Time0Handler() interrupt 1 // 定時器中斷
{cnt++; //統(tǒng)計爆表的次數(shù),cnt = 1的時候,報表了1//重新給初值TL0=0x33;TH0=0xFE;// 控制PWM波if(cnt < jiaodu){ sg90_con = 1 ;}else{sg90_con = 0 ;} if(cnt == 40){//爆表40次,經(jīng)過了20mscnt = 0; //當(dāng)100次表示1s,重新讓cnt從0開始,計算下一次的1ssg90_con = 1 ;}
}
- 測距開關(guān)蓋添加振動傳感器開蓋功能
#include "reg52.h"// 定義各個IO口
sbit D5 = P3^7; // LED D5連接到P3.7口
sbit D6 = P3^6; // LED D6連接到P3.6口
sbit SW1 = P2^1; // 開關(guān) SW1連接到P2.1口
sbit Trig = P1^5; // 超聲波傳感器Trig引腳連接到P1.5口
sbit Echo = P1^6; // 超聲波傳感器Echo引腳連接到P1.6口
sbit sg90_con = P1^1; // SG90舵機(jī)控制引腳連接到P1.1口
sbit D0_ON = P1^2; // LED D0_ON連接到P1.2口
sbit D1_OFF = P1^3; // LED D1_OFF連接到P1.3口
sbit vibrate = P3^2; // 振動傳感器連接到P3.2口
sbit beep = P2^0;char jiaodu; // 舵機(jī)的角度變量
char jd_bak;
char cnt = 0;// 定時器溢出次數(shù)累計變量
char mark_vibrate = 0;// 延遲2秒
void Delay2000ms() //@11.0592MHz
{unsigned char i, j, k;i = 15;j = 2;k = 235;do {do {while (--k);} while (--j);} while (--i);
}// 延遲10微秒
void Delay10us() //@11.0592MHz
{unsigned char i;i = 2;while (--i);
}// Trig輸出10微秒的高電平以啟動超聲波傳感器
void startHC()
{Trig = 0;Trig = 1;Delay10us();Trig = 0;
}// 初始化定時器0,用于舵機(jī)控制
void Time0Init1()
{TMOD &= 0xF0; // 設(shè)置定時器模式TMOD |= 0x01; // 配置定時器0工作模式為16位計數(shù)TL0 = 0x33; // 定時器初值TH0 = 0xFE; // 定時器初值TR0 = 1; // 開始計時TF0 = 0; // 清除定時器溢出標(biāo)志ET0 = 1; // 打開定時器0中斷EA = 1; // 打開總中斷
}// 初始化定時器1,用于超聲波控制
void Time0Init2()
{TMOD &= 0x0F; // 設(shè)置定時器模式TMOD |= 0x10; // 配置定時器1工作模式為16位計數(shù)TH1 = 0; // 定時器1初值TL1 = 0; // 定時器1初值
}// 延遲300毫秒
void Delay300ms() //@11.0592MHz
{unsigned char i, j, k;i = 3;j = 26;k = 223;do {do {while (--k);} while (--j);} while (--i);
}// 初始化舵機(jī)角度為0度(0.5ms高電平)
void initSG90_0()
{jiaodu = 1; // 初始角度是0度cnt = 0;sg90_con = 1; // 一開始從高電平開始
}// 獲取距離
double get_distance()
{double time;double dis;TH1 = 0; // 定時器1數(shù)據(jù)清零TL1 = 0;startHC(); // 啟動超聲波傳感器while(Echo == 0); // 等待Echo信號變高TR1 = 1; // 啟動定時器1while(Echo == 1); // 等待Echo信號變低TR1 = 0; // 停止定時器1time = (TH1 * 256 + TL1) * 1.085; // 計算時間,單位為微秒dis = time * 0.017; // 計算距離,單位為厘米return dis;
}// 打開狀態(tài)燈
void openStatusLight() {D5 = 0; // 點亮D5D6 = 1; // 熄滅D6
}// 關(guān)閉狀態(tài)燈
void closeStatusLight() {D5 = 1; // 熄滅D5D6 = 0; // 點亮D6
}// 打開垃圾桶
void openlajitong() {char n;jiaodu = 3; //90度 1.5ms高電平//舵機(jī)開蓋if(jd_bak != jiaodu){cnt = 0;beep = 0;for(n=0;n<2;n++)Delay150ms();beep = 1;Delay2000ms();}jd_bak = jiaodu;}// 關(guān)閉垃圾桶
void closelajitong() {char n;//關(guān)蓋for(n=0;n<2;n++)Delay150ms();jd = 1; //0度jd_bak = jd;cnt = 0;Delay150ms();
}
void EX0_Init()
{//打開外部中斷EX0 = 1;//低電平觸發(fā)IT0 = 0;
}
// 主函數(shù)
void main()
{double dis;Delay300ms(); // 讓硬件穩(wěn)定一下Time0Init1(); // 初始化定時器0Time0Init2(); // 初始化定時器1EX0_Init();initSG90_0(); // 初始化舵機(jī)角度while(1) {dis = get_distance(); // 獲取距離if(dis < 10 || SW1 == 0 || D0_ON == 1 || mark_vibrate == 1 ) { // 距離小于10cm或SW1按下或D0_ON為高電平openStatusLight();openlajitong();} else if (D1_OFF == 1) { // D1_OFF為高電平closeStatusLight();closelajitong();} else { // 其他情況closeStatusLight();closelajitong();}}
}// 定時器中斷處理函數(shù)
void Time0Handler() interrupt 1
{cnt++; // 累計定時器溢出次數(shù)TL0 = 0x33; // 重新設(shè)置定時器初值TH0 = 0xFE;if(cnt < jiaodu) {sg90_con = 1; // 輸出高電平} else {sg90_con = 0; // 輸出低電平}if(cnt == 40) { // 溢出40次,經(jīng)過20mscnt = 0; // 重置計數(shù)sg90_con = 1;}}void Ex0_Handler() interrupt 0 // 振動傳感器輸出低電平 中斷
{mark_vibrate = 1;
}