日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

嵌入式接口之GPIO驱动LED的实验(附完整代码和工程以及详细的调试过程)

發布時間:2024/8/1 编程问答 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 嵌入式接口之GPIO驱动LED的实验(附完整代码和工程以及详细的调试过程) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

目錄

    • 前言
    • 環境配置
    • 實驗內容
    • 實驗講解
      • 題目分析
      • 實現方式
      • 文件概覽
      • sw_delay.c
      • key_driver.c
        • 時鐘使能
        • GPIO初始化
        • key_driver.c代碼
      • led_driver.c
        • GPIO_SetBits、GPIO_ResetBits
        • led_driver.c代碼
      • main.c
    • 仿真調試
      • 設置仿真調試
      • 編譯
      • 調試
    • 總結

前言

由于期末考試需要考實驗代碼,為了自己能夠印象深刻,考試能夠順利通過,特意寫個博客記錄一下實驗的過程以及其中一些細節。下面將通過一個例題一步一步進行講解。

環境配置

軟件配置:Keil uVision5
開發板芯片型號:STM32F103ZE

實驗內容

基于C語言的GPIO操作
已知:戰艦開發板連接按鍵(輸入設備)KEY0、KEY1、KEY2,和發光二極管(輸出設備)LED0、LED2.
要求:用戶任意按下某個按鍵,開發板根據用戶按下的不同的按鍵,采用不同的方式使二極管閃爍。
硬件電路如下:

實驗講解

題目分析

由于實驗要求需要我們進行輸入輸出操作,那么就需要使用到GPIO,需要電亮二極管,因為硬件的響應速度是十分迅速的,如果僅僅在程序中輸出一下高電平,那現實中LED只是在極短的時間閃一下,以至于我們根本觀察不到它亮過,因此這里需要使用延時,由于我們只需要看到燈亮燈滅的效果即可,那么使用軟件延時即可,即用while循環來達到延時的效果,雖然精度和效率都不高,但是實現起來是十分方便的,也符合我們的實驗要求。
由于LED0和LED1分別接在PB5和PE5上,因此我們只需要操控GPIOB和GPIOE的Pin5的輸出即可實現實驗需要的效果了。

實現方式

下面的實驗將使用CMSIS標準庫版。CMSIS全稱Cortex MicroController Software Interface Standard由ARM 與芯片廠商建立的軟件接口標準。芯片商意法半導體公司(ST公司)推出的STM32 標準庫函數就是遵循CMSIS標準。

文件概覽

因為配置文件比較多,但是配置起來還是比較簡單的,就是c語言開頭導入配置文件即可,因此以下的代碼內容可運行默認的前提是已經配置好了需要的頭文件。

整個實驗的工程目錄如上圖所示,這個工程我會原封不動的傳到資源中去。因為這是我們老師給我們的工程模板,因此會比較規范,其中需要我們編寫代碼的文件只有sw_delay.c、key_driver.c、led_driver.c、main.c這四個文件。
其中
sw_delay.c需要寫入軟件延時的函數,是我們能夠清晰的看到LED燈亮和燈滅的實驗效果。
key_driver.c需要對應GPIO輸入腳的初始化,以達到按下按鍵能夠實現燈亮燈滅的控制效果。
led_driver.c需要寫入對應GPIO驅動LED的函數以及初始化。
main,c則是將上述三個文件的函數整合,完成整個實驗的內容。

sw_delay.c

這里使用軟件延時,while循環指定次數達到延時的效果。

#include "sw_delay.h" void SoftwareDelay(uint32_t time ) {while(time>0){time--;} }

key_driver.c

時鐘使能

在使用一個外設前,必須先配置和激活啟動該外設的時鐘,如GPIO端口B,那么就要激活GPIOB的時鐘。只有啟動了時鐘外設才變得可用,而不需要使用的外設無需使能時鐘,這樣做的好處是可以降低STM32芯片的內部功耗。

外設也區分高速外設和低速外設,這就需要對應不同工作頻率的時鐘來使能。
可見GPIO屬于高速外設,需要使用APB2來連接使能。
然后我們可以參考STM32固件庫使用手冊,查看對應時鐘使能函數的用法:

//代表使能GPIOA使得其能夠正常工作和使用 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE)

GPIO初始化


GPIO一共有16個引腳,8種工作模式,3種最大翻轉速度(2MHz、10MHz、50MHz)。
上拉輸入是指在沒有信號輸入的情況下可以穩定在高電平。
工作模式可以參考:深刻理解GPIO(上拉輸入、下拉輸入、模擬輸入、浮空輸入,開漏輸出,推挽輸出的區別,以STM32為例)感覺講的十分不錯和詳細。
庫函數中已經封裝好了GPIO的初始化結構體

其中三個參數的取值分別如下:


因此我們能夠對GPIO進行快速的初始化:

//定義一個GPIO結構體 GPIO_InitTypeDef GPIO_InitStructure; //使用引腳2、3、4 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4; //工作模式為上拉輸入,即無信號時處于高電平狀態 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //初始化GPIOE GPIO_Init(GPIOE, &GPIO_InitStructure);

key_driver.c代碼

最終我們的key_driver.c如下所示:

#include "stm32f10x_conf.h" void SoftwareDelay(uint32_t time ); void KEY_GPIO_Config(void) { GPIO_InitTypeDef GPIO_InitStructure;RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOE, ENABLE);GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;GPIO_Init(GPIOE, &GPIO_InitStructure); }

使能GPIOE,然后使用GPIOE的2、3、4號引腳上拉輸入作為我們控制LED的開關。

led_driver.c

GPIO_SetBits、GPIO_ResetBits


此函數能夠設置GPIO引腳的電平。

此函數能夠重置GPIO引腳的電平。

led_driver.c代碼

由于PB5和PE5分別連接著LED0和LED1,因此我們設置PB5和PE5為推挽輸出用于控制LED燈的亮滅,然后通過對PE2、3、4引腳的輸入來控制PB5和PE5的狀態(高電平或者低電平)從而控制LED0和LED1的狀態,達到我們需要的效果。

#include "stm32f10x_conf.h" void LED_GPIO_Config(void) { GPIO_InitTypeDef GPIO_InitStructure;RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOE,ENABLE);GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;//推挽輸出GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOB, &GPIO_InitStructure);GPIO_SetBits(GPIOB, GPIO_Pin_5);GPIO_Init(GPIOE, &GPIO_InitStructure);GPIO_SetBits(GPIOE, GPIO_Pin_5); } void LED0_LightUp(void)//點亮LED0 {GPIO_ResetBits(GPIOB, GPIO_Pin_5); } void LED1_LightUp(void)//點亮LED1 {GPIO_ResetBits(GPIOE, GPIO_Pin_5); }void LED0_Flash(void){//LED0閃爍4次uint8_t i;for(i=1; i<=4; i++){GPIO_ResetBits(GPIOB, GPIO_Pin_5);SoftwareDelay(100000);GPIO_SetBits(GPIOB, GPIO_Pin_5);SoftwareDelay(100000);} }void LED1_Flash(void){uint8_t i;for(i=1; i<=4; i++){GPIO_ResetBits(GPIOE, GPIO_Pin_5);SoftwareDelay(100000);GPIO_SetBits(GPIOE, GPIO_Pin_5);SoftwareDelay(100000);} }void LED01_Flash(void){uint8_t i;for(i=1; i<=4; i++){GPIO_ResetBits(GPIOB, GPIO_Pin_5);GPIO_ResetBits(GPIOE, GPIO_Pin_5);SoftwareDelay(100000);GPIO_SetBits(GPIOB, GPIO_Pin_5);GPIO_SetBits(GPIOE, GPIO_Pin_5);SoftwareDelay(100000);} }

main.c

main函數只需要將整體架構拼接起來就可以了。整體思路就是,初始化LED0和LED1都是熄滅狀態,按下KEY0、1、2兩個LED都會一直亮;按下KEY1、2 LED0閃爍;按下KEY0、2 LED1閃爍; 按下KEY0、1 LED01一起閃爍。

#include"stm32f10x_conf.h" void LED_GPIO_Config(void);//LED GPIO口配置函數申明 void LED0_LightUp(void);//LED0亮 void LED1_LightUp(void);//LED1滅 void LED0_Flash(void); void LED1_Flash(void); void LED01_Flash(void); #define KEY0 GPIO_ReadInputDataBit(GPIOE, GPIO_Pin_4)//讀取鍵0 #define KEY1 GPIO_ReadInputDataBit(GPIOE, GPIO_Pin_3)//讀取鍵1 #define KEY2 GPIO_ReadInputDataBit(GPIOE, GPIO_Pin_2)//讀取鍵2void KEY_GPIO_Config(void);//KRY GPIO初始化申明int main(void) { KEY_GPIO_Config();LED_GPIO_Config();while(1){if((KEY0 == 1)&&(KEY1 == 1)&&(KEY2 == 1)){LED0_LightUp();//LED0點亮LED1_LightUp();//LED1點亮}if((KEY0 == 0)&&(KEY1 == 1)&&(KEY2 == 1)){LED0_Flash;//LED0閃爍}if((KEY0 == 1)&&(KEY1 == 0)&&(KEY2 == 1)){LED1_Flash();//LED1閃爍}if((KEY0 == 1)&&(KEY1 == 1)&&(KEY2 == 0)){LED01_Flash();//LED01一起閃爍}}}

仿真調試

設置仿真調試


點擊魔術棒

然后Debug選擇Use Simulator即可。

編譯


點擊編譯之后即可開始調試。

調試


點擊調試按鈕進入調試界面
首先可以在main函數中設置幾個斷點如下所示:

然后需要打開GPIOB和GPIOE的對應詳細信息的界面:

打開之后如下所示,因為還沒初始化,所以看不到初始化后的結果

然后點擊左上角運行到斷點處,運行完初始化函數就能夠看到GPIOE和GPIOB的設置發生了變化:PB5和PE5是推挽輸出,PE2、3、4是上拉輸入。

當將PE4、3(分別對應的是KEY0、1)點擊模擬開關按下時,程序能夠運行到LED01閃爍的代碼語句中,此時PE5和PB5都會發生較快的閃動信號,模擬LED的閃亮,由于閃動太快整個過程可能不足一秒鐘,因此可以再增加一些延時,但是還是看的出來信號在閃動的。

總結

寫了一遍,確實也遇到了一些問題,讓我發現原來老師以前的代碼有些可能并不是必要的,并且理解了初始化以及LED被控制的操作,讓我更加熟悉了整個流程。畢竟學習,不能學了就忘,總得留下點東西才好。

總結

以上是生活随笔為你收集整理的嵌入式接口之GPIO驱动LED的实验(附完整代码和工程以及详细的调试过程)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。