基于STC15L104E單片機模擬PWM調(diào)光小夜燈
搜索自己的原件庫,發(fā)現(xiàn)上半年買的STC15L104E一直沒用,所以打算就用單片機來控制了,當(dāng)然,如果用模擬電路,可能幾個元件就可以完成了,但是,模擬對我來說更難設(shè)計,所以,,,好吧,廢話多了下面貼電路:
其實也沒什么,純粹是IO操作,兩個開光是調(diào)光用,AMS117是降壓用,AMP4953就相當(dāng)于開關(guān),后面的電感電容電路是防止出現(xiàn)閃爍的,額,如果有問題的話可以貼出來.
下面介紹模擬PWM操作,畢竟不是硬件的PWM而且要顧及程序長度,所以模擬出來的PWM頻率600HZ,不過用在LED上應(yīng)該足夠了.
設(shè)PWM基數(shù)為PWM_NUM,PWM比較輸出值為PWM_CMP.
主要思路就是利用單片機內(nèi)部計時器按一定周期中斷,然后在中斷服務(wù)程序里令PWM_NUM加一,判斷是否小于PWM_CMP比較值,如果小于,則IO輸出高,否則輸出低,這樣,我們就可以通過修改PWM_CMP的值來調(diào)節(jié)IO輸出脈寬,達到模擬PWM的效果了.PWM周期=計時器中斷周期/PWM_NUM;
好吧,我的文字表達能力不好,貼張圖來說明可能比較好:
如圖,假設(shè)PWM_CMP=6,PWM_NUM=16,也就是,PWM_NUM達到16后清零.每個計時器中斷周期PWM_NUM自動加一,判斷是否小于PWM_CMP,是則輸出高電平,否則輸出低電平,所以,如圖所示,當(dāng)PWM_NUM累加到6前,輸出電平是一直是高的,知道PWM_NUM累加到6后,輸出就拉低了,當(dāng)PWM_NUM達到16后,清零,這時PWM_NUM又小于PWM_CMP,故PWM輸出又為高了,周而復(fù)始,就達到模擬PWM的效果了,PWM周期就等于PWM_NUM重裝周期.
當(dāng)然值得注意的是,因為判斷是在中斷服務(wù)程序中執(zhí)行,所以計時器周期不能太短.
好吧,貼整個完整的程序出來,它的功能我先說明一下.
按下key1變亮,按下key2變暗,長按則連續(xù)調(diào)節(jié),兩個鍵一起按下改變顯示方式,分別有四個模式,單個分別亮,兩個亮,兩個都不亮.每次改變亮度和模式都寫入單片機EEPROM,開機讀取EEPROM,這樣便能開機保持上次關(guān)機的狀態(tài),不用每次打開都要調(diào)節(jié)了.說到這我就要吐槽了,這STC15系列A版外部中斷吶,連掉電喚醒都實現(xiàn)不了,那幾個外部中斷口都是擺設(shè)的.所以原本打算使用掉電模式作為關(guān)機狀態(tài)的,但是喚醒不了(除了復(fù)位鍵),所以只好用外部硬件開關(guān)關(guān)機了....
廢話不多說,貼程序,程序有標(biāo)注,看不明白或有問題指教的貼出來,虛心接受.
#include "reg52.h"
#include "intrins.h"
#define ON 0 //LED是低電平有效
#define OFF 1
#define PWM_TIME 200 //計時器計數(shù)值
#define MODEL_ADDR 0x0000 //EEPEOM地址
#define PWM_CMP_ADDR 0x0200
sfr AUXR =0x8e;
sfr P3M1 =0xb1;
sfr P3M0 =0xb2;
sfr IAP_DATA =0xc2;
sfr IAP_ADDRH=0xc3;
sfr IAP_ADDRL=0xc4;
sfr IAP_CMD =0xc5;
sfr IAP_TRIG =0xc6;
sfr IAP_CONTR=0xc7;
sbit KEY1=P3^0;
sbit KEY2=P3^1;
sbit LED1=P3^2;
sbit LED2=P3^3;
unsigned char key_down,key_cont,key_up;
//donw為上升沿,cont為長效,up為下降沿
unsigned char pwm_cmp=1; //PWM比較值
unsigned char pwm_num=0; //PWM計數(shù)值
unsigned char led_model=0; //LED模式
unsigned char pwm_delay=0; //延時暫存
unsigned char cmp_temp;
//led_cmp的暫存,用于運算是否寫入EEPROM
//計時器0初始化
void timer_init()
{
TMOD=0x00; //模式0,16位自動裝載模式
EA=1;
ET0=1;
TR0=1;
AUXR|=0x80; //1T模式
TL0=65536-PWM_TIME;
TH0=(65536-PWM_TIME)>>8;
}
//EEPROM讀寫后防止誤操作
void eeprom_dle()
{
IAP_CONTR=0;
IAP_CMD =0;
IAP_TRIG =0;
IAP_ADDRH=0;
IAP_ADDRL=0;
}
//擦除EEPROM扇區(qū)
void eeprom_erase(unsigned int addr)
{
IAP_CONTR=0x83;
IAP_CMD =0x03;
IAP_ADDRL=addr;
IAP_ADDRH=addr>>8;
IAP_TRIG =0x5a;
IAP_TRIG =0xa5;
_nop_();_nop_();_nop_();
//eeprom_dle();
關(guān)鍵詞:
STC15L104E單片機模擬PWM調(diào)光小夜
評論