STM32單片機流水燈仿真與程序設計
摘要
本次程序設計和仿真是基於Proteus和keil的環境對STM32F103系列單片機進行流水燈設計,通過配置STM32的GPIO工作模式,實現LED的點亮和熄滅;通過配置8位流水燈程序設計,實現燈的流水實現。
關鍵字:Proteus、keil、STM32F103、GPIO
一、工程介紹
1.1、實現要求
用STM32一個端口接8個發光二極管,編寫程序,實現從左到右輪流點亮8個二極管(即流水燈)
二、仿真電路設計
2.1、環境介紹
仿真採用Proteus 8.9 SP2安裝鏈接
2.2、電路設計
第一步:在Proteus中的[P]選擇所需要的零件有電阻RES、LED燈LED-GREEN最後還有單片機STM32F103R6
第二步:放置STM32F103R6單片機並設置VDDA、VSSA管腳以及NRST、VBAT和BOOT0
Design->Configure Power Rails ->Power Rails
第三步:放置八個LED
爲什麼LED接1K的電阻,這個可以參考鏈接2.2.2
三、STM32單片機GPIO口介紹
3.1、GPIO框圖
GPIO總體分爲7個部分:
- 保護二極管及上、下拉電阻:保護二級管可以防止引腳外部過高或過低的電壓輸入
- P-MOS 管和N-MOS 管:控制推輓輸出和開漏輸出
- 輸出數據寄存器:由輸出數據寄存器GPIOX_ODR
- 複用功能輸出:STM32 的其它片上外設對GPIO 引腳進行控制
- 輸入數據寄存器:存儲輸入數據寄存器GPIOx_IDR
- 複用功能輸入:GPIO 引腳的信號傳輸到STM32 其它片上外設
- 模擬輸入輸出:用於ADC 採集電壓的輸入通道
3.2、GPIO工作模式
GPIO 總共有8 種細分的工作模式
typedef enum
{
GPIO_Mode_AIN = 0x0, // 模擬輸入
GPIO_Mode_IN_FLOATING = 0x04, // 浮空輸入
GPIO_Mode_IPD = 0x28, // 下拉輸入
GPIO_Mode_IPU = 0x48, // 上拉輸入
GPIO_Mode_Out_OD = 0x14, // 開漏輸出
GPIO_Mode_Out_PP = 0x10, // 推輓輸出
GPIO_Mode_AF_OD = 0x1C, // 複用開漏輸出
GPIO_Mode_AF_PP = 0x18 // 複用推輓輸出
} GPIOMode_TypeDef;
稍加整理可以大致歸類爲以下三類:
- 輸入模式(模擬/浮空/上拉/下拉)
在輸入模式時,施密特觸發器打開,輸出被禁止,可通過輸入數據寄存器GPIOx_IDR
讀取I/O 狀態。其中輸入模式,可設置爲上拉、下拉、浮空和模擬輸入四種。上拉和下拉
輸入很好理解,默認的電平由上拉或者下拉決定。浮空輸入的電平是不確定的,完全由外
部的輸入決定,一般接按鍵的時候用的是這個模式。模擬輸入則用於ADC 採集。
- 輸出模式(推輓/開漏)
在輸出模式中,推輓模式時雙MOS 管以輪流方式工作,輸出數據寄存器GPIOx_ODR
可控制I/O 輸出高低電平。開漏模式時,只有N-MOS 管工作,輸出數據寄存器可控制I/O
輸出高阻態或低電平。輸出速度可配置,有2MHz\10MHz\50MHz 的選項。此處的輸出速
度即I/O 支持的高低電平狀態最高切換頻率,支持的頻率越高,功耗越大,如果功耗要求
不嚴格,把速度設置成最大即可。
在輸出模式時施密特觸發器是打開的,即輸入可用,通過輸入數據寄存器GPIOx_IDR
可讀取I/O 的實際狀態。
- 複用功能(推輓/開漏)
複用功能模式中,輸出使能,輸出速度可配置,可工作在開漏及推輓模式,但是輸出
信號源於其它外設,輸出數據寄存器GPIOx_ODR 無效;輸入可用,通過輸入數據寄存器
可獲取I/O 實際狀態,但一般直接用外設的寄存器來獲取該數據信號。
通過對GPIO 寄存器寫入不同的參數,就可以改變GPIO 的工作模式,再強調一下,
要了解具體寄存器時一定要查閱《STM32F10X-中文參考手冊》中對應外設的寄存器說明。
在GPIO 外設中,控制端口高低控制寄存器CRH 和CRL 可以配置每個GPIO 的工作模式和
工作的速度,每4 個位控制一個IO,CRH 控制端口的高八位,CRL 控制端口的低8 位,
具體的看CRH 和CRL 的寄存器描述。
四、程序設計
4.1、環境介紹
程序設計採用MDK 5.22安裝鏈接
4.2、移位程序設計
/******************************************************************************
* @brief Water_LED:流水燈實現
******************************************************************************/
void Water_LED(void)
{
unsigned long int time = 0xFFFF; //設置軟件延時時間
unsigned char Count = 0x00; //設置流水起始地址
unsigned char Stars = 0xFE; //設置流水燈初始狀態
unsigned char Move = 0x01; //設置移動補償
while((!((Count++)&0x08))) //循環實現8位流水燈
{
GPIOC->ODR = Stars; //改變輸出寄存器,改變端口狀態
while(time--); //軟件延時高電平持續實現
time = 0xFFFF;
GPIOC->ODR = 0xFF; //消抖實現
Stars = (Stars<<1)|(Move); //補償實現
// Stars = 0xFE (1111 1110B)左移一位爲(1111 1100B)爲了補償最後一個0
//Stars| Move =(1111 1100B)| 0000 0001B)=(1111 1101B)
Move = Move*2; //Move = (0000 0010B)
Move ++ ; //Move = (0000 0011B)
while(time--); //軟件延時低電平持續時間
time = 0xFFFF;
}
}
4.3、GPIO口設置
/******************************************************************************
* @brief Water_GPIO_Init:流水燈GPIO口初始化
******************************************************************************/
void Water_GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_OUT_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE);//使能GPIO口時鐘
GPIO_OUT_InitStructure.GPIO_Pin=GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7;
//選擇指定管腳
GPIO_OUT_InitStructure.GPIO_Mode=GPIO_Mode_Out_OD; //設置開漏輸出
GPIO_OUT_InitStructure.GPIO_Speed=GPIO_Speed_2MHz; //設置輸出頻率
GPIO_Init(GPIOC,&GPIO_OUT_InitStructure);
GPIOC->ODR = 0xFF; //初始化後LED全熄滅
}
4.4、主程序設計
int main(void)
{
SysClock_Configuration(RCC_PLLSource_HSI_Div2,RCC_CFGR_PLLMULL3);//設置系統時鐘
Water_GPIO_Init(); //流水燈GPIO口初始化
while(1)
Water_LED(); //流水燈實現
}
五、結果分析與改進
1、流水程序設計是沒有考慮GPIO8~15的狀態,所以GPIOC高位以上的管腳要是用到其他功能,,可能會出問題