標(biāo)題:
DIY全彩燈隨機(jī)顏色漸變程序 1677萬(wàn)色輸出 蜂鳴器放歌 2合1 可同時(shí)工作
[打印本頁(yè)]
作者:
npn
時(shí)間:
2016-7-7 11:44
標(biāo)題:
DIY全彩燈隨機(jī)顏色漸變程序 1677萬(wàn)色輸出 蜂鳴器放歌 2合1 可同時(shí)工作
蜂鳴器放歌程序用到兩個(gè)定時(shí)器,分別用于精準(zhǔn)控制頻率和時(shí)間。
賀卡音樂(lè)芯片唯一的制作方法,可加入其他功能,音樂(lè)數(shù)據(jù)可隨意修改。
可直接移植到其他芯片中,在中斷外的程序會(huì)嚴(yán)重影響到軟件延時(shí)。
單片機(jī)型號(hào):STC15F104E或STC15L104E或其他8腳STC芯片。
晶振頻率:24Mhz
硬件連接:
紅色到P3.3
公共極直接到P3.2
綠色到P3.1
藍(lán)色到P3.0
蜂鳴器連接P3.5(不同型號(hào)芯片可能會(huì)有不同,根據(jù)寄存器決定)
版本更新歷史:
1.修正為逐漸導(dǎo)通掃描LED,防止3v芯片不接電阻,多個(gè)LED同時(shí)導(dǎo)通而導(dǎo)致顏色顯示不正常。
2.添加了顏色漸變功能。
3.P3.0~P3.3口可直接連接4腳全彩LED,可設(shè)置共陰共陽(yáng)。
注意:
片內(nèi)必須包含控制IO口輸出頻率的特殊功能寄存器,否則將無(wú)法輸出頻率。
晶振頻率過(guò)高會(huì)導(dǎo)致低頻信號(hào)不能鳴叫,同時(shí)耗電量增加,看門(mén)狗更容易跑飛,
過(guò)低則會(huì)導(dǎo)致時(shí)間頻率誤差加大。
源碼:
#include <reg51.h>
#include<intrins.h>
#include <stdlib.h>
#include <stdio.h>
//#include <eeprom.h>
#define FOSC 24000000L //晶振頻率
#define public 1 //共陽(yáng)為1,共陰為0
unsigned int T1MS=65536-FOSC/1000; //計(jì)算定時(shí)器計(jì)時(shí)1毫秒需要的時(shí)間
sbit io=P3^2; //公共極
sbit io_blue=P3^0; //藍(lán)色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數(shù)據(jù)地址寄存器
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; //喚醒和時(shí)鐘輸出功能寄存器
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;//當(dāng)前音樂(lè)數(shù)據(jù)指向的指針
unsigned int code md[212]={ //音樂(lè)數(shù)據(jù),包含頻率和持續(xù)時(shí)間的數(shù)據(jù)。
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中斷定時(shí)器
TMOD = 0x01;
TL0 = T1MS; //設(shè)置計(jì)數(shù)器低8位
TH0 = T1MS >> 8; //設(shè)置計(jì)數(shù)器高8位
EA = 1;
ET0 = 1;
TR0 = 1;
}
void set_hz(unsigned int hz){ //設(shè)置蜂鳴器頻率
if(0 < (int)(65536-FOSC/2/hz)) { //頻率計(jì)算溢出
hz=65535; //設(shè)置頻率為65535Hz
}
TMOD = 0x00; //設(shè)置定時(shí)器為模式1(16位自動(dòng)重裝載)
TMOD &= ~0x40; //C/T1=0, 對(duì)內(nèi)部時(shí)鐘進(jìn)行時(shí)鐘輸出
TL1 = (65536-FOSC/2/hz); //初始化計(jì)時(shí)值
TH1 = (65536-FOSC/2/hz) >> 8;
INT_CLKO = 0x02;
TR1 = 1; //開(kāi)始計(jì)數(shù)
}
void eeprom_init(){ //EEPROM初始化程序
eeprom_contr = 0x83; //把第7位置1允許EEPROM可以讀寫(xiě)
eeprom_cmd = 0x00; //待機(jī)模式無(wú)ISP操作
eeprom_addrh = 0x00;
eeprom_addrl = 0x00;
}
unsigned char eeprom_read_dat(unsigned char addr_h,unsigned char addr_l){ //讀取EEPROM數(shù)據(jù)
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){ //寫(xiě)入EEPROM數(shù)據(jù)
eeprom_cmd = 0x02; //模式選擇為寫(xiě)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數(shù)據(jù)
eeprom_cmd = 0x03; //模式選擇為擦除EEPROM
eeprom_addrh = addr_h;
eeprom_addrl = addr_l;
eeprom_trig = 0x5A; //使命令有效
eeprom_trig = 0xA5; //使命令有效
}
unsigned char delay_led=0; //LED延時(shí)
unsigned char srand_add=0; //隨機(jī)數(shù)種子(累加)
unsigned char red_size=0; //當(dāng)前紅色LED亮度
unsigned char green_size=0;//當(dāng)前綠色LED亮度
unsigned char blue_size=0;//當(dāng)前藍(lán)色LED亮度
unsigned char new_red_size=0; //到達(dá)的紅色LED亮度
unsigned char new_green_size=0;//到達(dá)的綠色LED亮度
unsigned char new_blue_size=0;//到達(dá)的藍(lán)色LED亮度
unsigned int delay_rand=0; //隨機(jī)延時(shí)
void set_led_color(unsigned char red,unsigned char green,unsigned char blue){//設(shè)置LED顏色(3路不同占空比方波)
unsigned char input_red,input_green,input_blue;
unsigned char rgb_switch=1; //RGB切換開(kāi)關(guān),1是紅色,2是綠色,3是藍(lán)色。
unsigned char while_delay=0xFF; //該變量循環(huán)替減,變量等于0后退出循環(huán)。
unsigned char red_delay=input_red; //紅色LED占空比
unsigned char green_delay=input_green; //綠色LED占空比
unsigned char blue_delay=input_blue; //藍(lán)色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; //藍(lán)色LED占空比【位取反】
bit red_on=1;bit green_on=1;bit blue_on=1; //LED亮滅狀態(tài),1滅0亮。
bit not_red=1;bit not_green=1; bit not_blue=1; //是否處理某顏色通道 1處理0不處理
if(public == 1){ //共陽(yáng)極
input_red=0xFF-red; //紅色位取反
input_green=0xFF-green; //綠色位取反
input_blue=0xFF-blue; //藍(lán)色位取反
} else { //共陰級(jí)
input_red=red; //紅色位賦值
input_green=green; //綠色位賦值
input_blue=blue; //藍(lán)色位賦值
}
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){ //藍(lán)色亮度等于0
not_blue=0; //不處理藍(lán)色通道
bit_blue=public; //藍(lán)色亮滅等于公共極
}
if(blue==0xFF){ //藍(lán)色亮度等于255
not_blue=0; //不處理藍(lán)色通道
bit_blue=!public; //藍(lán)色亮滅等于取反公共極
}
while( while_delay != 0x00 && not_red_delay + red_delay + not_green_delay + green_delay + not_blue_delay + blue_delay != 0x00){ //所有替減變量大于或等于0
while_delay--; //循環(huán)變量替減
if(bit_red==!public){ //紅色LED緩存區(qū)與公共極相反
io_red=!public; //紅色LED的I/O接口等于取反公共極,可以構(gòu)成回路,點(diǎn)亮LED。
io_green=public;//綠色LED的I/O接口等于公共極,無(wú)法構(gòu)成回路,熄滅LED。
io_blue=public; //藍(lán)色LED的I/O接口等于公共極,無(wú)法構(gòu)成回路,熄滅LED。
//delay10us(); //延時(shí)10微秒
}
if(bit_green==!public){ //綠色LED緩存區(qū)與公共極相反
io_red=public; //紅色LED的I/O接口等于公共極,無(wú)法構(gòu)成回路,熄滅LED。
io_green=!public; //綠色LED的I/O接口等于取反公共極,可以構(gòu)成回路,點(diǎn)亮LED。
io_blue=public; //藍(lán)色LED的I/O接口等于公共極,無(wú)法構(gòu)成回路,熄滅LED。
//delay10us(); //延時(shí)10微秒
}
if(bit_blue==!public){ //藍(lán)色LED緩存區(qū)與公共極相反
io_red=public; //紅色LED的I/O接口等于公共極,無(wú)法構(gòu)成回路,熄滅LED。
io_green=public; //綠色LED的I/O接口等于公共極,無(wú)法構(gòu)成回路,熄滅LED。
io_blue=!public; //藍(lán)色LED的I/O接口等于取反公共極,可以構(gòu)成回路,點(diǎn)亮LED。
//delay10us(); //延時(shí)10微秒
}
if(rgb_switch == 1 && not_red == 1) { //處理紅色通道
if(red_on == 0){
bit_red=0; //將LED亮滅狀態(tài)放入緩存區(qū)。
not_red_delay--; //紅色LED反占空比減1
if(not_red_delay == 0) red_on=1; //紅色LED亮滅狀態(tài)放入緩存區(qū)
}
if(red_on == 1){
bit_red=1; //將LED亮滅狀態(tài)放入緩存區(qū)。
red_delay--; //紅色LED占空比減1
if(red_delay == 0) red_on=0; //紅色LED亮滅狀態(tài)放入緩存區(qū)
}
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亮滅狀態(tài)放入緩存區(qū)。
not_green_delay--; //綠色LED反占空比減1
if(not_green_delay == 0) green_on=1; //綠色LED亮滅狀態(tài)放入緩存區(qū)
}
if(green_on == 1){
bit_green=1; //將LED亮滅狀態(tài)放入緩存區(qū)。
green_delay--; //綠色LED占空比減1
if(green_delay == 0) green_on=0; //綠色LED亮滅狀態(tài)放入緩存區(qū)
}
rgb_switch++; //切換到藍(lán)色通道
} else {
rgb_switch++; //切換到藍(lán)色通道
not_green_delay--;
green_delay--;
}
if(rgb_switch == 3 && not_blue == 1){ //處理藍(lán)色通道
if(blue_on == 0){
bit_blue=0; //將LED亮滅狀態(tài)放入緩存區(qū)。
not_blue_delay--; //藍(lán)色LED反占空比減1
if(not_blue_delay == 0) blue_on=1; //藍(lán)色LED亮滅狀態(tài)放入緩存區(qū)
}
if(blue_on == 1){
bit_blue=1; //將LED亮滅狀態(tài)放入緩存區(qū)。
blue_delay--; //藍(lán)色LED占空比減1
if(blue_delay == 0) blue_on=0; //藍(lán)色LED亮滅狀態(tài)放入緩存區(qū)
}
rgb_switch=1; //切換紅色通道
} else {
rgb_switch=1; //切換紅色通道
not_blue_delay--;
blue_delay--;
}
}
}
void main(){ //主函數(shù)
AUXR |= 0xC0;
InitTimer0();
eeprom_init(); //EEPROM初始化
srand_add=eeprom_read_dat(0x00,0x01);//從EEPROM中讀取隨機(jī)隨種子
eeprom_erase_dat(0x00,0x01);//從EEPROM中擦除數(shù)據(jù)
srand_add++; //隨機(jī)數(shù)種子累加1個(gè)
eeprom_write_dat(0x00,0x01,srand_add); //將新種子寫(xiě)入EEPROM中
srand(srand_add); //初始化隨機(jī)數(shù)種子,用于每次芯片上電都會(huì)產(chǎn)生不重復(fù)的顏色。
delay_led=0; //LED延時(shí)計(jì)數(shù)器清零
red_size=0x00; //當(dāng)前紅色值為0
green_size=0x00; //當(dāng)前綠色值為0
blue_size=0x00; //當(dāng)前藍(lán)色值為0
if(public==1){ //如果LED為共陽(yáng)則 (注:修改IO口位置需要修改這里。)
P3M1 = 0x04; //定義P3.2口為強(qiáng)上拉輸出,提供更多電流以驅(qū)動(dòng)LED彩燈。
} else { //共陰則
P3M1 = 0x0B; //定義P3.0,P3,1,P3,3口為強(qiáng)上拉輸出,提供更多電流以驅(qū)動(dòng)LED彩燈。
}
io=public; //公共極賦值,否則LED就亮不了。
while(1) { //無(wú)限循環(huán)
new_red_size=rand();//紅色亮度取隨機(jī)數(shù)
new_green_size=rand();//藍(lán)色亮度取隨機(jī)數(shù)
new_blue_size=rand();//綠色亮度取隨機(jī)數(shù)
while(new_red_size != red_size && new_green_size != green_size && new_blue_size != blue_size){ //當(dāng)前顏色不等于隨機(jī)到達(dá)的顏色則循環(huán)
if(red_size<new_red_size) { //當(dāng)前紅色亮度小于到達(dá)的紅色亮度
red_size++; //紅色亮度相加
} else { //否則
red_size--; //紅色亮度相減
}
if(green_size<new_green_size) { //當(dāng)前綠色亮度小于到達(dá)的綠色亮度
green_size++; //綠色亮度相加
} else { //否則
green_size--; //綠色亮度相減
}
if(blue_size<new_blue_size) { //當(dāng)前藍(lán)色亮度小于到達(dá)的藍(lán)色色亮度
blue_size++; //藍(lán)色亮度相加
} else { //否則
blue_size--; //藍(lán)色亮度相減
}
delay_led=rand()&0xF+0xF; //設(shè)置替減次數(shù)
while(delay_led--){ //計(jì)數(shù)循環(huán)替減
set_led_color(red_size,green_size,blue_size); //設(shè)置輸出LED顏色
}
}
delay_led=rand()&0x7F+0x7F; //持續(xù)執(zhí)行0~127個(gè)下面的指令。
while(delay_led--){ //漸變完畢有1段時(shí)間保持顏色。
set_led_color(red_size,green_size,blue_size); //設(shè)置輸出LED顏色
}
}
}
void Timer0Interrupt(void) interrupt 1{ //1ms 定時(shí)器中斷程序
TH0 = 0x0A2;
TL0 = 0x40;
if(p==0){ //延遲時(shí)間減到0
p=md[m+1]; //設(shè)置延遲時(shí)間
set_hz(md[m]); //設(shè)置鳴叫頻率
m+=2; //指針加2
if(m>=212) m=0; //指針超過(guò)212則清零避免取出其他胡亂的數(shù)據(jù)
} else {
p--; //延遲時(shí)間減1
}
}
作者:
babylu200661
時(shí)間:
2016-7-7 14:31
好東西~
作者:
lb688
時(shí)間:
2016-7-7 15:23
不錯(cuò),學(xué)習(xí)了。
作者:
lb688
時(shí)間:
2016-7-7 15:24
不錯(cuò),好東西。
作者:
天下第一帥
時(shí)間:
2016-7-7 17:19
挺好的
作者:
nsj21n
時(shí)間:
2016-7-8 13:27
有點(diǎn)意思,不錯(cuò)!
作者:
HWL0541
時(shí)間:
2016-7-8 13:34
想看看這個(gè)
作者:
DIY電子
時(shí)間:
2016-7-8 14:48
學(xué)習(xí) 謝謝分享............
作者:
黃看山
時(shí)間:
2016-7-8 20:43
看看,好東西
作者:
行云流水
時(shí)間:
2016-7-8 23:33
這個(gè)不錯(cuò),學(xué)習(xí)學(xué)習(xí)!謝謝分享
作者:
xsjysm888
時(shí)間:
2016-7-13 20:41
正在學(xué)習(xí),看下
作者:
uva2015
時(shí)間:
2016-7-14 23:39
好東西,看看
作者:
1511544112
時(shí)間:
2016-7-16 22:49
不錯(cuò)!
作者:
hantp
時(shí)間:
2016-7-17 08:55
這個(gè)應(yīng)該不錯(cuò)。
作者:
仨芢
時(shí)間:
2016-7-17 10:45
好好好
作者:
騰飛的龍
時(shí)間:
2016-7-17 11:45
看看學(xué)習(xí)一下
作者:
山水qls
時(shí)間:
2016-7-20 14:47
好,非常棒,人才哈
作者:
darkpirates
時(shí)間:
2016-7-20 15:57
好東西~
作者:
286458071
時(shí)間:
2016-7-20 21:37
好東西!學(xué)習(xí)啦!
作者:
ztflove51
時(shí)間:
2016-7-21 08:20
好東西
作者:
abc201006
時(shí)間:
2016-7-22 05:33
蜂鳴器放歌, 有意思
作者:
wkuz8888
時(shí)間:
2016-7-25 00:03
好東西吧
作者:
wszyg621
時(shí)間:
2016-7-25 06:25
天天在學(xué) 就是沒(méi)長(zhǎng)進(jìn),還是年輕好!
作者:
shitouyiyuya
時(shí)間:
2016-7-26 22:20
#在這里快速回復(fù)# 這個(gè)不錯(cuò),學(xué)習(xí)學(xué)習(xí)!謝謝分享
作者:
綠源學(xué)習(xí)者
時(shí)間:
2016-7-27 22:06
什么東西
作者:
AOP
時(shí)間:
2016-7-28 23:10
這個(gè)要看看,學(xué)習(xí)學(xué)習(xí)
作者:
AOP
時(shí)間:
2016-7-28 23:22
代碼好規(guī)范啊
作者:
發(fā)瘋飛
時(shí)間:
2016-8-21 18:12
我也要
作者:
liumingqin
時(shí)間:
2016-8-21 22:25
向樓主學(xué)習(xí)
作者:
middfat
時(shí)間:
2016-8-22 06:16
學(xué)習(xí)了
作者:
nihua
時(shí)間:
2016-8-24 23:06
好強(qiáng)大,我是菜鳥(niǎo),正在發(fā)奮中
作者:
劉海龍
時(shí)間:
2016-8-25 08:41
學(xué)習(xí)一下
作者:
whengfu
時(shí)間:
2016-8-31 00:39
音樂(lè)與光色同時(shí)運(yùn)行,學(xué)習(xí)了
作者:
數(shù)據(jù)總線(xiàn)
時(shí)間:
2016-8-31 08:43
學(xué)習(xí)了,支持樓主的精神
作者:
lh3158
時(shí)間:
2016-8-31 12:25
看看,應(yīng)該是好東西
作者:
LH縱橫
時(shí)間:
2016-9-3 22:47
學(xué)習(xí)學(xué)習(xí) 嘿嘿
作者:
32323232
時(shí)間:
2016-9-4 10:13
謝謝你的分享
作者:
workload900
時(shí)間:
2016-9-4 15:21
自己嘗試寫(xiě)過(guò),效果不好。學(xué)習(xí)下高手怎么寫(xiě)的
作者:
東北那誰(shuí)
時(shí)間:
2016-9-12 21:56
樓主好人,謝謝分享
作者:
lids
時(shí)間:
2016-9-28 09:15
很好的資料,謝謝分享
作者:
dbsjacky
時(shí)間:
2017-6-30 19:27
謝謝 樓主分享
作者:
hei51com
時(shí)間:
2020-5-23 10:59
感謝分享,學(xué)習(xí)看看
歡迎光臨 (http://www.torrancerestoration.com/bbs/)
Powered by Discuz! X3.1