# Camera OV7670 第05段 inline ~ __attribute__((always_inline))、CheckSum ```javascript= uint8_t lineBuffer [lineBufferLength]; // Two bytes per pixel 行緩衝區長度 uint8_t * lineBufferSendByte; //行緩衝區發送字節 bool isLineBufferSendHighByte; //這是行緩衝器發送高字節 bool isLineBufferByteFormatted; //這是行緩衝區字節格式化 uint16_t frameCounter = 0; //幀計數器 uint16_t processedByteCountDuringCameraRead = 0;//相機讀取期間處理的字節數 void commandStartNewFrame(uint8_t pixelFormat);//命令開始新幀 void commandDebugPrint(const String debugText); uint8_t sendNextCommandByte(uint8_t checksum, uint8_t commandByte); void sendBlankFrame(uint16_t color); //發送空白幀 inline void processNextGrayscalePixelByteInBuffer() __attribute__((always_inline)); //處理緩衝區中的下一個灰度像素字節 inline void processNextRgbPixelByteInBuffer() __attribute__((always_inline)); //處理緩衝區中的下一個RGB像素字節 inline void tryToSendNextRgbPixelByteInBuffer() __attribute__((always_inline)); //嘗試在緩衝區中發送下一個 Rgb 像素字節 inline void formatNextRgbPixelByteInBuffer() __attribute__((always_inline)); //格式化緩衝區中的下一個 Rgb 像素字節 inline uint8_t formatRgbPixelByteH(uint8_t byte) __attribute__((always_inline)); //格式化 RGB 像素高字節 inline uint8_t formatRgbPixelByteL(uint8_t byte) __attribute__((always_inline)); //格式化 RGB 像素低字節 inline uint8_t formatPixelByteGrayscaleFirst(uint8_t byte) __attribute__((always_inline)); //優先格式化灰度像素字節 inline uint8_t formatPixelByteGrayscaleSecond(uint8_t byte) __attribute__((always_inline)); //第二格式化灰度秒像素字節 inline void waitForPreviousUartByteToBeSent() __attribute__((always_inline)); //等待上一個 Uart 字節被發送 inline bool isUartReady() __attribute__((always_inline)); //這是Uart準備中 ``` ## inline ~ __attribute__((always_inline)) 1. inline內嵌函數 內嵌函數是在一般的函數前面,加上inline這個關鍵字,例如以下的例子,我要做一個計算平方的函數 ```javascript= int square(int x) { return x*x; } inline int square(int x) { return x*x; } ``` 多了inline這個關鍵字在前方即為內嵌函數,而他的用意是什麼呢? 內嵌函數是用來加速C++的執行速度,在程式碼的語法上不會有什麼太大的差異,但是在Compiler編譯時,卻會有不一樣的效果 ### 內嵌函數的執行過程 一般而言,當我們撰寫函數,並呼叫使用,電腦的機器語言指令會紀錄目前工作階段的記憶體位址 然後跳至函數的記憶體位置處理完程序後,並回到原先的位址上,而這樣來回會造成時間上的額外負擔。 C++於是提供這種內嵌函數,當我們加入關鍵字時,在Compiler時便會把函數中的程式直接展開  - 若要使用inline時,要在宣告或定義時加入inline的關鍵字 - 另外,即便加入inline想要使用內嵌函數,編譯時也不一定就會實作,編譯器會選擇 如果你執行的函數中程式碼所需時間大於處理呼叫函數的時間,則能節省的時間比較少, 反之若是你的函數中程式碼執行的時間很短,則使用內前函數可以省去較多的呼叫函數的時間 並且如果常常會使用到此函數,使用內嵌的效率也會比較好 - 所以如果你的函數中的程式碼或處理較短,並且常呼叫使用的話,可以給他加上個inline (因為編譯器可能會應你的要求使用) - 另外如果是遞迴的程式,使用inline可能編譯器也不會理你(因為裡面的不斷呼叫運算會使編譯器判斷為此函數中程式的行可能會過大) 參考網站(https://dotblogs.com.tw/v6610688/2013/11/27/introduction_inline_function) ## __attribute__ 參考網站() 參考網站() 參考網站(https://huenlil.pixnet.net/blog/post/26078382) 參考網站(https://www.itread01.com/content/1548526536.html) ::: spoiler CheckSum累加和、校驗演算法 - 傳送方:對要資料累加,得到一個數據和,對和求反,即得到我們的校驗值。然後把要發的資料和這個校驗值一起傳送給接收方。 - 接收方:對接收的資料(包括校驗和)進行累加,然後加1,如果得到0, 那麼說明資料沒有出現傳輸錯誤。 (注意,此處傳送方和接收方用於儲存累加結果的型別一定要一致,否則加1就無法實現溢位從而無法得到0,校驗就會無效) - 舉個例子: 傳送方:要傳送0xA8(0b1010 1000),0x50(0b0101 0000),我們使用unsigned char(8位)來儲存累加和, 即為0xF8(0b1111 1000),取反得到校驗和為0x07(0b0000 0111)。然後將這三個資料(0xA8、0x50、0x07)傳送出去。 接收方:如果接收正確,這三個資料的累加和就是(0b1111 1111) 此時加1,則得到的結果為0 (實際得到的應該是0b100000000,但是由於是使用unsigned char(8位)來儲存累加和,所以高位被擷取掉,只剩下了低八位的8個0). 由上面的例子,我們可以知道演算法的目的是 使累加和和校驗值相加得到一個二進位制下每一位都是1的結果 這個結果很明顯很好處理,這種演算法實現起來也很簡單,下面給出C語言的程式碼示例。 ```javascript= 傳送方:以下是如何得到校驗值的程式碼,結果就是我們想要的校驗值。 U8 TX_CheckSum(U8 *buf, U8 len) //buf為陣列,len為陣列長度 { U8 i, ret = 0; for(i=0; i<len; i++){ ret += *(buf++); } ret = ~ret; return ret; } ``` ```javascript= 接收方:輸入已包含傳送發發來的校驗值,如果函式返回的值如果是0,說明資料正確。 U8 RX_CheckSum(U8 *buf, U8 len) //buf為陣列,len為陣列長度 { U8 i, ret = 0; for(i=0; i<len; i++){ ret += *(buf++); } ret = ret; return ret+1; } ``` 參考網站(https://www.itread01.com/content/1543038130.html) :::
×
Sign in
Email
Password
Forgot password
or
By clicking below, you agree to our
terms of service
.
Sign in via Facebook
Sign in via Twitter
Sign in via GitHub
Sign in via Dropbox
Sign in with Wallet
Wallet (
)
Connect another wallet
New to HackMD?
Sign up