1. 程式人生 > >51微控制器使用定時器中斷模擬PWM控制埠電壓

51微控制器使用定時器中斷模擬PWM控制埠電壓

  最近應實驗室需求寫一篇51微控制器產生PWM的文章供參考.

  微控制器晶片STC89C52,晶振12MHz,編譯環境Keil5.

  分析:若使微控制器埠為高電平, 則微控制器輸出電壓為恆值5V. 反之低電平輸出電壓為0V. 但是我們如果在週期為T的時間內使微控制器高電平出現t1秒, 低電平出現t2秒, 那麼在週期內, 高電平出現的時間為, 低電平時間為. 由於週期T的時間極短, 那麼在連續的時間t內, 相應埠輸出電壓為.

  實驗使用定時器0, 定時器0由兩個暫存器進行控制,分別為定時器/計數器工作方式暫存器TMOD,  定時器/計數器控制暫存器TCON.

TMOD是一個八位暫存器,如下:

,

TMOD暫存器高4位控制定時器1低四位控制定時器0: 

1. GATE位為門控制位, 選擇是否讓外部中斷控制定時器,此位一般置0, 即不讓外部中斷控制定時器.

2. C/T位為選擇定時器/計數器模式選擇, 此實驗中使用定時器模擬時間週期T,  所以置0選擇定時器模式.

3. M1和M0為定時器工作方式選擇位, 控制方式如下:

 

一般在週期短,要求定時精度高的情況下選擇方式2,但此實驗選擇方式1的16位計數器.

16位計數器的意思是週期T的長度不超過機器週期的倍,在12MHz晶振的作用下,機器週期為1us,故週期T不超過65536us.

 

TCON控制暫存器暫存器的高4位用於控制定時/計數器的啟動和中斷申請, 低4位用於控制外部中斷(此處不介紹).

  1. TF1:定時器1溢位中斷請求標誌位。定時器1計數溢位時由硬體自動置TF1為1。CPU響應中斷後TF1由硬體自動清0。定時器1工作時,CPU可隨時查詢TF1的狀態。所以,TF1可用作查詢測試的標誌。TF1也可以用軟體置1或清0,同硬體置1或清0的效果一樣。
  2. TR1:定時器1執行控制位。TR1置1時,定時器1開始工作;TR1置0時,定時器1停止工作。TR1由軟體置1或清0。所以,用軟體可控制定時/計數器的啟動與停止。
  3. TF0:定時器0溢位中斷請求標誌位,其功能與TF1類同。
  4. TR0:定時器0執行控制位,其功能與TR1類同。

 

定時器工作方式: (以工作方式1為模板)

  方式1為16位計數,由定時器的低8位 和 定時器的高8位組成。定時器的低8位溢位時向定時器的高8位進位+1,定時器的高8位溢位時,置位TCON中的TF0標誌,然後定時器高8為與低8位請零, 並向CPU發出中斷請求.

TL0->TH0->TF0->產生中斷(TL0/TH0/TF0清零)

下面介紹個定時器0實現PWM控制LED亮度的程式碼:

利用定時器0產生週期為100*100us, 電平持續時間為100*20us的方波. 

方波如下:

因為這裡我們是產生週期為10ms(100Hz)的PWM,所以可設定中斷的時間基準為100us, 中斷100次即為10ms. 並在中斷裡設定時間變數為n.

 1、當n>20時(0< n <T),讓單片相應的埠輸出低電平;(LED燈亮)

 2、當20<n<=T時,讓單片相應的埠輸出高電平,此時PWM中低電平的佔空比就為%n。

 3、當n=100時,表明週期T已滿,n清零;

 下面程式產生20%佔空比的pwm:

#include <reg52.h>

#define T 100     //定義時間進度為100個機器週期,即100us

sbit LED=P1^0;

unsigned int pwm_num=20;     //PWM中低電平出現的時間t2

void main()
{
	TMOD = 0x01;            //選擇為定時器0 工作方式1
	TH0=(65536-T)/256;      //定時器高八位
	TL0=(65536-T)%256;      //定時器低八位
	TR0=1;                  //開啟定時器
	ET0=1;                  //開啟定時器1的中斷使能
	EA=1;                   //開啟總中斷
	while (1);              //等待中斷髮生
}

void Timer1() interrupt 1   //中斷1(定時器0專用中斷通道)
{
	static unsigned char n; //靜態變數n  可以看成每100us加一次的時間t
	TH0=(65536-T)/256;      //重灌定時器的值
	TL0=(65536-T)%256;
	n++;                    //表明週期T已到100*100us
	if (n==100)
		n=0;
	LED = (n<=pwm_num) ? 0 : 1;   //判斷時間是否超過t2
}

最終實驗現象為:LED燈亮度變低.

 

若覺文章有助於你,可以在下面留言點贊哦 (<_>)!

如覺文章何處不明也可留言.

若轉載本文請註明出處.