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