簡(jiǎn)單介紹一下嵌入式軟件開(kāi)發(fā)中的注冊(cè)機(jī)制!
時(shí)間:2021-11-29 16:25:57
手機(jī)看文章
掃描二維碼
隨時(shí)隨地手機(jī)看文章
[導(dǎo)讀]點(diǎn)擊上方「嵌入式大雜燴」,選擇「置頂公眾號(hào)」第一時(shí)間查看嵌入式筆記!來(lái)源:CSDN作者|取經(jīng)的孫猴兒整理|嵌入式應(yīng)用研究院1.問(wèn)題描述在使用定時(shí)器的過(guò)程中最令人苦惱的就是,定義flag,holdtime,每用一次定義就會(huì)導(dǎo)致中斷函數(shù)中標(biāo)志位滿天飛,時(shí)間變量在程序中隨處可見(jiàn)。在想要...
1.問(wèn)題描述
在使用定時(shí)器的過(guò)程中最令人苦惱的就是,定義flag,holdtime,每用一次定義就會(huì)導(dǎo)致中斷函數(shù)中標(biāo)志位滿天飛,時(shí)間變量在程序中隨處可見(jiàn)。在想要移植,又不敢隨便刪除。程序處于高耦合狀態(tài),失去了一個(gè).c 一個(gè) .h的意義。
2.如何解決這種問(wèn)題
引入注冊(cè)機(jī)制。為了方便說(shuō)明注冊(cè)機(jī)制,舉一個(gè)例子:手機(jī)在使用相機(jī)這個(gè)功能時(shí),有一個(gè)操作:將拍攝的照片發(fā)送出去。以程序來(lái)實(shí)現(xiàn)這一過(guò)程,最容易想到的方法如下:
{
if(選擇微信發(fā)送)
{
獲取發(fā)送人;
選擇發(fā)送人;
}
else if(選擇qq發(fā)送)
{
獲取發(fā)送人;
選擇發(fā)送人;
}
else if(選擇微博發(fā)送)
{
獲取發(fā)送人;
選擇發(fā)送人;
}
.
.此處省略一萬(wàn)行
.
}
這是最容易想到的實(shí)現(xiàn)方式,就如上面定時(shí)器的實(shí)現(xiàn)方式,哪里要用了,再定義一系列變量就是了?;氐较鄼C(jī)例子,假設(shè)某一天一個(gè)比微信還火的聊天軟件出現(xiàn)了,用戶(hù)安裝了,想要發(fā)送圖片,這時(shí)該怎么做 ?當(dāng)然,只能在上面相機(jī)的發(fā)送發(fā)送模塊中添加else if(。。。。)和它的實(shí)現(xiàn)方式了,也就意味著,每更新一個(gè)需要使用圖片功能的軟件,就必須去修改相機(jī)模塊,是不是覺(jué)得和我們的定時(shí)器很像?
typedef struct
{
u8 num; //當(dāng)前注冊(cè)設(shè)備數(shù)
u8 list_ name[num _max]; //用于保存注冊(cè)設(shè)備列表
void (*click[num _max])(u8 * temp); //存放不同模塊(微信qq)的發(fā)送函數(shù)地址
}Equiment;
Equiment COM;
/**************************注冊(cè)函數(shù)****************************************/
void Photo_Register ( void(*a)(u8 * temp),u8 list ) //提供給外部的接口
{
if(COM.num < num.max)
{
COM. click[COM. num]=a; //保存函數(shù)地址
COM. List _name [ COM. num ]=list; //保存設(shè)備名至列表
COM. num ;
}
else
{
/****超過(guò)最大設(shè)備數(shù)報(bào)錯(cuò)******/
}
}
/*相機(jī)中的發(fā)送函數(shù)*/
void Click(u8 temp) // 最終實(shí)現(xiàn)圖片發(fā)送調(diào)用此函數(shù)即可
{
u8 i,NUM;
for(i=0; i<= COM.num ; i )
{
printf(“打印列表,顯示已經(jīng)注冊(cè)的設(shè)備”)
}
NUM =Get(選擇的發(fā)送方式);
if(!NUM)
COM.click[NUM](temp);
}
/*******************以上在相機(jī)中實(shí)現(xiàn)************************************/
微信中若要使用,在安裝過(guò)程中,提示打開(kāi)相機(jī)權(quán)限,便是調(diào)用上述注冊(cè)函數(shù)。將微信本身自集成的發(fā)送函數(shù)地址傳給相機(jī),相機(jī)每次發(fā)送只需判斷哪些設(shè)備注冊(cè)了,選擇對(duì)應(yīng)的方式即可。如此一來(lái),出現(xiàn)再多的新應(yīng)用要使用相機(jī),只需注冊(cè)一次即可。相機(jī)與微信QQ微博等模塊之間完美解耦!類(lèi)似的,定時(shí)器的解耦也能這樣處理。
定時(shí)器運(yùn)用注冊(cè)機(jī)制
首先,要想解耦,必須去掉胡亂定義的標(biāo)志位與時(shí)間變量,只允許一個(gè)時(shí)間變量。因此定義一個(gè)32位的時(shí)間變量,不要任何條件限制,讓他一直自加。
#ifndef __TIME_H
#define __TIME_H
#define TimerID_max 20 //最大注冊(cè)設(shè)備數(shù)
#define RunOutOf_time(ID , ms) ( systime.no w-systime.last[ID -1]< ms )
typedef struct
{
u8 ID; //設(shè)備ID
u32 now; //當(dāng)前時(shí)間
u32 last[TimerID_max]; //存放抓取到的時(shí)間
void (*timer_init)(u16 countdata,u16 freqData); //指向初始化函數(shù)
u8 (*get_id)(void); //指向獲取ID函數(shù)
void (*refresh)(u8 ID); //指向更新時(shí)間函數(shù)
}SYSTIME;
extern SYSTIME systime;
#endif
time.c
/*********提供給外部的API*******************/
void Timer_Init(u16 CountData,u16 FreqData);
unsigned char systime_get(void);
void Refresh(u8 ID);
/***********************************************/
SYSTIME systime = 定義SYSTIME類(lèi)型變量,并初始化函數(shù)指針
{
.get_id=systime_get,
.refresh=Refresh,
.timer_init=Timer_Init
};
/****************************************************/
//函數(shù)名:Timer_init
//描述:初始化定時(shí)器
//輸入:中斷時(shí)間相關(guān)
//輸出:null
/****************************************************/
void Timer_Init(u16 CountData,u16 FreqData)
{
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4,ENABLE);
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);
NVIC_InitStructure.NVIC_IRQChannel = TIM4_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 4;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(