前言
(1)在嵌入式程序設(shè)計(jì)中,我們常常會(huì)要對(duì)各類傳感器進(jìn)行數(shù)據(jù)存儲(chǔ)。大多時(shí)候的傳感器,例如紅外光傳感器,返回的數(shù)據(jù)要么是0,要么是1。因此,只需要一bit就能夠存儲(chǔ)。而很多人卻常常使用char型數(shù)組存儲(chǔ),這樣真正申請(qǐng)到的內(nèi)存只使用了八分之一。對(duì)于MCU這種空間寶貴的微型控制器而言,這是對(duì)內(nèi)存的極大浪費(fèi)。
(2)因此,我在此介紹一個(gè)初學(xué)C語(yǔ)言時(shí)候講解的技術(shù)——位域,提高空間的利用率。
(3)在入門嵌入式開(kāi)發(fā)的時(shí)候,大多數(shù)人都是做一個(gè)循跡小車,而進(jìn)行循跡,就需要對(duì)光電傳感器進(jìn)行偏差量化。根據(jù)偏差量化的值進(jìn)行輸出相應(yīng)的PWM。(如果是開(kāi)環(huán)控制)進(jìn)行偏差量化,使用聯(lián)合體,無(wú)疑是最高效的方式。
優(yōu)化兩種狀態(tài)變量存儲(chǔ)
存儲(chǔ)
(1)例如,我這個(gè)小項(xiàng)目,需要使用上一個(gè)12路循跡模塊,一個(gè)紅外遙控器,一個(gè)觸摸模塊(有一種觸摸模塊你手摸上去,就會(huì)返回指定電平)。
(2)為了高效存儲(chǔ)這些只有兩個(gè)狀態(tài)的變量。我們可以按照下面方式進(jìn)行存儲(chǔ)。
/*--- 存儲(chǔ)結(jié)構(gòu)設(shè)計(jì) ---*/
typedef struct
{
uint8_t track_bit1 :1;
uint8_t track_bit2 :1;
uint8_t track_bit3 :1;
uint8_t track_bit4 :1;
uint8_t track_bit5 :1;
uint8_t track_bit6 :1;
uint8_t track_bit7 :1;
uint8_t track_bit8 :1;
uint8_t track_bit9 :1;
uint8_t track_bit10 :1;
uint8_t track_bit11 :1;
uint8_t track_bit12 :1; //上面都是灰度傳感器控制位
uint8_t IRDS_bit13 :1; //紅外遙控器控制位
uint8_t Touch_bit14 :1; //觸摸模塊
uint8_t bit15 :1; //下面2bit保留
uint8_t bit16 :1;
}Bit_field;
訪問(wèn)
(1)現(xiàn)在我們知道如何存儲(chǔ)這個(gè)如何訪問(wèn)呢?這個(gè)其實(shí)是C語(yǔ)言位域基礎(chǔ)知識(shí),但是為了防止有一些大學(xué)這部分不教,所以我還是講一下。
Bit_field two_status_sensor;
two_status_sensor.track_bit1 = readpin(1); //使用你當(dāng)前的MCU讀取引腳電平函數(shù)
two_status_sensor.track_bit2 = readpin(2); //使用你當(dāng)前的MCU讀取引腳電平函數(shù)
two_status_sensor.IRDS_bit13 = readpin(13); //使用你當(dāng)前的MCU讀取引腳電平函數(shù)
if(two_status_sensor.IRDS_bit13 == 1) //假設(shè)遙控器被按下,引腳為高電平
{
//...
}
利用共用體進(jìn)行偏差量化
利用Excel可視化偏差量化
(1)現(xiàn)在我們使用位域?qū)@種2值變量有了一個(gè)很好的存儲(chǔ)了。但是我們都知道,想循跡模塊需要對(duì)數(shù)據(jù)進(jìn)行處理。而如何進(jìn)行偏差量化又是一個(gè)問(wèn)題。在此,我推薦使用excl表格,這樣能夠非常直觀的對(duì)數(shù)據(jù)處理。
(2)我們有幾路循跡,就需要寫(xiě)幾格,一個(gè)16進(jìn)制數(shù)據(jù)之后方便編程,最后是我們偏差量化值,2進(jìn)制那一格是為了方便轉(zhuǎn)換成16進(jìn)制而寫(xiě)。
(3)美化表格
(4)將表格填充
(5)然后自己填寫(xiě)自己設(shè)定的偏差量化值,并且將傳感器有反應(yīng)的地方用藍(lán)色填充,這樣有利于閱讀。
將偏差量化編程出來(lái)
大部分人寫(xiě)的垃圾代碼
(1)用Excel將傳感器的數(shù)值偏差量化出來(lái)了,但是如何編程了?想必很多同學(xué)使用下面這種非常低效方法進(jìn)行偏差量化。
char deviation; //存儲(chǔ)偏差量化值
if(two_status_sensor.track_bit1 == 1) deviation = -11;
if(two_status_sensor.track_bit1 == 1 && two_status_sensor.track_bit2) deviation = -10;
if(two_status_sensor.track_bit1 == 1) deviation = -9;
//...
(2)這種方法,編寫(xiě)起來(lái)非常麻煩,而且不方便閱讀,可以說(shuō),寫(xiě)的相當(dāng)?shù)睦?/p>
利用聯(lián)合體管控標(biāo)志位
(1)為了提高代碼的觀賞性,同時(shí)方便我們進(jìn)行調(diào)試。我認(rèn)為我們可以使用聯(lián)合體的方法優(yōu)化代碼。這樣之后,我們能夠發(fā)現(xiàn),對(duì)于偏差量化的值就能夠進(jìn)行非常好的管控。
/*--- 利用共用體優(yōu)化偏差量化 ---*/
typedef union //利用共用體優(yōu)化偏差量化
{
Bit_field sensor_value;
uint16_t state;
}_two_status_sensor;
/*--- 訪問(wèn)變量 ---*/
char deviation; //存儲(chǔ)偏差量化值的當(dāng)前值
_two_status_sensor two_status_sensor; //定義用于記錄傳感器的值
two_status_sensor.sensor_value.track_bit1 = readpin(1); //使用你當(dāng)前的MCU讀取引腳電平函數(shù)
//... 省略讀取傳感器的值過(guò)程
switch(two_status_sensor.state & 0x0FFF)//偏差量化,因?yàn)槭?2路循跡,所以只要低12位
{
case 0x0001:deviation=-11;break; //000000000001b
case 0x0003:deviation=-10;break; //000000000011b
//... 省略其他偏差量化過(guò)程
default://其它特殊情況單獨(dú)判斷
{
//...
}
}
利用帶參宏進(jìn)行標(biāo)志位判斷
(1)但是這個(gè)還能不能再次進(jìn)行優(yōu)化呢?肯定可以,我們知道,這個(gè)2值聯(lián)合體中,有一些是用于循跡,有些是用于遙控器,有些是用于觸摸芯片的。為了提高代碼的可閱讀性。我們是不是可以用幾個(gè)帶參宏來(lái)進(jìn)行定義呢?
/*--- 利用帶參宏進(jìn)行標(biāo)志位判斷 ---*/
#define track_state(x) x & 0x0FFF
#define IRDS_state(x) x & 0x1000
#define Touch_state(x) x & 0x2000
利用?:和條件編譯對(duì)提高代碼對(duì)硬件的適配程度
(1)我們有沒(méi)有發(fā)現(xiàn)一個(gè)問(wèn)題,上面循跡代碼,檢測(cè)到黑線是1。那么肯定有人會(huì)說(shuō)了,假如我硬件上檢測(cè)到黑線是低電平怎么辦呢?
(2)為了提高代碼對(duì)硬件的適配能力,于是我認(rèn)為可以使用條件編譯。
(3)因?yàn)椋煌腗CU讀取電平返回的不一定是0和1,有可能讀取到低電平是0,讀取到高電平是一個(gè)其他的非0值,例如5。所以為了防止1bit存儲(chǔ)不下導(dǎo)致溢出問(wèn)題。我們可以使用?:來(lái)處理。文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-657530.html
/*--- 提高代碼對(duì)硬件的適配能力 ---*/
#define track_active_level 1 //高電平有效寫(xiě)1,低電平有效寫(xiě)0
#if track_active_level
two_status_sensor.sensor_value.track_bit1 = readpin(1)!=0?0x01:0x00;
//... 其他11個(gè)同理
#else
two_status_sensor.sensor_value.track_bit1 = readpin(1)==0?0x01:0x00;
//... 其他11個(gè)同理
#endif
進(jìn)行錯(cuò)誤判斷,保護(hù)硬件,提高硬件的容錯(cuò)率
(1)看到上面的代碼,肯定有騷年覺(jué)得已經(jīng)很好了。但是,我們想想,如果循跡最終的結(jié)果返回的數(shù)據(jù)不是預(yù)期數(shù)據(jù)怎么辦?例如小車跑出去了。
(2)為了防止這種異常情況,保護(hù)硬件,我們可以加一個(gè)標(biāo)志位worse存儲(chǔ)錯(cuò)誤次數(shù)。如果次數(shù)超標(biāo)就強(qiáng)制停車。
(3)因?yàn)樾≤囇E可能只是剛好偏離路線一點(diǎn)點(diǎn),或者是硬件突然有點(diǎn)小問(wèn)題,所以我們還可以建立一個(gè)標(biāo)志位deviation_backup存儲(chǔ)偏差量化值的以往值。讓小車保持上一次的狀態(tài)運(yùn)行提高硬件容錯(cuò)率。文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-657530.html
/*--- 提高代碼對(duì)硬件的適配能力 ---*/
#define track_active_level 1 //高電平有效寫(xiě)1,低電平有效寫(xiě)0
#if track_active_level
two_status_sensor.sensor_value.track_bit1 = readpin(1)!=0?0x01:0x00;
//... 其他11個(gè)同理
#else
two_status_sensor.sensor_value.track_bit1 = readpin(1)==0?0x01:0x00;
//... 其他11個(gè)同理
#endif
/*--- 利用帶參宏進(jìn)行標(biāo)志位判斷 ---*/
#define track_state(x) x & 0x0FFF
#define IRDS_state(x) x & 0x1000
#define Touch_state(x) x & 0x2000
/*--- 利用共用體優(yōu)化偏差量化 ---*/
typedef union //利用共用體優(yōu)化偏差量化
{
Bit_field sensor_value;
uint16_t state;
}_two_status_sensor;
/*--- 訪問(wèn)變量 ---*/
char deviation; //存儲(chǔ)偏差量化值的當(dāng)前值
char deviation_backup,worse;//存儲(chǔ)偏差量化值的以往值,循跡錯(cuò)誤次數(shù)
_two_status_sensor two_status_sensor; //定義用于記錄傳感器的值
two_status_sensor.sensor_value.track_bit1 = readpin(1); //使用你當(dāng)前的MCU讀取引腳電平函數(shù)
//... 省略讀取傳感器的值過(guò)程
switch(track_state(two_status_sensor.state))//偏差量化,因?yàn)槭?2路循跡,所以只要低12位
{
case 0x0001:deviation=-11;worse/2;break; //000000000001b
case 0x0003:deviation=-10;worse/=2;break; //000000000011b
//... 省略其他偏差量化過(guò)程
default://其它特殊情況單獨(dú)判斷
{
deviation=deviation_backup;//如果是異常情況,就保持上一個(gè)狀態(tài)
worse++;
}
}
if(worse == 10) //如果多次循跡錯(cuò)誤,說(shuō)明出現(xiàn)問(wèn)題了,為了保護(hù)硬件,強(qiáng)制停車
{
//停車
}
到了這里,關(guān)于嵌入式設(shè)計(jì)中對(duì)于只有兩種狀態(tài)的變量存儲(chǔ)設(shè)計(jì),如何高效的對(duì)循跡小車進(jìn)行偏差量化的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!