定時器
1.簡介
C51中的定時器和計數(shù)器是同一個硬件電路支持的,通過寄存器配置不同,就可以將他當做定時器
或者計數(shù)器使用。
確切的說,定時器和計數(shù)器區(qū)別是致使他們背后的計數(shù)存儲器加1的信號不同。當配置為定時器使
用時,每經過1個機器周期,計數(shù)存儲器的值就加1。而當配置為計數(shù)器時,每來一個負跳變信號
(信號從P3.4 或者P3.5引腳輸入),就加1,以此達到計數(shù)的目的。
標準C51有2個定時器/計數(shù)器:T0和T1。他們的使用方法一致。C52相比C51多了一個T2
2.概念解讀
- 定時器和計數(shù)器,電路一樣
- 定時或者計數(shù)的本質就是讓單片機某個部件數(shù)數(shù)
- 當定時器用的時候,靠內部震蕩電路數(shù)數(shù)
- 當計數(shù)器用的時候,數(shù)外面的信號,讀取針腳的數(shù)據(jù)
3. 定時器怎么定時
定時器的本質原理: 每經過一個機器周期,就加1 :寄存器
- 什么是晶振?
晶振(晶體震蕩器),又稱數(shù)字電路的“心臟”,是各種電子產品里面必不可少的頻率元器件。數(shù)字電
路的所有工作都離不開時鐘,晶振的好壞、晶振電路設計的好壞,會影響到整個系統(tǒng)的穩(wěn)定性。
- 什么是時鐘周期
-時鐘周期也稱為振蕩周期,定義為時鐘頻率的倒數(shù)。時鐘周期是計算機中最基本的、最小的時間單
位。在一個時鐘周期內,CPU僅完成一個最基本的動作。時鐘周期是一個時間的量。更小的時鐘周 期就意味著更高的工作頻率
- 什么是機器周期
機器周期也稱為CPU周期。在計算機中,為了便于管理,常把一條指令的執(zhí)行過程劃分為若干個階
段(如取指、譯碼、執(zhí)行等),每一階段完成一個基本操作。完成一個基本操作所需要的時間稱為
機器周期。一般情況下,一個機器周期由若干個時鐘周期組成
- 加1經過了多少時間?
- 當晶振頻率是11.0592MHz的時候,等于11059.2KHz = 11059200Hz
機器周期 = 12 x 時鐘周期 =12 x (1/時鐘頻率) 秒 = 12 / 時鐘頻率 秒 = 12 / 11059200 秒 = 12
000 000 / 11059200 微秒 = 1.085 微秒
4. 定時器編程
定時器/計數(shù)器0和1的相關寄存器
配置TMOD,就是配置工作寄存器工作模式
定時器模式寄存器:TMOD來選擇定時器模式,選擇工作方式1,TMOD的bit0 bit1配置成0 1 :16
的定時器功能
配置TCON,就是配置定時器/計數(shù)器
- 怎么知道爆表
TCON寄存器的bit5(TF0)能表示爆表:當爆表的時候,硬件會修改bit5(TF0)位上面的數(shù)據(jù),改成1(置1),如果不用中斷,我們代碼清零
- 怎么開始計時
-TCON寄存器的bit4,通過編程讓這個位為1的時候,開始計時,相當于按下了鬧鐘
- 關于TH0/1和TL0/1寄存器 -
- 在哪里加1,最大計數(shù)時間,也就是爆表了能計算多長
在TH0/1和TL0/1寄存器中加1,默認是從0開始數(shù)數(shù),最多能數(shù)65536下,累計計時71ms
- 如何算出10ms定時器的初值
-就不讓他從0開始數(shù)數(shù),10ms需要數(shù)9216下,你讓他從65536-9126=56320(16進制表示為
0xDC00)開始數(shù)數(shù) 這樣TL0=0x00;TH0=0xDC
關于配置寄存器的一些置位操作
四個二進制數(shù)表示一位的16進制數(shù)
8421法進制的轉換(方便人類來看,對計算機底層來說,不關心進制010101010)
配寄存器推薦用按位操作,清零的時候,對應的需要清零的位與上0,不需要清零的位與上1置1的時候,需要置1的位置或1,不需要置一的位置或0
中斷
概念
在處理器中,中斷是一個過程,即CPU在正常執(zhí)行程序的過程中,遇到外部/內部的緊急事件需要處理,暫時中止當前程序的執(zhí)行,轉而去處理緊急的事物,待處理完畢后再返回被打斷的程序處繼續(xù)往下執(zhí)行。中斷在計算機多任務處理,尤其是即時系統(tǒng)尤為重要。比如uCOS,FreeRTOS等。
意義:
中斷能提高CPU的效率,同事能夠對突發(fā)事件做出實時處理。實現(xiàn)程序的并行化,實現(xiàn)嵌入式系統(tǒng)進程之間的切換。
中斷結構
中斷寄存器
由上面看出,假如CPU能響應定時器0中斷的條件:需要配置IE寄存器的bit1: ET0 bit7:EA,即
- ET0中斷允許要置一 ET0 = 1
- EA總中斷要置一 EA = 1
中斷優(yōu)先級
中斷函數(shù)的格式
如果使用C語言編程,中斷查詢次序號就是中斷號,例如:
void Int0_Routine(void) interrupt 0;
void Timer0_Rountine(void) interrupt 1;
void Int1_Routine(void) interrupt 2;
void Timer1_Rountine(void) interrupt 3;
void UART_Routine(void) interrupt 4;
void Timer2_Routine(void) interrupt 5;
void Int2_Routine(void) interrupt 6;
void Int3_Routine(void) interrupt 7;
中間名字可以自行改
/*******************************************************
*********定時器中斷控制LED每隔1秒亮滅一次********************
*****main中控制另外一個燈每個300ms亮滅一次,有點多線程的意思了***
*******************************************************/
#include "reg52.h"
sbit led = P3^6;
sbit led1 = P3^7;
int cnt = 0;
void Time0Init()
{
//1. 配置定時器0工作模式位16位計時
TMOD = 0x01;
//2. 給初值,定一個10ms出來
TL0=0x00;
TH0=0xDC;
//3. 開始計時
TR0 = 1;
TF0 = 0;
//4. 打開定時器0中斷
ET0 = 1;
//5. 打開總中斷EA
EA = 1;
}
void Delay300ms() //@11.0592MHz
{
unsigned char i, j, k;
i = 3;
j = 26;
k = 223;
do
{
do
{
while (--k);
} while (--j);
} while (--i);
}
void main()
{
led = 1;
Time0Init();
while(1){
led1 = 0;
Delay300ms();
led1 = 1;
Delay300ms();
}
}
void Time0Handler() interrupt 1
{
cnt++; //統(tǒng)計爆表的次數(shù)
//重新給初值
TL0=0x00;
TH0=0xDC;
if(cnt == 100){//爆表100次,經過了1s
cnt = 0; //當100次表示1s,重新讓cnt從0開始,計算下一次的1s
led = !led;//每經過1s,翻轉led的狀態(tài)
}
}
PWM開發(fā)SG90
簡介
PWM,英文名Pulse Width Modulation,是脈沖寬度調制縮寫,它是通過對一系列脈沖的寬度進
行調制,等效出所需要的波形(包含形狀以及幅值),對模擬信號電平進行數(shù)字編碼,也就是說通
過調節(jié)占空比的變化來調節(jié)信號、能量等的變化,占空比就是指在一個周期內,信號處于高電平的
時間占據(jù)整個信號周期的百分比,例如方波的占空比就是50%
- 通過占空比編碼模擬信號
- 占空比 一個周期內,高電平占據(jù)時長的百分比
如何實現(xiàn)PWM信號輸出
- 通過芯片內部模塊輸出,一般觀察手冊或者芯片IO口都會標明這個是否是PWM口
如下圖增強51,STC15w的CPU - 如果沒有集成PWM功能,可以通過IO口軟件模擬,相對硬件PWM來說精準度略差
控制舵機
什么是舵機?
如下圖所示,最便宜的舵機sg90,常用三根或者四根接線,黃色為PWM信號控制
用處:垃圾桶項目開蓋用、智能小車的全比例轉向、攝像頭云臺、機械臂等
常見的有0-90°、0-180°、0-360°
- 怎么控制舵機
向黃色信號線“灌入”PWM信號 - PWM波的頻率不能太高,大約50HZ,即周期=1/頻率=1/50=0.02s,20ms左右
數(shù)據(jù):
0.5ms-------------0度; 2.5% 對應函數(shù)中占空比為250
1.0ms------------45度; 5.0% 對應函數(shù)中占空比為500
1.5ms------------90度; 7.5% 對應函數(shù)中占空比為750
2.0ms-----------135度; 10.0% 對應函數(shù)中占空比為1000
2.5ms-----------180度; 12.5% 對應函數(shù)中占空比為1250
例如定時器需要定時20ms, 關心的單位0.5ms, 40個的0.5ms,初值0.5ms cnt++
20ms = 0.5ms * 40
3.編程實現(xiàn)
/*******************************************************
*********舵機黃色信號線接P1.1口,每隔2秒從0度到135度切換********
*************注意:初值不要算錯,修改位置兩個地方**************
*******************************************************/
#include <stdio.h>
#include <reg51.h>
#include<intrins.h>
sbit sg90_com = P1^1;
int cnt = 0;
int jd = 0;
void Timer0Init(void) //500微秒@11.0592MHz
{
AUXR &= 0x7F; //定時器時鐘12T模式
TMOD &= 0xF0; //設置定時器模式
TMOD |= 0x01; //設置定時器模式
TL0 = 0x33; //設置定時初值
TH0 = 0xFE; //設置定時初值
TF0 = 0; //清除TF0標志
TR0 = 1; //定時器0開始計時
EA = 1; //打開總中斷 1開 0關
ET0 = 1; //打開定時器0中斷
}
void Delay2000ms() //@11.0592MHz
{
unsigned char i, j, k;
_nop_();
i = 15;
j = 2;
k = 235;
do
{
do
{
while (--k);
} while (--j);
} while (--i);
}
void Delay300ms() //@11.0592MHz
{
unsigned char i, j, k;
_nop_();
i = 3;
j = 26;
k = 223;
do
{
do
{
while (--k);
} while (--j);
} while (--i);
}
int main()
{
jd = 1;
sg90_com = 0;
Delay300ms();
Timer0Init(); //每爆表一次,就觸發(fā)中斷,硬件調用中斷函數(shù)
while(1){
jd = 3;
cnt = 0;
Delay2000ms();
jd = 4;
cnt = 0;
Delay2000ms();
jd = 1;
Delay2000ms();
}
return 0;
}
void Timer0_Rountine() interrupt 1
{
cnt++;
TL0 = 0x33; //設置定時初值
TH0 = 0xFE; //設置定時初值
if(cnt < jd){
sg90_com = 1;
}else {
sg90_com = 0;
}
if(cnt == 40){
cnt = 0;
sg90_com = 1;
}
}
超聲波測距
簡介
超聲波測距模塊是用來測量距離的一種產品,通過發(fā)送和收超聲波,利用時間差和聲音傳播速度, 計算出模塊到前方障礙物的距離。
型號:HC-SR04
接線參考:模塊除了兩個電源引腳外,還有TRIG,ECHO引腳,這兩個引腳分別接我們開發(fā)板的P1.5和P1.6端口
- 怎么讓它發(fā)送波
Trig ,給Trig端口至少10us的高電平
- 怎么知道它開始發(fā)了
Echo信號,由低電平跳轉到高電平,表示開始發(fā)送波 怎么知道接收了返回波
Echo,由高電平跳轉回低電平,表示波回來了
- 怎么算時間
Echo引腳維持高電平的時間! 波發(fā)出去的那一下,開始啟動定時器 波回來的拿一下,我們開始停止定時器,計算出中間經過多少時間
- 怎么算距離
距離 = 速度 (340m/s)* 時間/2
時序圖
文章來源:http://www.zghlxwxcb.cn/news/detail-400291.html
#include <stdio.h>
#include <reg51.h>
#include<intrins.h>
//距離小于10cm,beep響,反之相反現(xiàn)象
sbit Trig = P1^5;
sbit Echo = P1^6;
sbit Beep = P1^2;
void Delay200us() //@11.0592MHz
{
unsigned char i;
_nop_();
i = 89;
while (--i);
}
void Delay10us() //@11.0592MHz
{
unsigned char i;
i = 2;
while (--i);
}
void Timer0Init(void) //0微秒@11.0592MHz
{
AUXR &= 0x7F; //定時器時鐘12T模式
TMOD &= 0xF0; //設置定時器模式
TMOD |= 0x01; //設置定時器模式
TL0 = 0x00; //設置定時初值
TH0 = 0x00; //設置定時初值
TF0 = 0; //清除TF0標志
}
void Delay1000us() //@11.0592MHz
{
unsigned char i, j;
_nop_();
i = 2;
j = 199;
do
{
while (--j);
} while (--i);
}
void Trigger_signal() //觸發(fā)信號,讓模塊內部發(fā)波
{
Trig = 0;
Delay200us();
Trig = 1;
Delay10us();
Trig = 0;
}
int main()
{
double time;
double dis;
Beep = 1;
Timer0Init();
while(1){
Trigger_signal();
while(Echo == 0);
TR0 = 1; //定時器0開始計時
while(Echo == 1);
TR0 = 0; //定時器0停止計時
time = (TH0*256 + TL0)*1.085;//單位為us
dis = time*0.017; //這里換算為厘米了
if(dis < 10){
Beep = 0;
Delay1000us();
}else {
Beep = 1;
}
TL0 = 0x00; //設置定時初值
TH0 = 0x00; //設置定時初值
}
return 0;
}
/*十進制2左移1位,變成20。相當于乘以10
二禁止1左移1位,變成10(2)。相當于乘以2,左移8位,乘以2的8次方=256;*/
開蓋垃圾桶
功能描述
檢測靠近時,垃圾桶自動開蓋并伴隨滴一聲,2秒后關蓋
發(fā)生震動時,垃圾桶自動開蓋并伴隨滴一聲,2秒后關蓋
硬件說明
SG90舵機,超聲波模塊,震動傳感器,蜂鳴器
接線說明
舵機控制口 P1.1;
超聲波Trig接 P1.5 ,Echo接 P1.6 ;
蜂鳴器接 P1.2 口;
震動傳感器接 P3.2`口(外部中斷0)
源碼文章來源地址http://www.zghlxwxcb.cn/news/detail-400291.html
#include <stdio.h>
#include <reg51.h>
#include<intrins.h>
sbit Trig = P1^5;
sbit Echo = P1^6;
sbit Vibrate = P3^2; //震動傳感器,有震動do口發(fā)送一個低電平
sbit sg90_com = P1^1;//舵機
sbit Beep = P1^2;//蜂鳴器
int cnt = 0;
int jd = 0;
int mark_vibrate = 0; //震動標志位
int jd_mark;
void Delay200us() //@11.0592MHz
{
unsigned char i;
_nop_();
i = 89;
while (--i);
}
void Delay10us() //@11.0592MHz
{
unsigned char i;
i = 2;
while (--i);
}
void Delay200ms() //@11.0592MHz
{
unsigned char i, j, k;
_nop_();
i = 2;
j = 103;
k = 147;
do
{
do
{
while (--k);
} while (--j);
} while (--i);
}
void Delay2000ms() //@11.0592MHz
{
unsigned char i, j, k;
_nop_();
i = 15;
j = 2;
k = 235;
do
{
do
{
while (--k);
} while (--j);
} while (--i);
}
void Timer1Init(void) //0微秒@11.0592MHz
{
AUXR &= 0xBF; //定時器時鐘12T模式
TMOD &= 0x0F; //設置定時器模式
TMOD |= 0x10; //設置定時器模式
TL1 = 0x00; //設置定時初值
TH1 = 0x00; //設置定時初值
TF1 = 0; //清除TF0標志
}
void Timer0Init(void) //500微秒@11.0592MHz
{
AUXR &= 0x7F; //定時器時鐘12T模式
TMOD &= 0xF0; //設置定時器模式
TMOD |= 0x01; //設置定時器模式
TL0 = 0x33; //設置定時初值
TH0 = 0xFE; //設置定時初值
TF0 = 0; //清除TF0標志
TR0 = 1; //定時器0開始計時
EA = 1; //打開總中斷 1開 0關
ET0 = 1; //打開定時器0中斷
}
void EX0_Init()
{
EX0 = 1;//打開外部中斷,1為允許
IT0 = 0;//設置外部中斷的觸發(fā)模式,下降沿或者低電平,0為低電平,1下降沿
}
void Beep_response()
{
Beep = 0;
Delay200ms();
Beep = 1;
}
void Init_SG90_0()
{
jd = 1;
cnt = 0;
sg90_com = 1;
}
void open_SG_90_90()
{
jd = 3;
if(jd_mark != jd){
cnt = 0;
Beep_response();
Delay2000ms();
}
jd_mark = jd;
}
void close_SG_90_0()
{
jd = 1;
cnt = 0;
jd_mark = jd;
Delay200ms();
}
void Trigger_signal() //觸發(fā)信號,讓模塊內部發(fā)波
{
Trig = 0;
Delay200us();
Trig = 1;
Delay10us();
Trig = 0;
}
double GetDistance()
{
double time;
double dis;
TL1 = 0x00; //設置定時初值
TH1 = 0x00; //設置定時初值
Trigger_signal();
while(Echo == 0);
TR1 = 1; //定時器1開始計時
while(Echo == 1);
TR1 = 0; //定時器0停止計時
time = (TH1*256 + TL1)*1.085;//單位為us
dis = time*0.017; //這里換算為厘米了
return dis;
}
int main()
{
double Distance;
Timer1Init();
Timer0Init();
EX0_Init();
Beep = 1;
Init_SG90_0();
while(1){
Distance = GetDistance();
if(Distance < 10 || mark_vibrate == 1){
open_SG_90_90();
mark_vibrate = 0;
} else{
close_SG_90_0();
}
}
return 0;
}
void Timer0_Handle() interrupt 1
{
cnt++;
TL0 = 0x33; //設置定時初值
TH0 = 0xFE; //設置定時初值
if(cnt < jd){
sg90_com = 1;
}else {
sg90_com = 0;
}
if(cnt == 40){
cnt = 0;
sg90_com = 1;
}
}
void EX0_Handle() interrupt 0
{
mark_vibrate = 1;
}
/*十進制2左移1位,變成20。相當于乘以10
二禁止1左移1位,變成10(2)。相當于乘以2,左移8位,乘以2的8次方=256;*/
到了這里,關于C51學習———定時器中斷的文章就介紹完了。如果您還想了解更多內容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網(wǎng)!