新聞中心

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

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

        作者: 時間:2016-11-25 來源:網(wǎng)絡(luò) 收藏
        鑒于宿舍晚上會被宿管滅燈,所以制作了一個小臺燈在關(guān)燈后"窺探"用,但是舍友陳某反應(yīng)光線太強(qiáng)影響其睡眠,所以決心做個可以調(diào)光的LED小夜燈,窺探自己的隱私,讓別人睡覺去吧...
        搜索自己的原件庫,發(fā)現(xiàn)上半年買的STC15L104E一直沒用,所以打算就用單片機(jī)來控制了,當(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.
        主要思路就是利用單片機(jī)內(nèi)部計時器按一定周期中斷,然后在中斷服務(wù)程序里令PWM_NUM加一,判斷是否小于PWM_CMP比較值,如果小于,則IO輸出高,否則輸出低,這樣,我們就可以通過修改PWM_CMP的值來調(diào)節(jié)IO輸出脈寬,達(dá)到模擬PWM的效果了.PWM周期=計時器中斷周期/PWM_NUM;
        好吧,我的文字表達(dá)能力不好,貼張圖來說明可能比較好:

        如圖,假設(shè)PWM_CMP=6,PWM_NUM=16,也就是,PWM_NUM達(dá)到16后清零.每個計時器中斷周期PWM_NUM自動加一,判斷是否小于PWM_CMP,是則輸出高電平,否則輸出低電平,所以,如圖所示,當(dāng)PWM_NUM累加到6前,輸出電平是一直是高的,知道PWM_NUM累加到6后,輸出就拉低了,當(dāng)PWM_NUM達(dá)到16后,清零,這時PWM_NUM又小于PWM_CMP,故PWM輸出又為高了,周而復(fù)始,就達(dá)到模擬PWM的效果了,PWM周期就等于PWM_NUM重裝周期.
        當(dāng)然值得注意的是,因為判斷是在中斷服務(wù)程序中執(zhí)行,所以計時器周期不能太短.
        好吧,貼整個完整的程序出來,它的功能我先說明一下.
        按下key1變亮,按下key2變暗,長按則連續(xù)調(diào)節(jié),兩個鍵一起按下改變顯示方式,分別有四個模式,單個分別亮,兩個亮,兩個都不亮.每次改變亮度和模式都寫入單片機(jī)EEPROM,開機(jī)讀取EEPROM,這樣便能開機(jī)保持上次關(guān)機(jī)的狀態(tài),不用每次打開都要調(diào)節(jié)了.說到這我就要吐槽了,這STC15系列A版外部中斷吶,連掉電喚醒都實現(xiàn)不了,那幾個外部中斷口都是擺設(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 //計時器計數(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();
        }
        上一頁 1 2 下一頁

        評論


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

        關(guān)閉
        主站蜘蛛池模板: 翼城县| 临漳县| 巴林右旗| 团风县| 太湖县| 揭阳市| 历史| 桂东县| 龙陵县| 富源县| 南溪县| 陕西省| 太白县| 钟祥市| 万宁市| 岳阳市| 衡东县| 满洲里市| 深水埗区| 长葛市| 蓬莱市| 平安县| 双流县| 河曲县| 镇远县| 东阿县| 若羌县| 大竹县| 湟中县| 响水县| 南康市| 晋宁县| 沾益县| 石嘴山市| 聊城市| 莒南县| 亳州市| 广德县| 江北区| 焦作市| 凤台县|