點擊上方"嵌入式開發(fā)圈" 記得關(guān)注我們哦! 微信公眾號:嵌入式開發(fā)圈
關(guān)注可了解更多的教程。問題或建議,請公眾號留言;
如果你覺得本文對你有幫助,歡迎贊賞
在嵌入式項目開發(fā)中,LED燈的操作是一定要會的,也是基礎(chǔ)中的基礎(chǔ),比如用51單片機寫個跑馬燈,這不簡單嘛,定義一個數(shù)組把那8個跑馬燈存起來,然后搞個for循環(huán)不就可以了嘛,但是,實際工作開發(fā)中寫一個跑馬燈可不像學(xué)校和書本上那么簡單噢,往往最簡單的東西,有可能也是最復(fù)雜的。
現(xiàn)在需求是這樣的,要求實現(xiàn)以下形式的流水燈:跑馬燈在這個表格中是一位一位進行存儲的,如果要一行全亮,那么寫0xff,燈就全亮了,寫0x00,燈就全滅了。
要求從led1流水到led100這個燈,如圖所示,也就是實現(xiàn)100個燈的跑馬燈操作。那如何實現(xiàn)呢?有人肯定會說定義十個數(shù)組就行啦,用填表的方法。然后搞十個for循環(huán)來實現(xiàn),那么可取不?可取,但是太麻煩啦,因為這是用空間來換時間,雖然能達到效果,但是就太浪費內(nèi)存空間了,效率也是很低的。
那么如何快速處理這個問題呢?
我們可以考慮位運算與循環(huán)的結(jié)合,首先思考一下,led是從第1個開始一直流到第100個,一共有十行,每行有十個,那么我們就可以定義一個for循環(huán)來循環(huán)相應(yīng)的行數(shù),設(shè)定led燈的初始位置,然后用移位算法,移動8位就換下一行,一個led相當于1bit,這樣的話,兩個for循環(huán)就可以搞定了,接下來我們用C語言來模擬這個過程。
1void delay()
2{
3 int i , j ;
4 for(i = 0 ; i < 1000 ; i++)
5 for(j = 0 ; j < 8000 ;j++);
6}
7//跑馬燈從高位到低位流
8void test_low_to_high_bit()
9{
10 int i , j ;
11 int tick ;
12 static int ledbuf[10] ;
13 for(i = 0 ; i < 10 ; i++)
14 {
15 //設(shè)定每次開始的位置,從0x01開始
16 ledbuf[i] = 0x01 ;
17 for(j = 0 ; j < 8 ; j++)
18 {
19 printf("%p ",ledbuf[i]);
20 //每次左移一位,左移八次
21 ledbuf[i] <<= 1 ;
22 delay() ;
23 }
24 putchar('\n');
25 //將數(shù)組清0,等待進入下一行
26 ledbuf[i] = 0 ;
27 }
28}
29//跑馬燈從低位到高位流
30void test_high_to_low_bit()
31{
32 int i , j ;
33 int tick ;
34 static int ledbuf[10] ;
35 for(i = 0 ; i < 10 ; i++)
36 {
37 //設(shè)定從高位的第一個LED燈的位置
38 ledbuf[i] = 0x80 ;
39 for(j = 0 ; j < 8 ; j++)
40 {
41 printf("%p ",ledbuf[i]);
42 //將數(shù)組的第一個元素右移一位,一共右移八位
43 ledbuf[i] >>= 1 ;
44 delay() ;
45 }
46 putchar('\n');
47 //將數(shù)組清0,等待進入下一行
48 ledbuf[i] = 0 ;
49 }
50}
51int main(void)
52{
53 test_low_to_high_bit() ; //測試從低位往高位輸出
54 putchar('\n');
55 test_high_to_low_bit() ; //測試從高位往低位輸出
56 return 0 ;
57}
運行結(jié)果:
運行結(jié)果很明顯,第一個是從第一位移位到第八位,移動了8次,移動了十行。第二個是反著來的,從高位到低位輸出。
如果,現(xiàn)在有個需求改了,那個表中,我要指定的LED亮,其它的不亮,然后實現(xiàn)流水燈的效果,那要如何去寫這個程序?
面對一個無規(guī)律的數(shù)組表,假設(shè)這個數(shù)組表存放的是100個LED燈,一會想要一個個閃爍,一會想要一排排閃爍,一會亂序閃爍,那么,思考這樣一個位移算法似乎是不可取的,所以,引入一個新的概念----查表法。
假設(shè)還是這么一張表,如圖所示。存放著100個LED燈。
1#include <stdio.h>
2#include <stdlib.h>
3#include <unistd.h>
4//這里的行可以自由寫,這樣就不受限制,想做出什么樣的效果都可以。
5int array[][10] = {
6
7 0x03,0x00,0x00,0x00,0x00,//第一列
8 0x00,0x02,0x00,0x00,0x00,
9
10 0x0C,0x00,0x00,0x00,0x00,//第二列
11 0x00,0x04,0x00,0x00,0x00,
12
13 0x10,0x00,0x00,0x00,0x00,//第三列
14 0x00,0x08,0x00,0x00,0x00,
15
16 0x60,0x00,0x00,0x00,0x00,//第四列
17 0x00,0x10,0x00,0x00,0x00,
18
19 0x80,0x01,0x00,0x00,0x00,//第五列
20 0x00,0x20,0x00,0x00,0x00,
21//多寫一行,用來標志結(jié)束
22 0xAA,0x55,0x00,0x00,0xC0,//end
23 0x00,0x00,0x00,0x00,0x00,
24
25};
26//輸出表中的數(shù)據(jù)
27void Print_led(int *array)
28{
29 int i;
30 for(i = 0; i < 10; i++)
31 {
32 printf("%3x", *(array+i));
33 }
34 printf("\n");
35}
36
37//延時函數(shù)
38void delay_500ms(void)
39{
40 usleep(500000);
41}
42
43int main(void)
44{
45 int i,j;
46 int tick;
47 int count = 0;
48 //如果當數(shù)組第count行第0列等于0xAA,或者第count行第1列等于0x55時
49 //那么就退出,否則就循環(huán)執(zhí)行遍歷數(shù)據(jù)
50 while(array[count][0] != 0xAA || array[count][1] != 0x55)
51 {
52 //以首元素每次向后偏移10個字節(jié)
53 Print_led((int *)(&array[0][0]+count*10) );
54 delay_500ms();
55 count++;
56 }
57 return 0;
58}
運行結(jié)果:
這樣,只需要往表里填想要輸出的數(shù)據(jù),就可以成功輸出了,這種方法就是以空間換時間的查表法,是嵌入式開發(fā)中最常用也是最實用的方法,這種方法對于算法掌握不是特別熟練的工程師來說是一種偷懶的辦法。
韋東山老師優(yōu)質(zhì)嵌入式學(xué)習(xí)干貨推薦:包括ARM裸機開發(fā)、Linux設(shè)備驅(qū)動程序、Linux應(yīng)用程序開發(fā)、Android系統(tǒng)學(xué)習(xí)、Linux設(shè)備樹等。
長期合作服務(wù)
深圳廣志創(chuàng)新科技有限公司
業(yè)務(wù)范圍:單片機軟件開發(fā)、項目工程開發(fā)、硬件電路設(shè)計、元器件供應(yīng)。本公司擁有智能家居,智能消防,消費類電子(移動電源、風(fēng)扇、玩具、廣告燈、加濕器等)等成熟開發(fā)方案。使用MCU范圍:8位單片機,32位單片機。
免責(zé)聲明:本文內(nèi)容由21ic獲得授權(quán)后發(fā)布,版權(quán)歸原作者所有,本平臺僅提供信息存儲服務(wù)。文章僅代表作者個人觀點,不代表本平臺立場,如有問題,請聯(lián)系我們,謝謝!