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