久久久久久久999_99精品久久精品一区二区爱城_成人欧美一区二区三区在线播放_国产精品日本一区二区不卡视频_国产午夜视频_欧美精品在线观看免费

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 10491|回復: 42
打印 上一主題 下一主題
收起左側

DIY全彩燈隨機顏色漸變程序 1677萬色輸出 蜂鳴器放歌 2合1 可同時工作

  [復制鏈接]
跳轉到指定樓層
樓主
ID:57657 發表于 2016-7-7 11:44 | 只看該作者 回帖獎勵 |倒序瀏覽 |閱讀模式
蜂鳴器放歌程序用到兩個定時器,分別用于精準控制頻率和時間。
賀卡音樂芯片唯一的制作方法,可加入其他功能,音樂數據可隨意修改。
可直接移植到其他芯片中,在中斷外的程序會嚴重影響到軟件延時。
單片機型號:STC15F104E或STC15L104E或其他8腳STC芯片。
晶振頻率:24Mhz
硬件連接:
紅色到P3.3
公共極直接到P3.2
綠色到P3.1
藍色到P3.0
蜂鳴器連接P3.5(不同型號芯片可能會有不同,根據寄存器決定)
版本更新歷史:
1.修正為逐漸導通掃描LED,防止3v芯片不接電阻,多個LED同時導通而導致顏色顯示不正常。
2.添加了顏色漸變功能。
3.P3.0~P3.3口可直接連接4腳全彩LED,可設置共陰共陽。
        注意:
                片內必須包含控制IO口輸出頻率的特殊功能寄存器,否則將無法輸出頻率。
                晶振頻率過高會導致低頻信號不能鳴叫,同時耗電量增加,看門狗更容易跑飛,
                過低則會導致時間頻率誤差加大。

源碼:

#include <reg51.h>
#include<intrins.h>
#include <stdlib.h>
#include <stdio.h>
//#include <eeprom.h>

#define FOSC 24000000L //晶振頻率
#define public 1 //共陽為1,共陰為0
unsigned int T1MS=65536-FOSC/1000; //計算定時器計時1毫秒需要的時間
sbit io=P3^2; //公共極
sbit io_blue=P3^0; //藍色LED通道
sbit io_green=P3^1;//綠色LED通道
sbit io_red=P3^3;//紅色LED通道
sbit led=P3^4;
//***********************
sfr P3M0 = 0xB1; // 定義P3M1寄存器
sfr P3M1 = 0xB2; // 定義P3M0寄存器
sfr eeprom_data  =  0xC2; //EEPROM數據地址寄存器
sfr eeprom_addrh =  0xC3; //EEPROM高8位地址寄存器
sfr eeprom_addrl =  0xC4; //EEPROM低8位地址寄存器
sfr eeprom_cmd   =  0xC5; //EEPROM模式操作寄存器
sfr eeprom_trig  =  0xC6; //EEPROM命令有效寄存器
sfr eeprom_contr =  0xC7; //EEPROM命令有效寄存器

sfr CLK_DIV     = 0x97;
sfr AUXR      = 0x8e;               //輔助特殊功能寄存器
sfr INT_CLKO  = 0x8f;               //喚醒和時鐘輸出功能寄存器
sbit T1CLKO   = P3^5;               //蜂鳴器連接VCC和P3.5

bit bit_blue=1;
bit bit_green=1;
bit bit_red=1;

unsigned int p=0; //延遲毫秒替減,為0則切換頻率
unsigned char m=0;//當前音樂數據指向的指針
unsigned int code md[212]={ //音樂數據,包含頻率和持續時間的數據。
0,580,600,300,600,100,900,200,1200,350,900,170,1200,200,1500,170,1600,260,1500,260,1180,180,1350,350,0,360,600,250,600,100,900,170,1200,360,900,170,1200,180,1500,170,1600,260,1500,260,1200,170,1330,200,0,150,1500,240,1330,100,1200,350,1200,270,1330,80,1500,170,2000,180,2000,175,1800,170,1600,170,1500,180,1330,170,1600,180,1500,180,1200,170,900,350,1000,350,1000,250,1100,100,1200,180,1500,350,1200,180,1340,170,1500,180,1600,170,1670,170,1800,190,1340,150,900,150,750,200,600,300,600,100,900,200,1200,350,900,170,1200,200,1500,170,1600,260,1500,260,1180,180,1350,350,0,360,600,250,600,100,900,170,1200,360,900,170,1200,180,1500,170,1600,260,1500,260,1200,170,1330,200,0,150,1500,260,1330,90,1200,350,1200,260,1330,90,1500,170,2000,350,1800,170,1600,170,1500,180,1330,170,1600,170,1500,180,1200,170,900,350,1000,350,1000,260,1100,90,1200,170,1500,340,1200,180,1330,170,1200,170,1120,180,1330,170,1200,350,0,250
};
void InitTimer0(void){ //初始化1ms中斷定時器
    TMOD = 0x01;
    TL0 = T1MS;                     //設置計數器低8位
    TH0 = T1MS >> 8;                    //設置計數器高8位
    EA = 1;
    ET0 = 1;
    TR0 = 1;
}


void set_hz(unsigned int hz){ //設置蜂鳴器頻率
    if(0 < (int)(65536-FOSC/2/hz)) { //頻率計算溢出
        hz=65535; //設置頻率為65535Hz
        }

    TMOD = 0x00;                    //設置定時器為模式1(16位自動重裝載)
    TMOD &= ~0x40;                  //C/T1=0, 對內部時鐘進行時鐘輸出
    TL1 = (65536-FOSC/2/hz);                 //初始化計時值
    TH1 = (65536-FOSC/2/hz) >> 8;
    INT_CLKO = 0x02;
    TR1 = 1;  //開始計數



}



void eeprom_init(){ //EEPROM初始化程序
        eeprom_contr        = 0x83;                //把第7位置1允許EEPROM可以讀寫
        eeprom_cmd         = 0x00;                //待機模式無ISP操作
        eeprom_addrh        = 0x00;
        eeprom_addrl        = 0x00;

}

unsigned char eeprom_read_dat(unsigned char addr_h,unsigned char addr_l){ //讀取EEPROM數據
        unsigned char e_dat = 0x00;
        eeprom_cmd         = 0x01;                //模式選擇為讀EEPROM
        eeprom_addrh        = addr_h;
        eeprom_addrl        = addr_l;
        eeprom_trig        = 0x5A;                //使命令有效
        eeprom_trig        = 0xA5;                //使命令有效
        e_dat                = eeprom_data;
        return e_dat;
}

void eeprom_write_dat(unsigned char addr_h,unsigned char addr_l,unsigned char w_dat){ //寫入EEPROM數據
        eeprom_cmd         = 0x02;                //模式選擇為寫EEPROM
        eeprom_addrh        = addr_h;
        eeprom_addrl        = addr_l;
        eeprom_data        = w_dat;
        eeprom_trig        = 0x5A;                //使命令有效
        eeprom_trig        = 0xA5;                //使命令有效

}

void eeprom_erase_dat(unsigned char addr_h,unsigned char addr_l){ //擦除EEPROM數據
        eeprom_cmd         = 0x03;                //模式選擇為擦除EEPROM
        eeprom_addrh        = addr_h;
        eeprom_addrl        = addr_l;
        eeprom_trig        = 0x5A;                //使命令有效
        eeprom_trig        = 0xA5;                //使命令有效
}



        unsigned char delay_led=0; //LED延時
        unsigned char srand_add=0; //隨機數種子(累加)
        unsigned char red_size=0; //當前紅色LED亮度
        unsigned char green_size=0;//當前綠色LED亮度
        unsigned char blue_size=0;//當前藍色LED亮度
        unsigned char new_red_size=0; //到達的紅色LED亮度
        unsigned char new_green_size=0;//到達的綠色LED亮度
        unsigned char new_blue_size=0;//到達的藍色LED亮度
        unsigned int delay_rand=0; //隨機延時
        void set_led_color(unsigned char red,unsigned char green,unsigned char blue){//設置LED顏色(3路不同占空比方波)
        unsigned char input_red,input_green,input_blue;
        unsigned char rgb_switch=1; //RGB切換開關,1是紅色,2是綠色,3是藍色。
        unsigned char while_delay=0xFF; //該變量循環替減,變量等于0后退出循環。
        unsigned char red_delay=input_red; //紅色LED占空比
        unsigned char green_delay=input_green; //綠色LED占空比
        unsigned char blue_delay=input_blue; //藍色LED占空比
        unsigned char not_red_delay=0xFF-input_red; //紅色LED占空比【位取反】
        unsigned char not_green_delay=0xFF-input_green; //綠色LED占空比【位取反】
        unsigned char not_blue_delay=0xFF-input_blue; //藍色LED占空比【位取反】
        bit red_on=1;bit green_on=1;bit blue_on=1; //LED亮滅狀態,1滅0亮。
        bit not_red=1;bit not_green=1; bit not_blue=1; //是否處理某顏色通道 1處理0不處理

                if(public == 1){ //共陽極

                        input_red=0xFF-red; //紅色位取反
                        input_green=0xFF-green; //綠色位取反
                        input_blue=0xFF-blue; //藍色位取反
                } else { //共陰級

                        input_red=red; //紅色位賦值
                        input_green=green; //綠色位賦值
                        input_blue=blue; //藍色位賦值

        }
               


                if(red==0x00){ //紅色亮度等于0
                not_red=0; //不處理紅色通道
                bit_red=public; //紅色亮滅等于公共極
                }

                if(red==0xFF){ //紅色亮度等于255
                not_red=0; //不處理紅色通道
                bit_red=!public; //紅色亮滅等于取反公共極
                }
                                if(green==0x00){ //綠色亮度等于0
                                not_green=0; //不處理綠色通道
                                bit_green=public; //綠色亮滅等于公共極
                                }

                                if(green==0xFF){ //綠色亮度等于255
                                not_green=0; //不處理綠色通道
                                bit_green=!public; //綠色亮滅等于取反公共極
                                }

                                        if(blue==0x00){ //藍色亮度等于0
                                        not_blue=0; //不處理藍色通道
                                        bit_blue=public; //藍色亮滅等于公共極
                                        }

                                        if(blue==0xFF){ //藍色亮度等于255
                                        not_blue=0; //不處理藍色通道
                                        bit_blue=!public; //藍色亮滅等于取反公共極
                                        }



                while( while_delay != 0x00 && not_red_delay + red_delay + not_green_delay + green_delay + not_blue_delay + blue_delay  != 0x00){ //所有替減變量大于或等于0
                while_delay--; //循環變量替減
                if(bit_red==!public){ //紅色LED緩存區與公共極相反
                        io_red=!public; //紅色LED的I/O接口等于取反公共極,可以構成回路,點亮LED。
                        io_green=public;//綠色LED的I/O接口等于公共極,無法構成回路,熄滅LED。
                        io_blue=public; //藍色LED的I/O接口等于公共極,無法構成回路,熄滅LED。
                        //delay10us();    //延時10微秒
                }

                if(bit_green==!public){ //綠色LED緩存區與公共極相反
                        io_red=public;    //紅色LED的I/O接口等于公共極,無法構成回路,熄滅LED。
                        io_green=!public; //綠色LED的I/O接口等于取反公共極,可以構成回路,點亮LED。
                        io_blue=public;   //藍色LED的I/O接口等于公共極,無法構成回路,熄滅LED。
                        //delay10us();      //延時10微秒
                }

                if(bit_blue==!public){ //藍色LED緩存區與公共極相反
                        io_red=public;   //紅色LED的I/O接口等于公共極,無法構成回路,熄滅LED。
                        io_green=public; //綠色LED的I/O接口等于公共極,無法構成回路,熄滅LED。
                        io_blue=!public; //藍色LED的I/O接口等于取反公共極,可以構成回路,點亮LED。
                        //delay10us();     //延時10微秒
                }




                        if(rgb_switch == 1 && not_red == 1) { //處理紅色通道
                                 
                                if(red_on == 0){
                                bit_red=0; //將LED亮滅狀態放入緩存區。
                                
                                not_red_delay--; //紅色LED反占空比減1
                                if(not_red_delay == 0) red_on=1; //紅色LED亮滅狀態放入緩存區
                                }

                                if(red_on == 1){
                                bit_red=1; //將LED亮滅狀態放入緩存區。
                                
                                red_delay--; //紅色LED占空比減1
                                if(red_delay == 0) red_on=0; //紅色LED亮滅狀態放入緩存區
                                }

                        rgb_switch++; //切換到綠色通道
                        } else {
                        rgb_switch++; //切換到綠色通道
                        not_red_delay--;
                        red_delay--;

                        }

                        if(rgb_switch == 2 && not_green == 1){ //處理綠色通道
                                 
                                if(green_on == 0){
                                bit_green=0; //將LED亮滅狀態放入緩存區。
                                
                                
                                not_green_delay--; //綠色LED反占空比減1
                                if(not_green_delay == 0) green_on=1; //綠色LED亮滅狀態放入緩存區
                                }

                                if(green_on == 1){
                                bit_green=1; //將LED亮滅狀態放入緩存區。
                                
                                
                                green_delay--; //綠色LED占空比減1
                                if(green_delay == 0) green_on=0; //綠色LED亮滅狀態放入緩存區
                                }
                        rgb_switch++; //切換到藍色通道
                        }  else {
                        rgb_switch++; //切換到藍色通道
                        not_green_delay--;
                        green_delay--;

                        }

                        if(rgb_switch == 3 && not_blue == 1){ //處理藍色通道
                                 
                                if(blue_on == 0){
                                bit_blue=0; //將LED亮滅狀態放入緩存區。
                                
                                
                                not_blue_delay--; //藍色LED反占空比減1
                                if(not_blue_delay == 0) blue_on=1; //藍色LED亮滅狀態放入緩存區
                                }

                                if(blue_on == 1){
                                bit_blue=1;  //將LED亮滅狀態放入緩存區。
                                
                                
                                blue_delay--; //藍色LED占空比減1
                                if(blue_delay == 0) blue_on=0; //藍色LED亮滅狀態放入緩存區
                                }
                        rgb_switch=1; //切換紅色通道
                        

                } else {
                rgb_switch=1; //切換紅色通道
                        not_blue_delay--;
                        blue_delay--;

                }

                }
}
void main(){ //主函數
        AUXR |= 0xC0;
        InitTimer0();
        eeprom_init(); //EEPROM初始化
        srand_add=eeprom_read_dat(0x00,0x01);//從EEPROM中讀取隨機隨種子
        eeprom_erase_dat(0x00,0x01);//從EEPROM中擦除數據
        srand_add++; //隨機數種子累加1個
        eeprom_write_dat(0x00,0x01,srand_add); //將新種子寫入EEPROM中
        srand(srand_add); //初始化隨機數種子,用于每次芯片上電都會產生不重復的顏色。
        delay_led=0;  //LED延時計數器清零
                red_size=0x00; //當前紅色值為0
                green_size=0x00; //當前綠色值為0
                blue_size=0x00; //當前藍色值為0



        if(public==1){ //如果LED為共陽則 (注:修改IO口位置需要修改這里。)

                P3M1 = 0x04;       //定義P3.2口為強上拉輸出,提供更多電流以驅動LED彩燈。

                        } else { //共陰則

                P3M1 = 0x0B;     //定義P3.0,P3,1,P3,3口為強上拉輸出,提供更多電流以驅動LED彩燈。

                }






                        io=public; //公共極賦值,否則LED就亮不了。



        while(1) { //無限循環

                        new_red_size=rand();//紅色亮度取隨機數
                        new_green_size=rand();//藍色亮度取隨機數
                        new_blue_size=rand();//綠色亮度取隨機數


                        while(new_red_size != red_size && new_green_size != green_size && new_blue_size != blue_size){ //當前顏色不等于隨機到達的顏色則循環
                                if(red_size<new_red_size) { //當前紅色亮度小于到達的紅色亮度
                                        red_size++; //紅色亮度相加
                                                } else { //否則
                                        red_size--; //紅色亮度相減
                                }

                                if(green_size<new_green_size) { //當前綠色亮度小于到達的綠色亮度
                                        green_size++; //綠色亮度相加
                                                } else { //否則
                                        green_size--; //綠色亮度相減
                                }

                                if(blue_size<new_blue_size) { //當前藍色亮度小于到達的藍色色亮度
                                        blue_size++; //藍色亮度相加
                                                } else { //否則
                                        blue_size--; //藍色亮度相減
                                }
                                       
                                        delay_led=rand()&0xF+0xF; //設置替減次數
                                        while(delay_led--){ //計數循環替減
                                                set_led_color(red_size,green_size,blue_size);  //設置輸出LED顏色


                                        }



                        }
                                       
                                        delay_led=rand()&0x7F+0x7F; //持續執行0~127個下面的指令。
                                                while(delay_led--){ //漸變完畢有1段時間保持顏色。
                                                        set_led_color(red_size,green_size,blue_size);  //設置輸出LED顏色
                                                }
                                       
                                       
                                                


                                





               


        }
}

void Timer0Interrupt(void) interrupt 1{ //1ms 定時器中斷程序
    TH0 = 0x0A2;
    TL0 = 0x40;
        if(p==0){  //延遲時間減到0
                p=md[m+1]; //設置延遲時間
                set_hz(md[m]); //設置鳴叫頻率
                m+=2; //指針加2
                if(m>=212) m=0; //指針超過212則清零避免取出其他胡亂的數據
        } else {
                p--; //延遲時間減1
               
        }
}





評分

參與人數 1黑幣 +100 收起 理由
admin + 100 共享資料的黑幣獎勵!

查看全部評分

分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏4 分享淘帖 頂 踩
回復

使用道具 舉報

沙發
ID:85607 發表于 2016-7-7 14:31 | 只看該作者
好東西~
回復

使用道具 舉報

板凳
ID:74143 發表于 2016-7-7 15:23 | 只看該作者
不錯,學習了。
回復

使用道具 舉報

地板
ID:74143 發表于 2016-7-7 15:24 | 只看該作者
不錯,好東西。
回復

使用道具 舉報

5#
ID:129577 發表于 2016-7-7 17:19 來自手機 | 只看該作者
挺好的
回復

使用道具 舉報

6#
ID:64089 發表于 2016-7-8 13:27 | 只看該作者
有點意思,不錯!
回復

使用道具 舉報

7#
ID:91165 發表于 2016-7-8 13:34 | 只看該作者
想看看這個
回復

使用道具 舉報

8#
ID:100826 發表于 2016-7-8 14:48 | 只看該作者
學習  謝謝分享............
回復

使用道具 舉報

9#
ID:129742 發表于 2016-7-8 20:43 | 只看該作者
看看,好東西
回復

使用道具 舉報

10#
ID:102293 發表于 2016-7-8 23:33 | 只看該作者
這個不錯,學習學習!謝謝分享
回復

使用道具 舉報

11#
ID:93151 發表于 2016-7-13 20:41 | 只看該作者
正在學習,看下
回復

使用道具 舉報

12#
ID:75461 發表于 2016-7-14 23:39 | 只看該作者
好東西,看看
回復

使用道具 舉報

13#
ID:87738 發表于 2016-7-16 22:49 | 只看該作者
不錯!
回復

使用道具 舉報

14#
ID:57149 發表于 2016-7-17 08:55 | 只看該作者
這個應該不錯。
回復

使用道具 舉報

15#
ID:130771 發表于 2016-7-17 10:45 來自手機 | 只看該作者
好好好
回復

使用道具 舉報

16#
ID:79544 發表于 2016-7-17 11:45 | 只看該作者
看看學習一下
回復

使用道具 舉報

17#
ID:91780 發表于 2016-7-20 14:47 | 只看該作者
好,非常棒,人才哈
回復

使用道具 舉報

18#
ID:75002 發表于 2016-7-20 15:57 | 只看該作者
好東西~
回復

使用道具 舉報

19#
ID:62929 發表于 2016-7-20 21:37 來自手機 | 只看該作者
好東西!學習啦!
回復

使用道具 舉報

20#
ID:73463 發表于 2016-7-21 08:20 | 只看該作者
好東西
回復

使用道具 舉報

21#
ID:134545 發表于 2016-7-22 05:33 | 只看該作者
蜂鳴器放歌, 有意思
回復

使用道具 舉報

22#
ID:99527 發表于 2016-7-25 00:03 | 只看該作者
好東西吧
回復

使用道具 舉報

23#
ID:130816 發表于 2016-7-25 06:25 | 只看該作者
天天在學 就是沒長進,還是年輕好。
回復

使用道具 舉報

24#
ID:134860 發表于 2016-7-26 22:20 | 只看該作者
#在這里快速回復# 這個不錯,學習學習!謝謝分享
回復

使用道具 舉報

25#
ID:72399 發表于 2016-7-27 22:06 | 只看該作者
什么東西
回復

使用道具 舉報

26#
ID:64913 發表于 2016-7-28 23:10 | 只看該作者
這個要看看,學習學習
回復

使用道具 舉報

27#
ID:64913 發表于 2016-7-28 23:22 | 只看該作者
代碼好規范啊
回復

使用道具 舉報

28#
ID:137251 發表于 2016-8-21 18:12 | 只看該作者
我也要
回復

使用道具 舉報

29#
ID:137220 發表于 2016-8-21 22:25 | 只看該作者
向樓主學習
回復

使用道具 舉報

30#
ID:3212 發表于 2016-8-22 06:16 | 只看該作者
學習了
回復

使用道具 舉報

31#
ID:137531 發表于 2016-8-24 23:06 來自手機 | 只看該作者
好強大,我是菜鳥,正在發奮中
回復

使用道具 舉報

32#
ID:123732 發表于 2016-8-25 08:41 | 只看該作者
學習一下
回復

使用道具 舉報

33#
ID:92231 發表于 2016-8-31 00:39 來自手機 | 只看該作者
音樂與光色同時運行,學習了
回復

使用道具 舉報

34#
ID:22995 發表于 2016-8-31 08:43 | 只看該作者
學習了,支持樓主的精神
回復

使用道具 舉報

35#
ID:138037 發表于 2016-8-31 12:25 來自手機 | 只看該作者
看看,應該是好東西
回復

使用道具 舉報

36#
ID:138379 發表于 2016-9-3 22:47 來自手機 | 只看該作者
學習學習 嘿嘿
回復

使用道具 舉報

37#
ID:127965 發表于 2016-9-4 10:13 | 只看該作者
謝謝你的分享
回復

使用道具 舉報

38#
ID:138421 發表于 2016-9-4 15:21 | 只看該作者
自己嘗試寫過,效果不好。學習下高手怎么寫的
回復

使用道具 舉報

39#
ID:136460 發表于 2016-9-12 21:56 | 只看該作者
樓主好人,謝謝分享
回復

使用道具 舉報

40#
ID:140489 發表于 2016-9-28 09:15 | 只看該作者
很好的資料,謝謝分享
回復

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規則

手機版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術交流QQ群281945664

Powered by 單片機教程網

快速回復 返回頂部 返回列表
主站蜘蛛池模板: www日韩| 91在线精品视频 | 久久精品色欧美aⅴ一区二区 | 在线国产视频观看 | 亚洲欧美高清 | 欧美精品一区二区三区蜜桃视频 | 91精品国产91久久久久游泳池 | 伊人伊成久久人综合网站 | 国产成人在线一区二区 | 国产在线一区二区三区 | 亚洲成人网在线 | 亚洲第一福利视频 | 狠狠爱视频 | 国产乱码精品一区二区三区忘忧草 | 日韩欧美在线视频 | 欧美一区二区大片 | 欧洲精品在线观看 | 麻豆视频在线免费看 | 日韩欧美成人精品 | 国产日韩欧美在线一区 | 日韩福利| 亚洲一区二区三区视频 | 91嫩草精品 | 欧美日韩视频在线第一区 | 91在线观看免费视频 | 成年人精品视频在线观看 | 91精品国产91久久综合桃花 | 午夜网| 国产成人精品a视频一区www | 亚洲视频国产视频 | 少妇精品亚洲一区二区成人 | av在线免费观看网站 | 午夜精品一区二区三区免费视频 | 久久国产精品99久久久久久丝袜 | 久久91精品 | 97免费在线观看视频 | 国产精品久久久久久久久久久久 | 成人精品视频免费 | 亚洲精品不卡 | 日本黄色免费视频 | 久久久精品日本 |