新聞中心

EEPW首頁(yè) > 嵌入式系統(tǒng) > 設(shè)計(jì)應(yīng)用 > 基于STC15L104E單片機(jī)模擬PWM調(diào)光小夜燈

基于STC15L104E單片機(jī)模擬PWM調(diào)光小夜燈

作者: 時(shí)間:2016-11-25 來源:網(wǎng)絡(luò) 收藏
鑒于宿舍晚上會(huì)被宿管滅燈,所以制作了一個(gè)小臺(tái)燈在關(guān)燈后"窺探"用,但是舍友陳某反應(yīng)光線太強(qiáng)影響其睡眠,所以決心做個(gè)可以調(diào)光的LED小夜燈,窺探自己的隱私,讓別人睡覺去吧...
搜索自己的原件庫(kù),發(fā)現(xiàn)上半年買的STC15L104E一直沒用,所以打算就用單片機(jī)來控制了,當(dāng)然,如果用模擬電路,可能幾個(gè)元件就可以完成了,但是,模擬對(duì)我來說更難設(shè)計(jì),所以,,,好吧,廢話多了下面貼電路:

其實(shí)也沒什么,純粹是IO操作,兩個(gè)開光是調(diào)光用,AMS117是降壓用,AMP4953就相當(dāng)于開關(guān),后面的電感電容電路是防止出現(xiàn)閃爍的,額,如果有問題的話可以貼出來.
下面介紹模擬PWM操作,畢竟不是硬件的PWM而且要顧及程序長(zhǎng)度,所以模擬出來的PWM頻率600HZ,不過用在LED上應(yīng)該足夠了.
設(shè)PWM基數(shù)為PWM_NUM,PWM比較輸出值為PWM_CMP.
主要思路就是利用單片機(jī)內(nèi)部計(jì)時(shí)器按一定周期中斷,然后在中斷服務(wù)程序里令PWM_NUM加一,判斷是否小于PWM_CMP比較值,如果小于,則IO輸出高,否則輸出低,這樣,我們就可以通過修改PWM_CMP的值來調(diào)節(jié)IO輸出脈寬,達(dá)到模擬PWM的效果了.PWM周期=計(jì)時(shí)器中斷周期/PWM_NUM;
好吧,我的文字表達(dá)能力不好,貼張圖來說明可能比較好:

如圖,假設(shè)PWM_CMP=6,PWM_NUM=16,也就是,PWM_NUM達(dá)到16后清零.每個(gè)計(jì)時(shí)器中斷周期PWM_NUM自動(dòng)加一,判斷是否小于PWM_CMP,是則輸出高電平,否則輸出低電平,所以,如圖所示,當(dāng)PWM_NUM累加到6前,輸出電平是一直是高的,知道PWM_NUM累加到6后,輸出就拉低了,當(dāng)PWM_NUM達(dá)到16后,清零,這時(shí)PWM_NUM又小于PWM_CMP,故PWM輸出又為高了,周而復(fù)始,就達(dá)到模擬PWM的效果了,PWM周期就等于PWM_NUM重裝周期.
當(dāng)然值得注意的是,因?yàn)榕袛嗍窃谥袛喾?wù)程序中執(zhí)行,所以計(jì)時(shí)器周期不能太短.
好吧,貼整個(gè)完整的程序出來,它的功能我先說明一下.
按下key1變亮,按下key2變暗,長(zhǎng)按則連續(xù)調(diào)節(jié),兩個(gè)鍵一起按下改變顯示方式,分別有四個(gè)模式,單個(gè)分別亮,兩個(gè)亮,兩個(gè)都不亮.每次改變亮度和模式都寫入單片機(jī)EEPROM,開機(jī)讀取EEPROM,這樣便能開機(jī)保持上次關(guān)機(jī)的狀態(tài),不用每次打開都要調(diào)節(jié)了.說到這我就要吐槽了,這STC15系列A版外部中斷吶,連掉電喚醒都實(shí)現(xiàn)不了,那幾個(gè)外部中斷口都是擺設(shè)的.所以原本打算使用掉電模式作為關(guān)機(jī)狀態(tài)的,但是喚醒不了(除了復(fù)位鍵),所以只好用外部硬件開關(guān)關(guān)機(jī)了....
廢話不多說,貼程序,程序有標(biāo)注,看不明白或有問題指教的貼出來,虛心接受.
#include "reg52.h"
#include "intrins.h"
#define ON 0 //LED是低電平有效
#define OFF 1
#define PWM_TIME 200 //計(jì)時(shí)器計(jì)數(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為長(zhǎng)效,up為下降沿
unsigned char pwm_cmp=1; //PWM比較值
unsigned char pwm_num=0; //PWM計(jì)數(shù)值
unsigned char led_model=0; //LED模式
unsigned char pwm_delay=0; //延時(shí)暫存
unsigned char cmp_temp;
//led_cmp的暫存,用于運(yùn)算是否寫入EEPROM
//計(jì)時(shí)器0初始化
void timer_init()
{
TMOD=0x00; //模式0,16位自動(dòng)裝載模式
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();
}
上一頁(yè) 1 2 下一頁(yè)

評(píng)論


技術(shù)專區(qū)

關(guān)閉