標(biāo)題: 單片機(jī)流水燈與呼吸燈結(jié)合-滴水燈程序及詳細(xì)教程 [打印本頁(yè)]
作者: xiongda 時(shí)間: 2015-5-26 19:22
標(biāo)題: 單片機(jī)流水燈與呼吸燈結(jié)合-滴水燈程序及詳細(xì)教程
TWAS手把手教你做呼吸燈-基于51單片機(jī)學(xué)習(xí)板
內(nèi)容比較簡(jiǎn)單,發(fā)這個(gè)貼主要是針對(duì)新手!
什么是呼吸燈?
顧名思義,燈光在微電腦控制之下完成由亮到暗的逐漸變化,感覺(jué)像是在呼吸。用專(zhuān)業(yè)的話來(lái)說(shuō)是通過(guò)控制PWM的占空比來(lái)完成對(duì)LED亮度的控制
什么是PWM和占空比?
脈沖寬度調(diào)制(Pulse Width Modulation,簡(jiǎn)稱(chēng)PWM),是利用微處理器的數(shù)字輸出來(lái)對(duì)模擬電路進(jìn)行控制的一種技術(shù)。
占空比:高電平在一個(gè)周期之內(nèi)所占的時(shí)間比率。
呼吸燈原理
當(dāng)一顆LED在高速閃爍,閃爍的頻率已經(jīng)超過(guò)了人眼的感知的范圍,那么我們看到這顆LED就是一直亮的,也就是視覺(jué)暫留現(xiàn)象(余暉效應(yīng))。如果
我們控制一次閃爍中亮和滅的時(shí)間(修改占空比),就可以控制亮度。
代碼實(shí)現(xiàn):
/*******************************************************
* 程序名稱(chēng):main.c
* 程序功能:實(shí)現(xiàn)呼吸燈的主程序文件
* 程序作者:TWAS
* 創(chuàng)建時(shí)間:2015-1-22
* 修改時(shí)間:
* 程序版本:V0.1
*******************************************************/
/* 包含的頭文件 */
#include <reg52.h>
/* 尋址變量定義 */
sbit LED_Drive = P3^5; /* 定義驅(qū)動(dòng)LED的IO口,LED為共陽(yáng) */
/******************************************************
* 函數(shù)名稱(chēng):main
* 函數(shù)功能:主函數(shù)
* 入口參數(shù):NULL
* 出口參數(shù):NULL
*******************************************************/
int main()
{
unsigned char i;
/* 初始化 */
LED_Drive = 1;
/* 主循環(huán) */
while(1)
{
for(i = 0; i < 200; i++)
{
/* 外邊的for循環(huán)共循環(huán)200次,前面10次點(diǎn)亮LED,后面180次熄滅LED
* 通過(guò)修改if后面的值,就可以改變占空比
*/
if(i < 10)
{
LED_Drive = 0;
}
else
{
LED_Drive = 1;
}
}
}
return 0;
}
/******************************************
* 程序結(jié)束
*****************************************/
可以明顯看出我們所控制的LED比電源燈暗許多,既然我們會(huì)控制亮度,想實(shí)現(xiàn)呼吸燈也就變的簡(jiǎn)單了
代碼實(shí)現(xiàn):(為了節(jié)約空間和界面簡(jiǎn)潔,只貼出主要實(shí)現(xiàn)的部分)
int main()
{
unsigned char i;
unsigned char ucNum = 0; /* 新增兩個(gè)變量,ucNum控制占空比*/
bit bAdd = 1; /* bAdd選擇是增大占空比還是減小占空比 */
/* 初始化 */
LED_Drive = 1;
/* 主循環(huán) */
while(1)
{
for(i = 0; i < 200; i++)
{
/* 外邊的for循環(huán)共循環(huán)200次,前面10次點(diǎn)亮LED,后面180次熄滅LED
* 通過(guò)修改if后面的值,就可以改變占空比
*/
if(i < ucNum)
{
LED_Drive = 0;
}
else
{
LED_Drive = 1;
}
}
/* 選擇是增大占空比還是減小占空比 */
if (1 == bAdd)
{
ucNum++;
}
else
{
ucNum--;
}
/* 當(dāng)Num等于200也就是最大值時(shí),bAdd置0,Num開(kāi)始減小 */
if (200 == ucNum)
{
bAdd = 0;
}
/* 當(dāng)Num等于200也就是最大值時(shí),bAdd置1,Num開(kāi)始增大 */
else if (0 == ucNum)
{
bAdd = 1;
}
}
return 0;
}
由于圖片看不到效果,這個(gè)地方就不貼圖了,根據(jù)測(cè)試,我們的所需要的功能實(shí)現(xiàn)了!
但是這時(shí)候有的人就有疑問(wèn)了,這是很普通的LED,那如果是特殊一點(diǎn)的呢?比如我所用的
學(xué)習(xí)板上面,16顆LED是用595驅(qū)動(dòng)的,那呼吸燈又該如何實(shí)現(xiàn)呢?
其實(shí)很簡(jiǎn)單,我們把驅(qū)動(dòng)LED的函數(shù)封裝一下,直接替換,其它不變就行了!
代碼實(shí)現(xiàn):(為了節(jié)約空間和界面簡(jiǎn)潔,只貼出主要實(shí)現(xiàn)的部分)
for(i = 0; i < 200; i++)
{
/* 外邊的for循環(huán)共循環(huán)200次,前面10次點(diǎn)亮LED,后面180次熄滅LED
* 通過(guò)修改if后面的值,就可以改變占空比
*/
if(i < ucNum)
{
DriveLED(0x0003); /* LED驅(qū)動(dòng),點(diǎn)亮D1和D2 */
}
else
{
DriveLED(0x0002); /* LED驅(qū)動(dòng),熄滅D1點(diǎn)亮D2 */
}
}
當(dāng)我把程序改成這樣的時(shí)候,出了一點(diǎn)問(wèn)題,不能呼吸,變成閃爍了!等等,先把LED驅(qū)動(dòng)部分發(fā)一下:
/******************************************************
* 函數(shù)名稱(chēng):SendData
* 函數(shù)功能:74HC595數(shù)據(jù)的發(fā)送
* 入口參數(shù):unsigned int uiDataOne, unsigned int uiDataTwo
* 出口參數(shù):void
*******************************************************/
void SendData(unsigned char ucDataOne, unsigned char ucDataTwo)
{
unsigned int i = 0;
/* 將片選信號(hào)置為低電平 */
HC595RCK = 0;
/* 輸入第一個(gè)數(shù)據(jù):uiDataOne */
for (i = 0; i < 8; i++)
{
/* 給出脈沖信號(hào),首先將CLK置為0 */
HC595CLK = 0;
if (0 != (ucDataOne & 0x80))
{
HC595DATA = 1;
}
else
{
HC595DATA = 0;
}
/* 給出脈沖信號(hào),首先將CLK置為1 */
HC595CLK = 1;
/* 準(zhǔn)備第二個(gè)數(shù)據(jù) */
ucDataOne = ucDataOne << 1;
}
/* 輸入第二個(gè)數(shù)據(jù):uiDataTwo */
for (i = 0; i < 8; i++)
{
/* 給出脈沖信號(hào),首先將CLK置為0 */
HC595CLK = 0;
if (0 != (ucDataTwo & 0x80))
{
HC595DATA = 1;
}
else
{
HC595DATA = 0;
}
/* 給出脈沖信號(hào),首先將CLK置為1 */
HC595CLK = 1;
/* 準(zhǔn)備第二個(gè)數(shù)據(jù) */
ucDataTwo = ucDataTwo << 1;
}
/* 將片選信號(hào)置為高電平 */
HC595RCK = 1;
}
/********************************************************
* 函數(shù)名稱(chēng):DriveLED
* 函數(shù)功能:595驅(qū)動(dòng)程序是分兩個(gè)數(shù)據(jù)發(fā)的,
* 本函數(shù)把它合并成一個(gè)數(shù)據(jù)
* 入口參數(shù):uiData:16顆LED需要顯示的數(shù)據(jù)
* 出口參數(shù):NULL
*******************************************************/
void DriveLED(unsigned int uiData)
{
SendData(uiData >> 8,uiData);
}
繼續(xù)剛剛的問(wèn)題,呼吸燈變成閃爍了,怎么回事呢?在程序邏輯上是沒(méi)有問(wèn)題的,
我們只是更改了LED的驅(qū)動(dòng)部分,看來(lái)就是LED驅(qū)動(dòng)的問(wèn)題了!先來(lái)Debug看一下,執(zhí)行
DriveLED這個(gè)函數(shù),時(shí)間是接近400微妙,循環(huán)200次,就是差不多80毫秒,那么LED的
閃爍頻率為12.5HZ(都是大概的值,沒(méi)有精確計(jì)算),還不足以形成視覺(jué)暫留現(xiàn)象。
那怎么辦呢,減少循環(huán)次數(shù)為50,頻率增大到50HZ左右,像這樣:
for(i = 0; i < 50; i++)
{
/* 通過(guò)修改ucNum的值,就可以改變占空比 */
if(i < ucNum)
{
DriveLED(0x0003); /* LED驅(qū)動(dòng),點(diǎn)亮D1和D2 */
}
else
{
DriveLED(0x0002); /* LED驅(qū)動(dòng),熄滅D1點(diǎn)亮D2 */
}
}
經(jīng)過(guò)驗(yàn)證!成功了!
如有錯(cuò)誤的地方,希望大家批評(píng)指正!
作者: dely2009 時(shí)間: 2015-6-14 10:42
學(xué)習(xí)的是一種思維的方法,感覺(jué)挺好,收藏待練習(xí)
作者: 我的MCU 時(shí)間: 2015-6-20 17:40
剛剛驗(yàn)證了一下,確實(shí)可以實(shí)現(xiàn),樓主厲害
作者: 許生 時(shí)間: 2019-7-9 16:45
樓主我也遇到麻煩為啥用PWM。調(diào)光的呼吸燈的程序變成流水燈程序的一個(gè)函數(shù)調(diào)用的形式。結(jié)果只有流水沒(méi)有呼吸。
求救大佬:'(
#include"reg52.h"
#include<intrins.h>
typedef unsigned int u16;
typedef unsigned char u8;
sbit led1=P2;
int PWM_Low,Clock=500;
#define led P2
void delay(u16 a)
{while(a--);
}
void main1(int t)
{
for(PWM_Low=Clock;PWM_Low>0;PWM_Low--)
{t=1;
delay(PWM_Low);
{int b;
for (b=0;b<PWM_Low;b++);}
t=0;
delay(Clock-PWM_Low);
{int b;
for (b=0;b<Clock-PWM_Low;b++);}
} }
void main()
{u8 i,t,t1,t2;
t1=0xfe;
t2=0x7f;
for(i=0;i<4;i++)
{t=t1&t2;
led=t;
main1(t);
delay(50000);
t1=_crol_(t1,1);
t2=_cror_(t2,1);} }
了
歡迎光臨 (http://www.zg4o1577.cn/bbs/) |
Powered by Discuz! X3.1 |
主站蜘蛛池模板:
国产精品不卡
|
日本网站免费观看
|
亚洲高清视频在线
|
91伊人
|
365夜爽爽欧美性午夜免费视频
|
日p视频免费看
|
在线观看国产
|
伊伊综合网
|
亚洲高清av在线
|
九九热re
|
国产欧美三区
|
91黄色片免费看
|
一级国产精品一级国产精品片
|
一级毛片在线看
|
av大片|
欧美精品国产精品
|
青草福利
|
国产日韩精品视频
|
亚洲91视频|
国产一区二区三区免费观看在线
|
日韩中文字幕一区二区
|
午夜免费av
|
日韩免费福利视频
|
欧美黄色一区
|
免费a级毛片在线播放
|
男人天堂99|
日韩av在线免费
|
日本三级电影免费
|
亚洲成人中文字幕
|
欧美在线一级
|
日韩中文字幕一区
|
在线观看免费av网站
|
久久久精品一区二区
|
国产精品国产a级
|
天天操天天怕
|
中文精品视频
|
99免费在线|
欧美成年黄网站色视频
|
欧美精品国产一区二区
|
日韩成人免费视频
|
一区二区视频
|