常用處理差異辦法
關(guān)于差異的處理,前文提到的全部采用uint8_t類型進(jìn)行設(shè)計(jì),比較保險(xiǎn)穩(wěn)妥,但數(shù)據(jù)量大、項(xiàng)目需求復(fù)雜的時(shí)候,未必就能滿足,所以還是需要正面應(yīng)對(duì)這些硬性問(wèn)題。
這里整理出幾個(gè)簡(jiǎn)單轉(zhuǎn)換的過(guò)程。
1. 多個(gè)uint8_t轉(zhuǎn)uint16_t/uint32_t
這個(gè)轉(zhuǎn)換很容易可以實(shí)現(xiàn),信手拈來(lái):
val_u16 = (val_u8_tmp1<<8) |val_u8_tmp2;
這里的轉(zhuǎn)基本都是把兩個(gè)uint8_t類型“組合”成uint16_t或者uint32_t,而實(shí)際項(xiàng)目工程中,多是對(duì)uint8_t類型的數(shù)據(jù)流進(jìn)行轉(zhuǎn)換,并且是轉(zhuǎn)換部分?jǐn)?shù)據(jù),因此這里直接寫(xiě)成宏定義,便于開(kāi)發(fā)移植:
小端模式轉(zhuǎn)成uint16_t/uint32_t
大端模式轉(zhuǎn)成uint16_t/uint32_t
分析小端模式轉(zhuǎn)成uint16_t類型的數(shù)據(jù),首先將這一長(zhǎng)串的宏拆分然后逐步去理解:
實(shí)際是((uint16_t)*(volatile uint8_t*)((ptr)+1)<<8)和(uint16_t)*(volatile uint8_t*)(ptr)兩個(gè)數(shù)據(jù)進(jìn)行位或的運(yùn)算。
1.右半邊 (volatileuint8_t*)(ptr)是將ptr所指地址強(qiáng)轉(zhuǎn)為volatile uint8_t*類型;
2.然后是使用*(volatileuint8_t*)(ptr)根據(jù)地址從內(nèi)存中取出該字節(jié);
3.緊接著將取出的一字節(jié)數(shù)據(jù)使用(uint16_t)強(qiáng)制類型轉(zhuǎn)換成uint16_t類型。
同樣的原理,
1.左半邊(volatileuint8_t*)((ptr)+1)是將prt所指地址的下一個(gè)內(nèi)存單元強(qiáng)轉(zhuǎn)為volatile uint8_t*類型;
2.然后是使用*(volatileuint8_t*)((ptr)+1) 根據(jù)地址從內(nèi)存中取出該字節(jié);
3.緊接著將取出的一字節(jié)數(shù)據(jù)使用(uint16_t)強(qiáng)制類型轉(zhuǎn)換成uint16_t類型,再左移8位處理。
最后將兩個(gè)結(jié)果做位或運(yùn)算,即實(shí)現(xiàn)了“組合”,返回uint16_t類型結(jié)果。
以上過(guò)程分析的比較啰嗦,并且其中做的一些強(qiáng)轉(zhuǎn)和volatile修飾也是很有必要的,因?yàn)樵O(shè)計(jì)的宏要想可靠,還考慮到在有中斷、有事件處理的系統(tǒng)里,對(duì)數(shù)據(jù)操作還是需要謹(jǐn)慎些!
2.單個(gè)uint16_t/uint32_t轉(zhuǎn)uint8_t
單個(gè)字/雙字轉(zhuǎn)成字節(jié),使用場(chǎng)景比較少,最簡(jiǎn)單方式直接利用位與(&)和移位運(yùn)算。
取低字節(jié):
val_u8_tmp = val_u16&0xFF;
取高字節(jié):
val_u8_tmp =(val_u16>>8)&0xFF;
3.對(duì)uint16_t/uint32_t類型進(jìn)行字/雙字內(nèi)自轉(zhuǎn)
其原理一樣是操作內(nèi)存地址的方式,寫(xiě)成宏定義,方便使用。
其轉(zhuǎn)換的結(jié)果是將原數(shù)據(jù)翻轉(zhuǎn)成相反的端模式。
總結(jié),項(xiàng)目的開(kāi)發(fā)細(xì)節(jié)問(wèn)題弄清楚了,對(duì)后續(xù)的開(kāi)發(fā)工作也是磨刀不誤砍柴工,并且在有通信需求時(shí),尤其有必要做好通信協(xié)議的溝通協(xié)調(diào),設(shè)計(jì)一套雙方通用的協(xié)議結(jié)構(gòu),對(duì)后續(xù)開(kāi)發(fā)有著規(guī)范可循,對(duì)解決Bug也可以快速定位問(wèn)題!