用STM32mini版寫一個流水燈
今天,我用STM32mini版來寫一個流水燈,自己的能力有限,是個小白,有不完美或者不對的的地方還望賜教,不喜勿噴,
學習一個新東西是一件很開心的事情,但是,自學一件從來沒有接觸過的事物,或許有點惡心,但是對于32單片機和51單片機的自學者來說,沒有什么是比自己點亮流水燈更讓人興奮地了,確實,點亮了流水燈,剩下的無非就是學習其他硬體資源的控制方法,
本文接下來會介紹,流水燈的點亮方式和操作程序中遇到的問題及其解決辦法,
為什么學習每一種板子都要從流水燈開始?因為點亮了流水燈,就足以表明學習者對GPIO口可以進行簡單操作了,而且對后續模塊學習的除錯環節也有一定的指示作用,
本次實驗用的是STM32mini來進行操作的(不管什么版本,基本操作都一樣),其電路圖如圖1-1所示,

要想點亮流水燈,就需要先點亮一個LED燈,
點亮一個LED燈
LED燈是怎樣被點亮的呢?眾所周知,LED都是單向導電的,簡單來講,在一個固定的通電方向上,只要LED中流過足夠的電流,它就發光,現在就是不知道這個足夠的電流是多少,那上面圖中的LED介面電路來說,它是由右向左導通的,以LED0為例,當LED0右端PB5輸出高電平時,電阻和LED兩端的總電壓為3.3V,那么就由歐姆定律很容易的就可以判斷出LED0的電流不會超過3.3mA,因為LED0內部也是有電阻的,因此可以判斷LED0發光時流經的電流是小于3.3mA的,一般為1~2mA就會發光,
現在的關鍵問題是什么呢?問題就是“如何實用程式來控制LED0的PB5輸出高電平?”
控制PB5輸出高電平的方法可以概述為:
1、找到PB口的控制暫存器,將其設定為輸出模式;
2、找到PB口的資料暫存器,將該暫存器中控制PB5的控制位的值設定為1;
3、右端管腳就會輸出高電平,相應的LED就會被點亮,
接下來就需要查看具體的PB口控制暫存器、PB口資料暫存器的具體地址以及使用方法,不同的處理器的操作方法都是相似的,不同的暫存器名字可能有所不同,各個暫存器的地址可能有所不同,這樣就會使操作變得十分繁瑣,為了解決這個問題ST公司的工程師已經把這些東西以韌體庫的形式提供給廣大用戶了,使用韌體庫,自學者只需要了解韌體庫提供的函式然后呼叫即可,(筆者將會在另一篇文章中來具體介紹韌體庫)
流水燈程式分析
盡管還沒有介紹韌體庫函式,但是還是建議看完以下代碼的分析,不用通篇理解只需要看一下庫函式使用的具體例子即可,咱們日后會對程式段中使用到的函式進行具體的分析,
#include"stm32f10x_gpio.h"
#define Led1_On() GPIO_SetBits(GPIOB,GPIO_Pin_5)
#define Led1_Off() GPIO_ResetBits(GPIOB,GPIO_Pin_5)
#define Led2_On() GPIO_SetBits(GPIOD,GPIO_Pin_6)
#define Led2_Off() GPIO_ResetBits(GPIOD,GPIO_Pin_6)
#define Led3_On() GPIO_SetBits(GPIOD,GPIO_Pin_3)
#define Led3_Off() GPIO_ResetBits(GPIOD,GPIO_Pin_3)
第1行,既然使用了韌體庫中的函式,那么就需要包含庫函式的頭檔案了,
第2~3行,實作對PB引腳的位置和復位操作,也就是點亮LED,熄滅LED,
第4~7行,實作對PD6、PD3引腳的位置和復位操作,
void LED_Init(void);
void Delay(__IO uint32_t nCount);
第8~9行宣告了兩個函式,
void Delay(unsigned int nCount)
{
for(;nCount!=0;nCount--);
}
上述是一個延時函式,實作一定時間的延時,
void LED_Init(void)
{
GPIO_InitTypeDef GPIO_Structure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD,ENABLE);
GPIO_Structure.GPIO_Pin=GPIO_Pin_5;
GPIO_Structure.GPIO_Mode=GPIO_Mode_Out_PP;
GPIO_Structure.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Iint(GPIOB,&GPIO_Sructure);
GPIO_Structure.GPIO_Pin=GPIO_Pin_6;
GPIO_Structure.GPIO_Pin=GPIO_Pin_3;
GPIO_Iint(GPIOD,&GPIO_Sructure);
}
上述函式中只有三條陳述句沒有講解,其他陳述句相信都有似曾相識的感覺,
第10行,定義了一個GPIO——InitTypeDef型別的結構體變數GPIO_Structure,即通過該陳述句找到了“快遞盒子”,
第13~15行,對結構體變數GPIO_Structure中的值進行了初始化,可以理解為向“盒子”里面填東西,當然填哪些東西是需要注意的,當然具體需要填什么,韌體庫已經給你定義好了,隨著更加深入的學習會更加了解,
第16行,呼叫GPIO_Iint()函式進行“快遞”,此時相當于“發送快遞”了,剩下的就看函式的了,
第17和19行,類似于13~16行,
第16行,這行程式的意思初始化IO口的翻轉速度,一個IO口可以實作時而輸出高電平,時而輸出低電平,但是涉及一個最大翻轉速度的問題,這個函式就是對此定義的,
此外,我們對比第16、19行可以看出,GPIO_Iint()函式的第一個引數決定了“快遞”的目的地地址,但是接收的方式可以有很多,

int main(void)
{
SystemInit();
LED_Init();
while(1)
{
led1_On();Led2_Off();Led3_Off();
Delay(0x8FFFF);
led1_Off();Led2_On();Led3_Off();
Delay(0x8FFFF);
led1_Off();Led2_Off();Led3_On();
Delay(0x8FFFF);
}
}
第20行,呼叫SystemInit()函式,又會有個疑問,這是個什么函式?這也是韌體庫中的函式,此函式主要是實作對處理器時鐘的初始化作業,我們在這里主要記住:一般在主函式力需要首先呼叫該函式,就這一點就行了,
第21行,呼叫LED_Init()函式,進行初始化,
第22~28行,才是真正實作了流水燈的效果的函式,
筆者提問望讀者評論
啟動代碼是如何作業的?
什么時候用main作為主函式名?
源程式
#include"stm32f10x_gpio.h"
#define Led1_On() GPIO_SetBits(GPIOB,GPIO_Pin_5)
#define Led1_Off() GPIO_ResetBits(GPIOB,GPIO_Pin_5)
#define Led2_On() GPIO_SetBits(GPIOD,GPIO_Pin_6)
#define Led2_Off() GPIO_ResetBits(GPIOD,GPIO_Pin_6)
#define Led3_On() GPIO_SetBits(GPIOD,GPIO_Pin_3)
#define Led3_Off() GPIO_ResetBits(GPIOD,GPIO_Pin_3)
void LED_Init(void);
void Delay(__IO uint32_t nCount);
void LED_Init(void)
{
GPIO_InitTypeDef GPIO_Structure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD,ENABLE);
GPIO_Structure.GPIO_Pin=GPIO_Pin_5;
GPIO_Structure.GPIO_Mode=GPIO_Mode_Out_PP;
GPIO_Structure.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Iint(GPIOB,&GPIO_Sructure);
GPIO_Structure.GPIO_Pin=GPIO_Pin_6;
GPIO_Structure.GPIO_Pin=GPIO_Pin_3;
GPIO_Iint(GPIOD,&GPIO_Sructure);
}
int main(void)
{
SystemInit();
LED_Init();
while(1)
{
led1_On();Led2_Off();Led3_Off();
Delay(0x8FFFF);
led1_Off();Led2_On();Led3_Off();
Delay(0x8FFFF);
led1_Off();Led2_Off();Led3_On();
Delay(0x8FFFF);
}
}
void Delay(unsigned int nCount)
{
for(;nCount!=0;nCount--);
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/230413.html
標籤:其他
