嵌入式開發(fā)中一些c語言的小知識

姓名:徐予康? 學(xué)號:19020100223 學(xué)院:丁香二號書院

轉(zhuǎn)自:https://blog.csdn.net/peipanbryant/article/details/105610240

【嵌牛導(dǎo)讀】嵌入式的學(xué)習(xí)避免不了c語言的學(xué)習(xí),本文介紹了一些嵌入式開發(fā)中c語言的基礎(chǔ)知識點(diǎn)

【嵌牛鼻子】static和extern變量 continue和break FIFO和軟件定時(shí)器

【嵌牛提問】嵌入式學(xué)習(xí)的c語言,你需要了解一些什么?

【嵌牛正文】

c程序小知識點(diǎn)總結(jié)

1.靜態(tài)變量static與外部變量extern的使用

靜態(tài)變量static兩種使用方式

一.定義局部變量

用static聲明后的局部變量的值在函數(shù)調(diào)用結(jié)束后不消失而保持原值,其占用的是靜態(tài)存儲(chǔ)區(qū),所以即其占用的存儲(chǔ)單元不釋放。典型應(yīng)用是用static變量求階乘n!。

2.這樣聲明的變量,其存儲(chǔ)在程序的bss段,而在bss段在程序中執(zhí)行時(shí)會(huì)初始化為0.

// eg:

static int b[5] ;

//則b[0] = 0 ,b[1] = 0等等. 而如果不是這樣定義則輸出可能是亂碼

二.定義全局變量

當(dāng)定義全局變量只限于本文件使用,而不被其他文件使用,這時(shí)可以在定義外部變量的時(shí)候加一個(gè)static聲明。注意定義加了static和不加的外部變量都是存放在靜態(tài)存儲(chǔ)區(qū),而區(qū)別就在于上一句的“只限于本文件使用”。

外部變量extern

作用:聲明外部變量,擴(kuò)展它在程序文件中的作用域。即在文件1定義的全局變量int A,可以在文件2中定義 extern A ,便可調(diào)用這個(gè)文件1中的全局變量。比如在實(shí)際具體工程項(xiàng)目中,在定時(shí)器文件中定義的全局變量時(shí)間int32_t g_iRunTime ,最長可以表示 24.85天,也就是你的終端可持續(xù)運(yùn)行的時(shí)間,在其他項(xiàng)目其他文件中,像主函數(shù)文件中也需調(diào)用用于判斷運(yùn)行時(shí)間則就用extern g_iRunTime調(diào)用。

2.函數(shù)封裝后返回值的方法

一. 只需返回一個(gè)值得時(shí)候

常用的簡單方法就是定義函數(shù)為有返回值的函數(shù),其函數(shù)的類型標(biāo)識符與返回值得類型一致。

比如 int fun();函數(shù)返回就是int類型的數(shù)值。

定義一個(gè)全局變量,因?yàn)槿肿兞看嬖谟陟o態(tài)存儲(chǔ)區(qū),當(dāng)函數(shù)調(diào)用的時(shí)候改變了全局變量的值,也實(shí)現(xiàn)了函數(shù)返回值得功能。

二. 要求返回多個(gè)值得時(shí)候

前兩者返回一個(gè)值得方法可以共用以達(dá)到返回多個(gè)值。

在形參中定義一個(gè)數(shù)組或者指針,并在主函數(shù)中定義一個(gè)數(shù)組來保存返回的值

需要注意的是,一般原則:在程序設(shè)計(jì)中,再劃分模塊時(shí)要求模塊”內(nèi)聚性”強(qiáng),與其他模塊的“耦合性”弱。簡單理解就是,在封裝的各個(gè)函數(shù)中各有自己獨(dú)立功能,即功能單一,方便調(diào)用,而不能搞的太亂。對于全局變量需限制使用。

3.循環(huán)控制continue與break的區(qū)別

在項(xiàng)目工程當(dāng)中,或者簡單的C語言代碼當(dāng)中,循環(huán)使用的非常普遍,掌握循環(huán)的各個(gè)形式非常重要,這里簡單的介紹下循環(huán)控制中continue 與 break的區(qū)別。

利用代碼體現(xiàn):

//簡介循環(huán)控制continue與break的區(qū)別

main()

{while(表達(dá)式一)

? ? {if(表達(dá)式二)

? ? ? ? {break ; //跳出循環(huán),也即跳出while語句轉(zhuǎn)執(zhí)行下面的語句}}

? ? while(表達(dá)式一)

? ? {if(表達(dá)式二)

? ? ? ? {continue ; //跳到條件限制,也即跳到while語句判斷中}}}


如上面清晰易懂,在寫代碼當(dāng)中或者看懂下載得源代碼中,如果不是在主函數(shù)main中出現(xiàn)的while(1),其他函數(shù)中出現(xiàn)while(1),都必然存在一個(gè)break語句,在首先學(xué)習(xí)看懂源代碼的任務(wù)中,這點(diǎn)比較重要。(看來這點(diǎn)只適合初學(xué)者啊,只要有點(diǎn)經(jīng)驗(yàn)都知道這些淺顯的但關(guān)鍵的知識點(diǎn))

項(xiàng)目程序規(guī)范

1.消息隊(duì)列FIFO

核心思想:通過消息隊(duì)列機(jī)制,在MAIN函數(shù)中,通過消息傳遞任務(wù)來執(zhí)行。 當(dāng)某一任務(wù)需要執(zhí)行的時(shí)候,通知消息隊(duì)列,主程序去執(zhí)行。 主程序在函數(shù)中解析消息隊(duì)列,看有無任務(wù)。

首先在頭文件中定義隊(duì)列的類型,以及消息隊(duì)列的尺寸。

建立一個(gè)函數(shù):uint8_t MsgtGetMes( Msg_List *_pByte) ,從消息隊(duì)列中讀出一條信息。和一個(gè)函數(shù): uint8_t MsgtPushMes( Msg_List *_pByte),寫入到隊(duì)列一條消息。

判斷有無任務(wù)需要執(zhí)行(這個(gè)時(shí)候需要用到軟件定時(shí)器(下面將具體介紹),每個(gè)功能到設(shè)置一定的時(shí)間去向cpu發(fā)送處理數(shù)據(jù)),將需要執(zhí)行的任務(wù)放入隊(duì)列函數(shù)void AppTaskScan(void),巡檢任務(wù)。

建立一個(gè) 函 數(shù) : vTaskStartScheduler(), 任務(wù)調(diào)度函數(shù),將消息隊(duì)列中讀出一個(gè)任務(wù)去執(zhí)行,先發(fā)出信號的任務(wù)先執(zhí)行,如果有一個(gè)任務(wù)同時(shí)觸發(fā)相同的任務(wù),按隊(duì)列的先后去執(zhí)行這依程序。

**至此,**在主函數(shù)mian中的while(1)中調(diào)用5,6兩個(gè)函數(shù)詢檢即可。

隊(duì)列FIFO運(yùn)用主要是對CPU分配管理:一般的計(jì)算機(jī)系統(tǒng)只有一個(gè)CPU,如果在系統(tǒng)中的多個(gè)進(jìn)程都滿足運(yùn)行條件,這就可以用一個(gè)就緒隊(duì)列來進(jìn)行管理。當(dāng)某個(gè)進(jìn)程需要執(zhí)行的時(shí)候,它的進(jìn)程名就插入到就緒隊(duì)列的尾端。如果此隊(duì)列是空的,CPU就立即執(zhí)行此進(jìn)程;如果此隊(duì)列非空,則該進(jìn)程就需要排在隊(duì)列的尾端進(jìn)行等待。CPU總是首先執(zhí)行排在隊(duì)首的進(jìn)程,一個(gè)進(jìn)程分配的一段時(shí)間執(zhí)行完了,又將它插入隊(duì)尾進(jìn)行等待,CPU轉(zhuǎn)而為下一個(gè)出現(xiàn)在隊(duì)首的進(jìn)程服務(wù)。如此。按照“FIFO”的原則一直進(jìn)行下去,直到執(zhí)行完的進(jìn)程從隊(duì)列中刪掉。

隊(duì)列fifo還可用于許多場景,比如串口fifo,多串口運(yùn)行時(shí)的分配。

2.軟件定時(shí)器的使用

這部分我主要是針對stm32的程序來使用的,首先配置systick定時(shí)器作為系統(tǒng)滴答定時(shí)器。缺省定時(shí)周期為1ms。實(shí)現(xiàn)了多個(gè)軟件定時(shí)器供主程序使用(精度1ms), 可以通過修改 TMR_COUNT 增減軟件定時(shí)器個(gè)數(shù)。

這部分還是主要為CPU處理隊(duì)列信息的使用做服務(wù)的。為每個(gè)單一任務(wù)設(shè)置定時(shí)器,一旦到了設(shè)定的時(shí)間就像隊(duì)列寫入一個(gè)該任務(wù)消息,直到CPU處理為止,定時(shí)器主要實(shí)現(xiàn)任務(wù)調(diào)度的問題。當(dāng)然,風(fēng)格不同的工程師有著不同的用法!

配置systick定時(shí)器,周期為1ms

方法:在core_cm3.h有一個(gè)這樣的函數(shù)uint32_t SysTick_Config(uint32_t ticks),該函數(shù)的形參表示內(nèi)核時(shí)鐘多少個(gè)周期后觸發(fā)一次Systick定時(shí)中斷

– SystemCoreClock / 1000 表示定時(shí)頻率為 1000Hz, 也就是定時(shí)周期為 1ms

– SystemCoreClock / 500 表示定時(shí)頻率為 500Hz, 也就是定時(shí)周期為 2ms

– SystemCoreClock / 2000 表示定時(shí)頻率為 2000Hz, 也就是定時(shí)周期為 500us

所以我們一般在定時(shí)器初始化函數(shù)中調(diào)用SysTick_Config(SystemCoreClock / 1000);形成周期性中斷函數(shù)每一ms執(zhí)行中斷一次,即需要中斷就要寫了個(gè)中斷服務(wù)程序void SysTick_Handler(void);該函數(shù)主要為下面制定軟件定時(shí)器的計(jì)數(shù)每隔1ms進(jìn)行減一操作。

軟件定時(shí)器的設(shè)置

1.定義定時(shí)器結(jié)構(gòu)體以及定時(shí)器的個(gè)數(shù)和各個(gè)任務(wù)定時(shí)器的名稱

typedef struct

{

volatile uint8_t Flag; /* 定時(shí)到達(dá)標(biāo)志? */

volatile uint32_t Count; /* 計(jì)數(shù)器 */

volatile uint32_t PreLoad; /* 計(jì)數(shù)器預(yù)裝值 */

}SOFT_TMR;

/* 軟件定時(shí)器個(gè)數(shù) */

#define TMR_COUNT? ? ? ? ? 5? //自己設(shè)定需要多少軟件定時(shí)器

/*定義定時(shí)器名稱*/

#define C_TMR_ID? ? ? ? ? (4)?

#define C_TMR_ID? ? ? ? ? (3)

#define E1_TMR_ID? ? ? ? ? (2)

#define E_TMR_ID? ? ? ? ? (1)

#define cTMR_ID? ? ? ? ? ? (0)

現(xiàn)在主要寫兩個(gè)函數(shù) 一個(gè):void bsp_StartAutoTimer(uint8_t _id, uint32_t _period)主要是將設(shè)定的實(shí)時(shí)計(jì)數(shù)器初值period的值裝入結(jié)構(gòu)體中,利用定時(shí)器中斷服務(wù)程序自減一,并到減到0時(shí)Flag置為1,在另一個(gè)函數(shù)uint8_t bsp_CheckTimer(uint8_t _id)中判斷Flag定時(shí)到達(dá)標(biāo)志是否定時(shí)時(shí)間到了,返回1.用于void AppTaskScan(void)巡檢判斷任務(wù)。

版權(quán)聲明:本文為CSDN博主「peipan」的原創(chuàng)文章,遵循CC 4.0 BY-SA版權(quán)協(xié)議,轉(zhuǎn)載請附上原文出處鏈接及本聲明。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容