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

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

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

水滴效果實現和講解

[復制鏈接]
跳轉到指定樓層
樓主
ID:357406 發表于 2018-6-23 20:01 | 只看該作者 回帖獎勵 |倒序瀏覽 |閱讀模式
簡介
學習嵌入式第一個例子通常都是控制一個 LED 亮滅,然后是花樣繁多的流水燈,但不管燈的花樣如何變化,單個 LED 的亮度沒有變化,只有亮、滅兩個狀態,本章我們實現如何控制 LED 的亮度。
1 什么是 PWM
脈沖寬度調制(Pulse Width Modulation,簡稱 PWM),是利用微處理器的數字輸出來對模擬電路進行控制的一種技術。在本章的應用中可以認為 PWM 就是一種方波。比如圖 1:
file:///C:\Users\楊磊\AppData\Local\Temp\ksohtml\wpsCB4D.tmp.jpg
1 方 波是周期為 10ms,占空比為 60%的 PWM。
占空比:高電平在一個周期之內所占的時間比率。
2 硬件設計
在例說 51 單片機的第三章,我們講過如何控制開發板上 LED 的亮滅。首先譯碼器輸出端
LEDS6 為低,T10 導通,給 8 LED 供電,然后通過緩沖器 8 個輸出端 BD0~BD7 的控制 LED 的亮滅(低亮高滅)。
file:///C:\Users\楊磊\AppData\Local\Temp\ksohtml\wpsCB6D.tmp.png
2 LED 硬件連接


如果 BD 口輸出高低不斷變化,則 LED 會閃爍;如果這種高低電平變化非常快,由于人的視覺暫留現象,LED 就會出現不同的亮度。
3 軟件設計
3.1 PWM 能否控制亮度
下面我們就用實踐驗證 PWM 是否能夠控制 LED 的亮度,測試代碼如下:
程序清單 L1: 驗證 PWM 能否控制 LED 的亮度
#include <reg52.h>
#include "my_type.h"
#include "hw_config.h"
void main(void)
{
u8 i = 0;
//使能獨立 LED 的供電,即 LEDS6 輸出低電平LEDEN = 0;
ADDR0 = 0;
ADDR1 = 1;
ADDR2 = 1;
ADDR3 = 1;
//第一個 LED 亮P0 = 0xFE;
while(1)
{
for(i=0; i<250; i++) //第 22 行
{
if(i<10)
{
P0 &= 0xFD;        //第二個燈亮
}
else


{
P0 |= 0x02;        //第二個燈滅
}
} //第 32 行
}
}
L1(22-32) :這段代碼實現 P0.1 輸出占空比為 96%的方波,而 P0.0 恒為低。
P0.1 輸出如圖 3 所示(受紙張限制,圖中高低電平長度比例和實際有偏差)。
file:///C:\Users\楊磊\AppData\Local\Temp\ksohtml\wpsCB6E.tmp.jpg
3
下載驗證:從開發板上可以看到運行效果,D1 D2 亮。這里說明一點:當 P0 輸出低電平時 LED 亮,所以,PWM 的占空比越小越亮)。
3.2 產生 8 個亮度級別
3.1 節的例子證實了我們的設想,PWM 可控制 LED 的亮度,下面我們設計幾組占空比不同的 PWM,看看對 LED 亮度的控制效果。代碼如下:
程序清單 L2:不同占空比對 LED 亮度的控制
#include <reg52.h>
#include "hw_config.h"
#include "my_type.h"
//亮度級別表
code u8 LightLevel[8]={0,1,2,4,8,16,32,64};
void main(void)
{
u8 i = 0; u8 j = 0; u8 k = 0;
u8 temp = 0;


//使能獨立 LED 的供電,即 LEDS6 輸出低電平LEDEN = 0;
ADDR0 = 0;
ADDR1 = 1;
ADDR2 = 1;
ADDR3 = 1;
//開始全滅P0 = 0xFF;
while(1)
{
//P0 端口輸出 8 組占空比不同的 PWM for(i=0; i<64; i++) //第 29 行
{
for( j=0; j<8; j++)
{
if(LightLevel[ j] <= i)
{


}
else
{
}
}
temp |= (1<<j);
temp &= ~(1<<j);


P0 = temp;
}
} //第 45 行
}
L2(29-45).此段程序是讓 P0 口輸出 8 組占空比不同的 PWM,如圖 4:


file:///C:\Users\楊磊\AppData\Local\Temp\ksohtml\wpsCB8F.tmp.jpg
4
下載驗證:從開發板上可以看到運行效果,從 D1 到 D8 的亮度逐漸增大。
3.3 水滴下落效果
根據 PWM 可控制 LED 亮度的原理,我們用 8 個 LED 實現水滴下落的效果。第一步,水滴逐漸變大,用 D1 從暗變亮模擬;第二步,水滴下落,帶有拖尾效果,LED 逐個亮,移動速度加快,且越靠前的 LED 亮度越大。
程序清單 L3 水滴流水燈
#include <reg52.h>
#include "hw_config.h"
#include "my_type.h"
//亮度級別表
code u8 LightLevel[8]={0,1,2,4,8,16,32,64};
//水滴時間,實現加速效果
code u8 LightTime[16]={16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1};
void main(void)
{
u8 i,j,k;


u8 temp,count; u8 state;
//使能獨立 LED 的供電,即 LEDS6 輸出低電平LEDEN = 0;
ADDR0 = 0;
ADDR1 = 1;
ADDR2 = 1;
ADDR3 = 1;
while(1)
{
//開始全滅P0 = 0xFF;
//---------------水滴逐漸變大(第一個 LED 亮度逐漸變大)--------- for(i=0; i<64; i++)
{
//一個亮度級別發送 64 個脈沖for( j=0; j<64; j++)
{
P0 = 0xFE;
//以 i 為亮度級別,隨著 i 的增大,占空比增大for(k=0; k<64; k++)
{
if(k > i)
{
P0 = 0xFF;
}
}
}
}
//----------------------水滴降落過程---------------------
for(state=0; state<16; state++)
{


//每一狀態維持 LightTime[state]個脈沖for(count=0; count<=LightTime[state]; count++)
{
//temp 記錄 8 個 LED 的狀態,0 代表亮,1 代表滅temp = 0x00;
//一個脈沖長度 j 從 0 到 63 for( j=0; j<64; j++)
{
//根據亮度表,依次確定 8 個 LED 當前狀態,亮或滅for(k=0; k<8; k++)
{
//以 j 為亮度級別,每個 LED 亮度不一樣
if(LightLevel[k] == j)
{
temp |= (1 << k);
}
}
if(state <= 7)
{


}
else
{
}
}
}
file:///C:\Users\楊磊\AppData\Local\Temp\ksohtml\wpsCB90.tmp.png}
}
}
P0 = ~((~temp) >> (7-state));
P0 = ~((~temp) << (state-7));


L2(31-46).實現水滴變大效果,這段代碼的作用可用圖形表達,如圖 5:


file:///C:\Users\楊磊\AppData\Local\Temp\ksohtml\wpsCB91.tmp.jpg
5
控制 D1 由暗變亮,用了 64 個亮度級別,每個級別發送 64 個脈沖。
L2(49-81).實現水滴下落。代碼就不逐行解釋了,大家可根據注釋自己分析,主要說一下實現的方法。
定義 LED 有 8 個亮度級別,若用開發板上的 8 個 LED 表示,如圖 6:
file:///C:\Users\楊磊\AppData\Local\Temp\ksohtml\wpsCB92.tmp.png
6
圖中的紅色面積代表亮度程度。實現流水效果的方法就是:讓所有的亮度依次經過在所有  LED, 如圖 7:


file:///C:\Users\楊磊\AppData\Local\Temp\ksohtml\wpsCB93.tmp.png
7
狀態的持續時間從 0-15 逐漸減小,以模擬水滴加速。下載驗證:下載到開發板上,可以看到水滴下落效果。
3.4 定時器產生 PWM
前面 3 個例子中,我們用循環語句雖然能產生占空比不同的 PWM,但 PWM 的周期不好控制,對此,我們學習如何用定時器產生特定周期 PWM。關于 8051 定時器的使用方法,大家可以參考例說 51 單片機的 4 章和 5 章。
我們用定時器 0 產生 PWM,代碼如下:
程序清單 L4 定時器 0 產生 PWM
#include <reg52.h>
#include "hw_config.h"
#include "my_type.h"


//亮度級別表
code u8 LightLevel[8]={1,2,4,8,16,28,50,64};
//函數聲明
void timer0_init(void);
void main(void)
{
//使能獨立 LED 的供電,即 LEDS6 輸出低電平LEDEN = 0;
ADDR0 = 0;
ADDR1 = 1;
ADDR2 = 1;
ADDR3 = 1;
timer0_init();
while(1)
{
}
}
/********************************************************** 函數名稱:timer0_init
功        能:初始化定時器 0
**********************************************************/ void timer0_init(void)
{
TMOD = 0x01;                //運行模式 1 TH0                = 0xFF;        //10us 中斷TL0        = 0xFA;
EA        = 1;        //開啟中斷ET0        = 1;
TR0        = 1;        //啟動定時器


}
/************************************************************ 函數名稱:timer0_overflow
功        能:定時器 0 溢出中斷
************************************************************/ void timer0_overflow(void) interrupt TIMER0_OVERFLOW
{
u8 i,temp = 0; static u8 count = 0;
count++; count %= 64;
for(i=0; i<8; i++)
{
if(LightLevel <= count)
{


}
else
{
}
}
temp |= (1<<i);
temp &= ~(1<<i);


P0 = temp;
TR0 = 0;
TH0 = 0xFF;        //重新賦值TL0 = 0xF7;
TR0 = 1;
}
L4(32).初始化定時器 0,沒 10us 產生一次中斷。
L4(55-65).控制輸出 8 組不同占空比的 PWM。這段代碼功能和程序清單 2 中的功        能一致。


下載驗證:下載到開發板上,可以看到 D1 到 D8 亮度逐漸增大。
3.5 亮度不同的點陣
學習了用定時器產生 PWM,我們可以控制更多的 LED,比如 LED 點陣的亮度。下面的例子實現 LED 點陣每行的亮度都不同。
程序清單 5 亮度不同的點陣
#include <reg52.h>
#include "hw_config.h"
#include "my_type.h"
//亮度級別表
code u8 LightLevel[8]={1,2,4,8,16,32,50,64};
//函數聲明
void timer0_init(void);
void main(void)
{
//使能控制點陣的譯碼器 LEDEN = 0;
ADDR3 = 0;
timer0_init();
while(1)
{}
}
/***************************************************************** 函數名稱:timer0_init
功        能:初始化定時器 0
*****************************************************************/ void timer0_init(void)
{
TMOD = 0x01;                //運行模式 1 TH0        = 0xFF;        //中斷時間 10us


TL0
= 0xF7
EA ET0 TR0
}
= 1;
= 1;
= 1;
//開啟中斷
//啟動定時器
/***************************************************************** 函數名稱:timer0_overflow
功        能:定時器 0 溢出中斷
*****************************************************************/ void timer0_overflow(void) interrupt TIMER0_OVERFLOW
{
u8 i;
u8 p1_value = 0;
static u8 state = 0;        //點陣狀態(掃描行數) static u8 count = 0;
TR0 = 0;
count++; if(count == 64)
{
state++; state %= 8;
count = 0;
}
if(count < LightLevel[state])
{


}
else
{
}
P0 = 0x00;
P0 = 0xFF;


p1_value = P1 & 0xf8; p1_value   |=   state; P1 = p1_value;
TH0 = 0xFF;        //重新賦值TL0 = 0xFA;
TR0 = 1;
}
L5(28).初始化定時器,每 10us 中斷一次。
L5(51-57).每中斷 64 次,點陣掃描移動到下一行,用 state 記錄當前行數。
L5(59-66).掃描每一行輸出的 PWM 都不一樣,使用的方式和處理獨立 LED 一致。L5(68-70).輸出點陣對應的位碼。
下載驗證:下載到開發板上,可以看到運行效果,點陣第一行最暗,越往下越亮。
3.6 點陣模擬音樂頻譜分析效果
在很多音樂播放軟件上,都有頻譜分析的圖形,如圖 8:
file:///C:\Users\楊磊\AppData\Local\Temp\ksohtml\wpsCB94.tmp.png
8
我們用也可以模擬相似的圖形,代碼如下:
程序清單 6:點陣模擬音樂頻譜分析
#include <reg52.h>
#include "hw_config.h"
#include "my_type.h"
// 頻 譜 波 形 表     code u8 Wave[16][8]=
{
{0xFF,0xFF,0xFF,0xFF,0xFE,0xBB,0xFE,0xAA},
{0xFF,0xFF,0xFF,0xFE,0xFB,0xAE,0xFA,0xAA},
{0xFF,0xFF,0xFF,0xFE,0xEB,0xBE,0xEA,0xAA},
{0xFF,0xFF,0xFE,0xFB,0xAF,0xFE,0xAA,0xAA},
{0xFF,0xFE,0xFB,0xBE,0xEA,0xBA,0xAA,0xAA},
{0xFF,0xFE,0xBB,0xEE,0xBA,0xBA,0xAA,0xAA},


{0xFE,0xBB,0xEE,0xBA,0xAA,0xAA,0xAA,0xAA},
{0xBA,0xEF,0xBE,0xAA,0xAA,0xAA,0xAA,0xAA},
{0xEE,0xBB,0xFE,0xAA,0xAA,0xAA,0xAA,0xAA},
{0xEE,0xBB,0xFE,0xEA,0xAA,0xAA,0xAA,0xAA},
{0xFE,0xEB,0xBE,0xFE,0xAA,0xAA,0xAA,0xAA},
{0xFF,0xEE,0xBB,0xFF,0xAE,0xAA,0xAA,0xAA},
{0xFF,0xFE,0xAF,0xFB,0xEE,0xAA,0xAA,0xAA},
{0xFF,0xFF,0xFE,0xBB,0xEF,0xBA,0xAA,0xAA},
{0xFF,0xFF,0xFF,0xFE,0xAB,0xFF,0xEE,0xAA},
{0xFF,0xFF,0xFF,0xFF,0xFE,0xEB,0xBE,0xAA}
};
//亮度級別表
code u8 LightLevel[8]={1,2,4,8,16,32,50,64};
//函數聲明
void timer0_init(void);
void main(void)
{
//使能控制點陣的譯碼器 LEDEN = 0;
ADDR3 = 0;
timer0_init();
while(1)
{
}
}
/***************************************************************** 函數名稱:timer0_init
功        能:初始化定時器 0
*****************************************************************/ void timer0_init(void)


{
TMOD = 0x01;                //運行模式 1 TH0                = 0xFF;        //10us 中斷TL0        = 0xFA;
EA        = 1;        //開啟中斷ET0        = 1;
TR0        = 1;        //啟動定時器
}
/***************************************************************** 函數名稱:timer0_overflow
功        能:定時器 0 溢出中斷
*****************************************************************/ void timer0_overflow(void) interrupt TIMER0_OVERFLOW
{
u8 i;
u8 p1_value = 0;
static u8 state = 0;        //點陣狀態(掃描行數) static u8 count = 0;
static u8 wave_state = 0;        //波形狀態static u16 wave_count = 0;
TR0 = 0;
//每中斷 1000 次,改變波形狀態wave_count++;   if(wave_count == 1000)
{
wave_count = 0; wave_state++; wave_state  %= 16;
}
//每中斷 64 次,改變掃描的行


count++; if(count == 64)
{
state++; state %= 8;
count = 0;
}
if(count < LightLevel[state])
{


}
else
{
}
P0 = Wave[wave_state][state];
P0 = 0xFF;


//輸出位碼
p1_value = P1 & 0xf8; p1_value |= state;
P1 = p1_value;
//定時器重新賦值 TH0 = 0xFF;
TL0 = 0xF7; TR0 = 1;
}
L6(6).波形表,共 16 個狀態,每個狀態下有 8 個數據,即一個點陣界面。掃描點        陣時循環發送,實現動態效果。
L6(77-83).每中斷 1000 次,更換一個狀態。
L6(86-101).和 L5 的功能一致,只是點陣段碼輸出的數據變成了波形表。下載驗證:下載程序到開發板,可以看到,點陣顯示的頻譜分析效果。

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

使用道具 舉報

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

本版積分規則

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

Powered by 單片機教程網

快速回復 返回頂部 返回列表
主站蜘蛛池模板: 成人免费黄色 | 成人在线观看亚洲 | 精品综合久久久 | 午夜精品久久 | 在线免费观看黄色 | 国产精品区二区三区日本 | 99久久日韩精品免费热麻豆美女 | 日韩精品视频中文字幕 | 日韩欧美国产精品一区二区 | 成人精品鲁一区一区二区 | 国产一区二区三区在线看 | 国产亚洲一级 | 欧美福利网站 | 91久久夜色精品国产网站 | 黄色永久免费 | 日韩免费视频一区二区 | 在线视频一区二区 | 日本精品一区二区在线观看 | 精品三区 | 欧美激情精品久久久久久免费 | av一二三四 | 免费a网站 | 国产精品a一区二区三区网址 | 一级片免费在线观看 | 婷婷色国产偷v国产偷v小说 | 欧美一级片 | 日本超碰| www天天操 | 成人精品久久久 | 亚洲第一在线 | 亚洲综合一区二区三区 | 久久尤物免费一区二区三区 | 久久久久网站 | 国产精品免费一区二区三区四区 | 激情五月综合网 | 日本视频在线播放 | 中文字幕的av | 欧美成人免费在线视频 | 91精品国产综合久久久久 | 亚洲一区二区三区四区视频 | 婷婷开心激情综合五月天 |