經過千辛萬苦,在上一章《星星點燈(一)-LED點燈初階》我們終于把LED點亮了,醜是醜了點,但是總是有進步嘛!萬丈高樓平地起,有了這個基礎,隻要我們本着不抛棄,不放棄的精神,來個打破砂鍋問到底,我想就會百尺竿頭更進一步的。
本章,我們把醜小鴨打扮一下,看看能不能離白天鵝更像一點。
第一步:代碼子產品化
我們把I/O初始化的代碼獨立出去,為以後驅動更多的LED做準備,而且由于各種硬體限制原因,可能驅動LED的端口并沒有集中到一個順序的端口,PA有幾個,PB有幾個等等。那就需要分别的初始化它。
這樣我們把實作代碼分離出來後,上層調用就不需要做任何的修改,隻需要完成底層函數的修改就可以達到這個目的。
把調用和實作分離,這是實作子產品化編寫代碼的第一步。
void LedInit(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_14;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);
}
同樣的,我們把延時函數寫成一個通用的函數,就像這樣:
void DelayMS(UINT32 ms)
{
volatile UINT32 i,j; //注意這個變量一定要用volatile 聲明,否則編譯器會給你優化掉的。
for(i = 0;i < ms;i++)
{
for(j = 0;j < 10 * 800;j++);
}
}
第二步 把宏定義修理一下
還記得那個奇醜無比的LEDON嗎?如果非得定義宏(比如一個系統隻有一顆LED)的方式來操作LED的功能,那至少我們可以這樣來定義它,使他看起來更加紳士一些:
//定義宏
#define LedOn() (GPIOB->BRR = GPIO_Pin_14)
#define LedOff() (GPIOB->BSRR= GPIO_Pin_14)
//調用宏
LedOn();
LedOff();
這有什麼好處呢?
第一.它至少看起來像一個正常的語句了。
第二.為什麼我們不用全部大寫的方式來定義宏呢?這樣的好處就是當有一天我後悔了,我要用函數的方式來實作這個LedOn()的功能,我隻需要去掉宏的定義,用如下的函數去實作就可以了,但是調用的地方卻不需要做任何修改。
是不是很有智慧的方式啊,你學會了嗎?
void LedOn(void)
{
GPIOB->BRR = GPIO_Pin_14;
}
好了,現在我們的點燈程式,有這些子產品的支援,我們就比較簡潔清爽了,如下:
void main(void)
{
LedInit();
while(1)
{
LedOn();
DelayMS(500);
LedOff();
DelayMS(500);
}
}
現在是不是看起來比較心情愉悅了很多啊?
我們把實作細節對調用者隐藏起來,比如LedInit()函數,把需要變化的參數,用函數傳遞參數的方式傳入來實作調用和實作的分離,這就是函數的子產品化最簡單的實作。
函數子產品化的好處是便于以後上層代碼的移植,我們需要更換到其他晶片去實作的時候,上層邏輯就不用再去實作,隻要把對應的底層驅動重新編寫,就能達到移植的目的。
上面的代碼現在還有沒有什麼缺陷呢?
那就是DelayMS(500)這個函數,我們總不能讓CPU就在這裡幹等,啥事情都不幹吧?要幹其他事情吧,又怎麼去保證LED點亮的延遲時間呢?這真是一個頭疼的地方。
中斷,對,你第一印象想到的就是中斷,在中斷裡面計數,然後計數到了再點亮或者熄滅LED。大概就是下面這樣子:
//1ms的中斷程式
static int LedCnt = 0;
static int LedStatus = 0;
void TimerInt(void)
{
if(++LedCnt > 500)
{
if(LedStatus == 0)
LedOn();
else
LedOff();
LedStatus = ~LedStatus;
}
}
沒毛病,點亮一個LED也對了,在加上一些使能的條件也就差不多了。但是,也就是但是,現在要點亮更多的燈呢?還要玩幾個花式呢?又傻眼了吧!系統裡面還有按鍵,還有好多其他的事情,難道都在中斷裡面去扔一大堆變量?
顯然,這是一個不可能完成的任務,如何來解決?請聽下回分解。
大緻思路提示:
1.消息隊列
2.軟定時器
3.LED操作函數的修改
![](https://img.laitimes.com/img/__Qf2AjLwojIjJCLyojI0JCLiAzNfRHLGZkRGZkRfJ3bs92YsYTMfVmepNHL3xWbkVHbtllb1cVWxgmMMBjVtJWd0ckW65UbM5WOHJWa5kHT20ESjBjUIF2X0hXZ0xCMx81dvRWYoNHLrdEZwZ1Rh5WNXp1bwNjW1ZUba9VZwlHdssmch1mclRXY39CXldWYtlWPzNXZj9mcw1ycz9WL49zZwpmL3IzMwADO0EjM3EzMwAjMwIzLc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.jpg)