本篇文章是根據(jù)B站UP主江科大自化協(xié)的教學(xué)視頻STM32入門教程-2023持續(xù)更新中,在了解、學(xué)習(xí)與實(shí)操后整理的學(xué)習(xí)筆記,內(nèi)容部分來(lái)自UP主的課程資料,并包含了一些個(gè)人的理解,如有謬誤歡迎指正,詳細(xì)知識(shí)點(diǎn)可以觀看UP主的視頻進(jìn)行了解。
希望大家都能早日掌握單片機(jī)。
一、前置知識(shí)(C語(yǔ)言)
1、指針
(1)基本概念
? 計(jì)算機(jī)的內(nèi)存中每個(gè)存儲(chǔ)單元都是有序的,且都是按字節(jié)編碼的,字節(jié)是最小的存儲(chǔ)單位。在程序中我們定義的變量存儲(chǔ)于類似的緩存中,不過(guò)緩存位于CPU內(nèi)部,且速度更快,同樣每個(gè)存儲(chǔ)單元也有對(duì)應(yīng)編碼,我們稱其為地址,而指針即為地址。
? 指針是一種數(shù)據(jù)類型,是地址,指針變量即為存儲(chǔ)地址的變量,其定義形式為:
//數(shù)據(jù)類型 *指針名
int *x;
float *f;
char *ch;
//如上,就分別定義了int、float和char類型的指針變量
- 由上面的例子可以得到,指針變量也是有數(shù)據(jù)類型的,因?yàn)椴煌瑪?shù)據(jù)類型占的地址空間不同,所以指針變量的類型應(yīng)與它將指向的變量數(shù)據(jù)類型相同。
(2)指針變量的使用
Ⅰ、指針變量的聲明(初始化)
? 在聲明指針變量時(shí),如果不一開始就賦值的話,可能會(huì)導(dǎo)致較為嚴(yán)重的錯(cuò)誤:
int *p;
*p = 100;
//如上,因?yàn)橹羔樧兞繜o(wú)初值,“100”的值賦給的緩存地址是不確定(隨機(jī))的,這樣有可能導(dǎo)致一些重要的緩存位置的數(shù)據(jù)被替換導(dǎo)致數(shù)據(jù)丟失出錯(cuò)
? 因此建議聲明時(shí)賦空(“NULL”),避免出錯(cuò):
int *p = NULL;//等同于int *p = 0;
*p = 100;
- 聲明指針變量時(shí)一定要先初始化,否則可能會(huì)導(dǎo)致出錯(cuò)。
Ⅱ、相關(guān)運(yùn)算符
- 取地址運(yùn)算符&:?jiǎn)文窟\(yùn)算符&是用來(lái)取操作對(duì)象的地址。例:&i 為取變量 i 的地址。對(duì)于常量表達(dá)式、寄存器變量不能取地址(因?yàn)樗鼈兇鎯?chǔ)在存儲(chǔ)器中,沒(méi)有地址);
- 指針運(yùn)算符*(間接尋址符):與&為逆運(yùn)算,作用是通過(guò)操作對(duì)象的地址,獲取存儲(chǔ)的內(nèi)容。例:x = &i,x 為 i 的地址,間接尋址x 則為通過(guò) i 的地址,獲取 i 的內(nèi)容;
- 關(guān)系:*x = &x;
代碼示例:
int a;//聲明了一個(gè)普通變量a
int *pa;//聲明一個(gè)指針變量,指向變量a的地址
pa = &a;//通過(guò)取地址符&,獲取a的地址,賦值給指針變量
printf("%d",*pa);//通過(guò)間接尋址符,獲取指針指向的內(nèi)容
- 注意:聲明中的*符號(hào)和其他情況下使用的意義不同,聲明中的僅僅表示聲明的變量為指針變量,另起一行賦值時(shí)不需要帶上星號(hào);其他情況下為指針運(yùn)算符,通過(guò)操作對(duì)象的地址,獲取存儲(chǔ)的內(nèi)容;為符號(hào)的復(fù)用。
(3)指針與數(shù)組
Ⅰ、相同點(diǎn)
- 數(shù)組名是數(shù)組第一個(gè)元素的地址,即
char str[6]={0,1,2,3,4,5};
char *P=str;
//輸入第一個(gè)元素,以下兩條語(yǔ)句功能相同
scanf("%s\n",str);
scanf("%s\n",p);
//打印第一個(gè)元素,以下兩條語(yǔ)句功能相同
printf("%s",*str);
printf("%s",*p);
Ⅱ、不同點(diǎn)
- 數(shù)組名只是一個(gè)地址(常量,不可變),而指針是一個(gè)左值(可變)。
(C語(yǔ)言的術(shù)語(yǔ)lvalue左值指用于識(shí)別或定位一個(gè)存儲(chǔ)位置的標(biāo)識(shí)符,必須是可改變的。)
char str[6]={0,1,2,3,4,5};
char *P=str;
//輸入第二個(gè)元素
//scanf("%s\n",str+1);此為錯(cuò)誤的用法
scanf("%s\n",p+1);
//打印第二個(gè)元素
//printf("%s",*(str+1);此為錯(cuò)誤的用法
printf("%s",*(p+1));
- 注意:p+1并不是簡(jiǎn)單地將地址加1,而是指向數(shù)組的下一個(gè)元素。
2、結(jié)構(gòu)體
(1)基本概念
? 結(jié)構(gòu)體是一種構(gòu)造數(shù)據(jù)類型。數(shù)組是同種類型的數(shù)據(jù)的集合,那么結(jié)構(gòu)體就是不同類型的數(shù)據(jù)組合成的整體。其定義形式如下:
struct 結(jié)構(gòu)體名稱
{
//結(jié)構(gòu)體成員可以是一種基本的數(shù)據(jù)類型,也可以是數(shù)組,或者另一個(gè)結(jié)構(gòu)體
結(jié)構(gòu)體成員1;
結(jié)構(gòu)體成員2;
結(jié)構(gòu)體成員3;
……
};
- 注意:大括號(hào)后面的分號(hào)不能少,這是一條完整的語(yǔ)句。
(2)定義結(jié)構(gòu)體變量
? 結(jié)構(gòu)體聲明僅是進(jìn)行一個(gè)框架的描繪,并不會(huì)為其分配存儲(chǔ)空間, 直到定義一個(gè)結(jié)構(gòu)體變量。
Ⅰ、基本方式
? 定義形式如下:
struct 結(jié)構(gòu)體名稱 結(jié)構(gòu)體變量名
? 示例如下:
#include <stdio.h>
struct Book
{
char title[120];
char author[40];
float price;
unsigned int date;
char publisher[40];
}
int main(void)
{
struct Book book;
return 0;
}
- 這樣定義的變量為局部變量
Ⅱ、在聲明的最后進(jìn)行定義
? 定義形式如下:
struct 結(jié)構(gòu)體名稱
{
//結(jié)構(gòu)體成員可以是一種基本的數(shù)據(jù)類型,也可以是數(shù)組,或者另一個(gè)結(jié)構(gòu)體
結(jié)構(gòu)體成員1;
結(jié)構(gòu)體成員2;
結(jié)構(gòu)體成員3;
……
} 結(jié)構(gòu)體變量名;
- 這樣定義的變量為全局變量
Ⅲ、直接定義結(jié)構(gòu)體變量
定義形式如下:
struct
{
//結(jié)構(gòu)體成員可以是一種基本的數(shù)據(jù)類型,也可以是數(shù)組,或者另一個(gè)結(jié)構(gòu)體
結(jié)構(gòu)體成員1;
結(jié)構(gòu)體成員2;
結(jié)構(gòu)體成員3;
……
} 結(jié)構(gòu)體變量名;
- 只有關(guān)鍵字struct,沒(méi)有結(jié)構(gòu)體名稱。由于沒(méi)有結(jié)構(gòu)體名稱,在此定義語(yǔ)句后面無(wú)法再定義這個(gè)類型的其他結(jié)構(gòu)變量。一般情況下,除非變量不會(huì)再增加,還是建議采用前兩種結(jié)構(gòu)變量的定義形式
Ⅳ、利用typedef進(jìn)行簡(jiǎn)化
? 定義形式如下:
typedef struct 結(jié)構(gòu)體名稱
{
//結(jié)構(gòu)體成員可以是一種基本的數(shù)據(jù)類型,也可以是數(shù)組,或者另一個(gè)結(jié)構(gòu)體
結(jié)構(gòu)體成員1;
結(jié)構(gòu)體成員2;
結(jié)構(gòu)體成員3;
……
} 簡(jiǎn)化的結(jié)構(gòu)體變量定義格式("struct 結(jié)構(gòu)體名稱");
int main(void)
{
簡(jiǎn)化的結(jié)構(gòu)體變量定義格式("struct 結(jié)構(gòu)體名稱") 結(jié)構(gòu)體變量名;
}
- 這樣定義的變量為全局變量
? 示例如下:
typedef struct Book
{
char title[120];
char author[40];
float price;
unsigned int date;
char publisher[40];
} infor;
int main(void)
{
infor book;
return 0;
}
(3)訪問(wèn)結(jié)構(gòu)體變量
Ⅰ、使用點(diǎn)號(hào)運(yùn)算符
? 要訪問(wèn)結(jié)構(gòu)體成員,我們需要引入一個(gè)新的運(yùn)算符——點(diǎn)號(hào)(.)運(yùn)算符。比如book.title就是引用book結(jié)構(gòu)體的title成員,它是一個(gè)字符數(shù)組;而book.price則是引用book結(jié)構(gòu)體的price成員,它是一個(gè)浮點(diǎn)型的變量。示例如下:
typedef struct{
char title[120];
char author[40];
float price;
unsigned int date;
char publisher[40];
} infor;
int main(void)
{
infor book;
book.title[120]="";
book.author[40]="";
book.price=;
book.date=;
book.publisher=;
}
Ⅱ、使用結(jié)構(gòu)體指針(使用運(yùn)算符)
? 要訪問(wèn)結(jié)構(gòu)體成員,我們需要引入一個(gè)新的運(yùn)算符——指針(->)運(yùn)算符。
? 訪問(wèn)形式如下:
結(jié)構(gòu)體指針(結(jié)構(gòu)體的首地址)->結(jié)構(gòu)體成員名=;//意為將值賦給結(jié)構(gòu)體指針指向的結(jié)構(gòu)體成員
//等同于:
(*結(jié)構(gòu)體指針).結(jié)構(gòu)體成員名=;//注意:“.”號(hào)運(yùn)算符優(yōu)先級(jí)比“*”號(hào)運(yùn)算符高,因此要加括號(hào)
? 示例如下:
typedef struct{
char title[120];
char author[40];
float price;
unsigned int date;
char publisher[40];
} infor;
int main(void)
{
infor book;
struct *pt;
pt=&book;
pt->title[120]="";
pt->author[40]="";
pt->price=;
pt->date=;
pt->publisher[40]=;
}
3、枚舉
(1)基本概念
? 枚舉是C語(yǔ)言中的一種基本數(shù)據(jù)類型,它的用途是:定義一個(gè)取值受限制的整形變量,用于限制變量取值范圍,讓數(shù)據(jù)更為簡(jiǎn)潔和易讀,提高可讀性。其定義格式如下:
enum 枚舉類型名稱{
枚舉值名稱,
枚舉值名稱,
……
};
- 注意:大括號(hào)后面的分號(hào)不能少,這是一條完整的語(yǔ)句;每個(gè)成員名稱后的分隔符為“,”,這是與結(jié)構(gòu)體不同的地方。
- 注意:第一個(gè)枚舉成員的默認(rèn)值為整型的 0,后續(xù)枚舉成員的值在前一個(gè)成員上加 1;若我們?cè)谶@個(gè)實(shí)例中把第一個(gè)枚舉成員的值定義為 1,第二個(gè)就為 2,以此類推。
(2)定義枚舉變量
Ⅰ、基本方式
? 定義形式如下:
enum 枚舉類型名稱 枚舉變量1,枚舉變量2;
Ⅱ、在聲明的最后進(jìn)行定義
? 定義形式如下:
enum 枚舉類型名稱{
枚舉值名稱,
枚舉值名稱,
……
} 枚舉變量名;
Ⅲ、直接定義枚舉變量
? 定義形式如下:
enum {枚舉值名稱,枚舉值名稱,……} 枚舉變量名;
- 枚舉類型名稱可以省略;
- 因?yàn)槊杜e變量類型較長(zhǎng),所以通常用typedef更改變量類型名。
(3)訪問(wèn)枚舉成員
? 示例如下:
int main(void)
{
enum Week{Mon=1,Tue,Wed} day;
day = Wed;
return 0;
}
(4)實(shí)例
Ⅰ、常規(guī)用法
#include <stdio.h>
enum WeekDay{Mon=1,Tue,Wed,Thu,Fri,Sat,Sun};
int main(void)
{
enum WeekDay day;
day = Mon; //day = 1;
day = Tue; //day = 2;
printf("%d\n",day);
return 0;
}
Ⅱ、遍歷枚舉類型
#include <stdio.h>
enum Week{Mon=1, Tue, Wed, Thu, Fri, Sat, Sun} day;
int main(){
// 遍歷枚舉元素
for (day = Mon; day <= Sun; day++)
{
printf("枚舉元素:%d\n", day);
}
}
- 僅當(dāng)枚舉類型值連續(xù)才可遍歷。
Ⅲ、STM32中與結(jié)構(gòu)體結(jié)合的用法
typedef enum
{
GPIO_Speed_10MHz = 1,
GPIO_Speed_2MHz,
GPIO_Speed_50MHz
}GPIOSpeed_TypeDef;
typedef struct
{
uint16_t GPIO_Pin;
GPIOSpeed_TypeDef GPIO_Speed; //定義枚舉變量
GPIOMode_TypeDef GPIO_Mode;
}GPIO_InitTypeDef;
int main(void)
{
GPIO_InitTypeDef GPIO_InitStructure; //定義結(jié)構(gòu)體變量
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
}
//節(jié)選
二、STM32F103基本介紹
1、STM32簡(jiǎn)介
? STM32是ST公司基于ARM Cortex-M內(nèi)核開發(fā)的32位微控制器,常應(yīng)用在嵌入式領(lǐng)域,如智能車、無(wú)人機(jī)、機(jī)器人、無(wú)線通信、物聯(lián)網(wǎng)、工業(yè)控制、娛樂(lè)電子產(chǎn)品等。STM32功能強(qiáng)大、性能優(yōu)異、片上資源豐富、功耗低,是一款經(jīng)典的嵌入式微控制器。目前STM32共有四個(gè)系列,分別是高性能系列、主流系列、超低功耗系列和無(wú)線系列,對(duì)應(yīng)的都有不同的產(chǎn)品,如:
- 高性能系列:STM32F2、F4、F7、H7等;
- 主流系列:STM32F0、F1、F3、G0、G4等;
- 超低功耗系列:STM32L0、L1、L4、L4+、L5、U5等;
- 無(wú)線系列:STM32WL、WB等。
2、系統(tǒng)結(jié)構(gòu)
3、STM32F103C8T6基本信息
-
系列:主流系列STM32F1
-
內(nèi)核:ARM Cortex-M3
-
主頻:72MHz
-
RAM:20K(SRAM)
-
ROM:64K(Flash)
-
供電:2.0~3.6V(標(biāo)準(zhǔn)3.3V)
-
封裝:LQFP48
4、STM32F103C8T6片上資源/外設(shè)(Peripheral)
5、引腳定義
6、最小系統(tǒng)電路
三、GPIO通用IO口的使用
1、GPIO簡(jiǎn)介
? GPIO(General Purpose Input Output)通用輸入輸出口,可配置為8種輸入輸出模式,引腳電平:0V~3.3V,部分引腳可容忍5V。
? 輸出模式下可控制端口輸出高低電平,用以驅(qū)動(dòng)LED、控制蜂鳴器、模擬通信協(xié)議輸出時(shí)序等。
? 輸入模式下可讀取端口的高低電平或電壓,用于讀取按鍵輸入、外接模塊電平信號(hào)輸入、ADC電壓采集、模擬通信協(xié)議接收數(shù)據(jù)等。
2、GPIO位結(jié)構(gòu)和工作模式
? GPIO位結(jié)構(gòu)由引腳端口、驅(qū)動(dòng)器和寄存器組成。由圖可以將結(jié)構(gòu)分為兩部分,一是上半部分,為輸入模式;二是下半部分,為輸出模式。
- 輸入模式:共四種輸入模式,上拉電阻和下拉電阻將其分為三種模式,分別為上拉輸入(連接上拉電阻)、下拉輸入(連接下拉電阻)和浮空輸入(上拉、下拉電阻均不連接);后通過(guò)施密特觸發(fā)器對(duì)電壓進(jìn)行整形然后輸入;不通過(guò)施密特觸發(fā)器的為模擬輸入,引腳直接接入內(nèi)部ADC。
上拉電阻接通時(shí),保證引腳為高電平;
下拉電阻接通時(shí),保證引腳為低電平;
施密特觸發(fā)器執(zhí)行邏輯:如果輸入電壓大于某一閾值,輸入就會(huì)瞬間升為高電平;如果輸入電壓小于某一閾值,輸入就會(huì)瞬間降為低電平。
- 輸出模式:共四種輸出模式,輸出可以由輸出數(shù)據(jù)寄存器或者片上外設(shè)控制(復(fù)用輸出);在輸出控制部分,由兩個(gè)MOS管將其分為三種模式,分別為推挽輸出(兩個(gè)MOS管都有效)、開漏模式(N—MOS管有效)和關(guān)閉(配置為輸入模式時(shí),兩個(gè)MOS管都無(wú)效)。
MOS管相當(dāng)于一種電子開關(guān),通過(guò)信號(hào)來(lái)控制開關(guān)的導(dǎo)通和關(guān)閉,開關(guān)負(fù)責(zé)使IO口輸出高或低電平;
推挽輸出模式(強(qiáng)推輸出模式)下,高低電平均有較強(qiáng)的驅(qū)動(dòng)能力,STM32對(duì)IO口有絕對(duì)的控制權(quán);
開漏輸出模式下,只有低電平有驅(qū)動(dòng)能力,高電平?jīng)]有驅(qū)動(dòng)能力;常作為通信協(xié)議的驅(qū)動(dòng)方式,在多機(jī)通信的情況下,這個(gè)模式可以避免各個(gè)設(shè)備的相互干擾;還可用于輸出5V的電平信號(hào)
- 一個(gè)端口只能有一個(gè)輸出,但可以有多個(gè)輸入。即在輸入模式下,輸出都是無(wú)效的;在輸出模式下,輸入模式也是有效的。
? 通過(guò)配置GPIO的端口配置寄存器,端口可以配置成以下8種模式:
3、不同外設(shè)的GPIO配置
? 內(nèi)容較多,見(jiàn)STM32F10XXX參考手冊(cè)。
4、GPIO常用寄存器
(1)端口配置低\高寄存器(GPIOx_CRL/GPIOx_CRH)(x=A…E)
? 端口配置寄存器共16位,但每4位數(shù)據(jù)表示1位,共需要64位,而STM32中每個(gè)寄存器都為32位,因此分為端口配置低寄存器和端口配置高寄存器。通過(guò)端口配置寄存器可以配置GPIO工作模式與端口輸出速度。
輸出速度可以限制輸出引腳的最大翻轉(zhuǎn)速度,作用是降低功耗、提高穩(wěn)定性,一般情況下配置為50MHz。
(2)端口輸入數(shù)據(jù)寄存器(GPIOx_IDR)(x=A…E)
? 輸入數(shù)據(jù)共16位,但寄存器共32位,因此寄存器高16位為空。
(3)端口輸出數(shù)據(jù)寄存器(GPIOx_ODR)(x=A…E)
? 輸出數(shù)據(jù)共16位,但寄存器共32位,因此寄存器高16位為空。
(4)端口位設(shè)置/清除寄存器(GPIOx_BERR)(x=A…E)
? 高16位用于清除,低16位用于設(shè)置。
- 高16位:為0不影響;為1清0;
- 低16為:為0不影響;為1置1。
(5)端口位清除寄存器(GPIOx_BER)(x=A…E)
? 高16位為空,低16位用于清除,方法同上。
(5)端口位配置鎖定寄存器(GPIOx_LCKR)(x=A…E)
? 高15位為空,低17位用于鎖定,較少使用。
5、GPIO常用函數(shù)
(1)RCC常用函數(shù)
? 在RCC時(shí)鐘控制的函數(shù)庫(kù)中,我們最經(jīng)常用到的是以下三個(gè)函數(shù):
//AHB系統(tǒng)總線時(shí)鐘控制
void RCC_AHBPeriphClockCmd(uint32_t RCC_AHBPeriph, FunctionalState NewState);
//APB2總線時(shí)鐘控制
void RCC_APB2PeriphClockCmd(uint32_t RCC_APB2Periph, FunctionalState NewState);
//APB1總線時(shí)鐘控制
void RCC_APB1PeriphClockCmd(uint32_t RCC_APB1Periph, FunctionalState NewState);
/*第一個(gè)參數(shù)為外設(shè)選擇,與STM32互聯(lián)型的設(shè)備在下列列表中選擇:
* @arg RCC_AHBPeriph_DMA1
* @arg RCC_AHBPeriph_DMA2
* @arg RCC_AHBPeriph_SRAM
* @arg RCC_AHBPeriph_FLITF
* @arg RCC_AHBPeriph_CRC
* @arg RCC_AHBPeriph_OTG_FS
* @arg RCC_AHBPeriph_ETH_MAC
* @arg RCC_AHBPeriph_ETH_MAC_Tx
* @arg RCC_AHBPeriph_ETH_MAC_Rx
*
* @arg RCC_APB2Periph_AFIO, RCC_APB2Periph_GPIOA, RCC_APB2Periph_GPIOB,
* RCC_APB2Periph_GPIOC, RCC_APB2Periph_GPIOD, RCC_APB2Periph_GPIOE,
* RCC_APB2Periph_GPIOF, RCC_APB2Periph_GPIOG, RCC_APB2Periph_ADC1,
* RCC_APB2Periph_ADC2, RCC_APB2Periph_TIM1, RCC_APB2Periph_SPI1,
* RCC_APB2Periph_TIM8, RCC_APB2Periph_USART1, RCC_APB2Periph_ADC3,
* RCC_APB2Periph_TIM15, RCC_APB2Periph_TIM16, RCC_APB2Periph_TIM17,
* RCC_APB2Periph_TIM9, RCC_APB2Periph_TIM10, RCC_APB2Periph_TIM11
*
* @arg RCC_APB1Periph_TIM2, RCC_APB1Periph_TIM3, RCC_APB1Periph_TIM4,
* RCC_APB1Periph_TIM5, RCC_APB1Periph_TIM6, RCC_APB1Periph_TIM7,
* RCC_APB1Periph_WWDG, RCC_APB1Periph_SPI2, RCC_APB1Periph_SPI3,
* RCC_APB1Periph_USART2, RCC_APB1Periph_USART3, RCC_APB1Periph_USART4,
* RCC_APB1Periph_USART5, RCC_APB1Periph_I2C1, RCC_APB1Periph_I2C2,
* RCC_APB1Periph_USB, RCC_APB1Periph_CAN1, RCC_APB1Periph_BKP,
* RCC_APB1Periph_PWR, RCC_APB1Periph_DAC, RCC_APB1Periph_CEC,
* RCC_APB1Periph_TIM12, RCC_APB1Periph_TIM13, RCC_APB1Periph_TIM14
*
* 其他設(shè)備在下列列表中選擇:
* @arg RCC_AHBPeriph_DMA1
* @arg RCC_AHBPeriph_DMA2
* @arg RCC_AHBPeriph_SRAM
* @arg RCC_AHBPeriph_FLITF
* @arg RCC_AHBPeriph_CRC
* @arg RCC_AHBPeriph_FSMC
* @arg RCC_AHBPeriph_SDIO
*
*可用按位或(|)來(lái)選擇多個(gè)外設(shè)
*
*第二個(gè)參數(shù)為選擇使能或失能,選擇:ENABLE or DISABLE
*/
? GPIO連接在APB2總線上,且假定以PA0為接口,則使能GPIO的函數(shù)為:
void RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
(2)GPIO常用函數(shù)
? 在GPIO通用IO口的函數(shù)庫(kù)中,我們最經(jīng)常用到的是以下函數(shù):
//復(fù)位函數(shù),調(diào)用這個(gè)函數(shù)后,所指定的GPIO外設(shè)就會(huì)被復(fù)位
void GPIO_DeInit(GPIO_TypeDef* GPIOx);
//復(fù)位函數(shù),可以復(fù)位AFIO外設(shè)
void GPIO_AFIODeInit(void);
//初始化函數(shù),功能:用結(jié)構(gòu)體的參數(shù)來(lái)初始化GPIO口
//初始化時(shí),我們需要先定義一個(gè)結(jié)構(gòu)體變量,然后給結(jié)構(gòu)體賦值,最后調(diào)用初始化函數(shù),函數(shù)內(nèi)部會(huì)自動(dòng)讀取結(jié)構(gòu)體的值,然后把外設(shè)的各個(gè)參數(shù)配置好。
void GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct);
//功能:把結(jié)構(gòu)體變量賦一個(gè)默認(rèn)值
void GPIO_StructInit(GPIO_InitTypeDef* GPIO_InitStruct);
//以下四個(gè)函數(shù)為GPIO的讀取函數(shù),均有返回值
//功能:讀取輸入數(shù)據(jù)寄存器某一個(gè)端口的輸入值
uint8_t GPIO_ReadInputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
//功能:讀取整個(gè)輸入數(shù)據(jù)寄存器
uint16_t GPIO_ReadInputData(GPIO_TypeDef* GPIOx);
//功能:讀取輸出數(shù)據(jù)寄存器的某一位,用于輸出模式下,查看輸入的值
uint8_t GPIO_ReadOutputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
//功能:讀取整個(gè)輸出數(shù)據(jù)寄存器
uint16_t GPIO_ReadOutputData(GPIO_TypeDef* GPIOx);
//以下四個(gè)函數(shù)為GPIO的寫入函數(shù)
//功能:將指定端口引腳設(shè)置為高電平
void GPIO_SetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
//功能:將指定端口引腳設(shè)置為低電平
void GPIO_ResetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
//功能:對(duì)指定端口進(jìn)行寫入操作
void GPIO_WriteBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, BitAction BitVal);
//功能:同時(shí)對(duì)16個(gè)端口進(jìn)行寫入操作
void GPIO_Write(GPIO_TypeDef* GPIOx, uint16_t PortVal);
/*參數(shù)注釋:
*①GPIO_TypeDef* GPIOx,GPIO端口選擇,值為GPIOx(x=A~G);
*可用按位或(|)來(lái)選擇多個(gè)端口
*
*②uint16_t GPIO_Pin,IO口引腳選擇,一個(gè)GPIO端口有16個(gè)引腳,所以其值為GPIO_Pin_x(x=0~15)
*可用按位或(|)來(lái)選擇多個(gè)引腳
*
*③BitAction BitVal,指定寫入的數(shù)據(jù)值,這個(gè)參數(shù)可以是BitAction枚舉中的一個(gè)值,值為:
* @arg Bit_RESET:清除端口值,即置低電平
* @arg Bit_SET:設(shè)置端口值,即置高電平
*
*④uint16_t PortVal,指定要寫入端口輸出數(shù)據(jù)寄存器的值
*
*⑤GPIO_InitTypeDef* GPIO_InitStruct,GPIO初始化結(jié)構(gòu)體的地址
*/
/*初始化結(jié)構(gòu)體定義:
*①定義一個(gè)結(jié)構(gòu)體變量
*GPIO_InitTypeDef GPIO_InitStructure;
*結(jié)構(gòu)體如下:
*typedef struct
*{
* uint16_t GPIO_Pin;
* GPIOSpeed_TypeDef GPIO_Speed;
* GPIOMode_TypeDef GPIO_Mode;
*}GPIO_InitTypeDef;
*由此可知該結(jié)構(gòu)體有三個(gè)成員,分別為GPIO_Pin、GPIO_Speed和GPIO_Mode,下一步就是分別賦值
*
*②給結(jié)構(gòu)體賦值:
*GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //設(shè)置推挽輸出
*GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; //使用GPIO的0號(hào)引腳
*GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//速度為50MHz
*
*GPIO_Mode,用于設(shè)置工作模式,其枚舉如下:
*typedef enum
*{ GPIO_Mode_AIN = 0x0, //模擬輸入模式(Analog IN)
* GPIO_Mode_IN_FLOATING = 0x04, //浮空輸入模式
* GPIO_Mode_IPD = 0x28, //下拉輸入模式(In Pull Down)
* GPIO_Mode_IPU = 0x48, //上拉輸入模式(In Pull Up)
* GPIO_Mode_Out_OD = 0x14, //開漏輸出模式(Out Open Drain)
* GPIO_Mode_Out_PP = 0x10, //推挽輸出模式(Out Push Pull)
* GPIO_Mode_AF_OD = 0x1C, //復(fù)用開漏模式(Atl Open Drain)
* GPIO_Mode_AF_PP = 0x18 //復(fù)用推挽模式(Atl Push Pull)
*}GPIOMode_TypeDef;
*
*GPIO_Pin,選擇引腳,值為GPIO_Pin_x(x=0~15和All)
*
*GPIO_Speed,選擇輸出速度,其枚舉如下:
*typedef enum
*{
* GPIO_Speed_10MHz = 1,
* GPIO_Speed_2MHz,
* GPIO_Speed_50MHz
*}GPIOSpeed_TypeDef;
*常用速度為50MHz
*/
6、GPIO初始化
? 以用低電平驅(qū)動(dòng)的方式點(diǎn)亮一個(gè)接在PA0口的LED,并使其閃爍為例。
(1)使用RCC開啟GPIO的時(shí)鐘
? GPIO連接在APB2總線上,且以PA0為接口,則使能時(shí)鐘的函數(shù)為:
void RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
(2)使用GPIO_Init函數(shù)初始化GPIO
? 為了保證高低電平的強(qiáng)驅(qū)動(dòng)能力,選用推挽輸出,代碼如下:
//定義結(jié)構(gòu)體變量(局部變量)
GPIO_InitTypeDef GPIO_InitStructure;
//訪問(wèn)結(jié)構(gòu)體變量(引出結(jié)構(gòu)體成員)
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //設(shè)置推挽輸出
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; //使用GPIO的0號(hào)引腳
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//速度為50MHz
(3)使用輸出或輸入的函數(shù)控制GPIO口
? 調(diào)用輸入的函數(shù),GPIO_SetBits()、GPIO_ResetBits()和GPIO_WriteBit()均可單獨(dú)設(shè)置引腳低電平,代碼如下:
GPIO_ResetBits(GPIOA,GPIO_Pin_0);
Delay_ms(250);
GPIO_SetBits(GPIOA,GPIO_Pin_0);
Delay_ms(250);
GPIO_WriteBit(GPIOA,GPIO_Pin_0,Bit_RESET);
Delay_ms(250);
GPIO_WriteBit(GPIOA,GPIO_Pin_0,Bit_SET);
Delay_ms(250);
//通過(guò)強(qiáng)制轉(zhuǎn)換為BitAction的枚舉類型來(lái)直接輸入高低電平
GPIO_WriteBit(GPIOA,GPIO_Pin_0,(BitAction)0);
Delay_ms(250);
GPIO_WriteBit(GPIOA,GPIO_Pin_0,(BitAction)1);
Delay_ms(250);
7、GPIO應(yīng)用實(shí)例
(1)LED閃爍
? LED有來(lái)兩種驅(qū)動(dòng)方式:高電平驅(qū)動(dòng)和低電平驅(qū)動(dòng),對(duì)STM32來(lái)說(shuō),兩種驅(qū)動(dòng)方式均可,但是因?yàn)楹芏鄦纹瑱C(jī)或者芯片,都使用了高電平弱驅(qū)動(dòng)、低電平強(qiáng)驅(qū)動(dòng)的規(guī)則,這樣可以在一定程度上避免高低電平?jīng)_突,所以常使用低電平驅(qū)動(dòng)方式。
開漏輸出模式下,只有低電平有驅(qū)動(dòng)能力,高電平?jīng)]有驅(qū)動(dòng)能力,因此無(wú)法進(jìn)行高電平驅(qū)動(dòng)。
? 代碼如下(LED連接PA0口):
#include "stm32f10x.h" // Device header
#include "Delay.h"
/*
*第一步,使用RCC開啟GPIO的時(shí)鐘
*第二步,使用GPIO_Init函數(shù)初始化GPIO
*第三步,使用輸出或輸入的函數(shù)控制GPIO口
*/
int main(void)
{
//第一步,開啟時(shí)鐘
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
//第二步,初始化GPIO
//定義結(jié)構(gòu)體變量(局部變量)
GPIO_InitTypeDef GPIO_InitStructure;
//訪問(wèn)結(jié)構(gòu)體變量(引出結(jié)構(gòu)體成員)
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //設(shè)置推挽輸出
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; //使用GPIO的0號(hào)引腳
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//速度為50MHz
//使用GPIO_Init函數(shù)初始化GPIO
GPIO_Init(GPIOA, &GPIO_InitStructure);
//第三步,控制GPIO口
while(1)
{
GPIO_ResetBits(GPIOA,GPIO_Pin_0);
Delay_ms(250);
GPIO_SetBits(GPIOA,GPIO_Pin_0);
Delay_ms(250);
GPIO_WriteBit(GPIOA,GPIO_Pin_0,Bit_RESET);
Delay_ms(250);
GPIO_WriteBit(GPIOA,GPIO_Pin_0,Bit_SET);
Delay_ms(250);
//通過(guò)強(qiáng)制轉(zhuǎn)換為BitAction的枚舉類型來(lái)直接輸入高低電平
GPIO_WriteBit(GPIOA,GPIO_Pin_0,(BitAction)0);
Delay_ms(250);
GPIO_WriteBit(GPIOA,GPIO_Pin_0,(BitAction)1);
Delay_ms(250);
}
}
(2)LED流水燈
? 實(shí)現(xiàn)基本流水燈(LED連接PA0~PA6),代碼如下:
#include "stm32f10x.h" // Device header
#include "Delay.h"
int main(void)
{
//第一步,開啟時(shí)鐘
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
//第二步,初始化GPIO
//定義結(jié)構(gòu)體變量(局部變量)
GPIO_InitTypeDef GPIO_InitStructure;
//訪問(wèn)結(jié)構(gòu)體變量(引出結(jié)構(gòu)體成員)
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //設(shè)置推挽輸出
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_All; //使用GPIO的所有引腳
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//速度為50MHz
//使用GPIO_Init函數(shù)初始化GPIO
GPIO_Init(GPIOA, &GPIO_InitStructure);
while(1)
{
//低電平驅(qū)動(dòng),因此需要取反
GPIO_Write(GPIOA,~0x0001); //0000 0000 0000 0001
Delay_ms(500);
GPIO_Write(GPIOA,~0x0002); //0000 0000 0000 0010
Delay_ms(500);
GPIO_Write(GPIOA,~0x0004); //0000 0000 0000 0100
Delay_ms(500);
GPIO_Write(GPIOA,~0x0008); //0000 0000 0000 1000
Delay_ms(500);
GPIO_Write(GPIOA,~0x0010); //0000 0000 0001 0000
Delay_ms(500);
GPIO_Write(GPIOA,~0x0020); //0000 0000 0010 0000
Delay_ms(500);
GPIO_Write(GPIOA,~0x0040); //0000 0000 0100 0000
Delay_ms(500);
}
}
? 實(shí)現(xiàn)往返流水燈,代碼如下:
#include "stm32f10x.h" // Device header
#include "Delay.h"
int main(void)
{
//第一步,開啟時(shí)鐘
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
//第二步,初始化GPIO
//定義結(jié)構(gòu)體變量(局部變量)
GPIO_InitTypeDef GPIO_InitStructure;
//訪問(wèn)結(jié)構(gòu)體變量(引出結(jié)構(gòu)體成員)
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //設(shè)置推挽輸出
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_All; //使用GPIO的所有引腳
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//速度為50MHz
//使用GPIO_Init函數(shù)初始化GPIO
GPIO_Init(GPIOA, &GPIO_InitStructure);
while(1)
{
unsigned int i;
for(i=0;i<7;i++)
{
GPIO_Write(GPIOA,~(0x0001<<i));
Delay_ms(250);
}
for(i=0;i<7i++)
{
GPIO_Write(GPIOA,~(0x0040>>i));
Delay_ms(250);
}
}
}
(3)GPIO控制有源蜂鳴器
?
? 有源蜂鳴器同樣使用低電平驅(qū)動(dòng),不過(guò)接口為PB12,代碼如下:
#include "stm32f10x.h" // Device header
#include "Delay.h"
int main(void)
{
//第一步,開啟時(shí)鐘
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
//第二步,初始化GPIO
//定義結(jié)構(gòu)體變量(局部變量)
GPIO_InitTypeDef GPIO_InitStructure;
//訪問(wèn)結(jié)構(gòu)體變量(引出結(jié)構(gòu)體成員)
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //設(shè)置推挽輸出
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12; //使用GPIO的12號(hào)引腳
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//速度為50MHz
//使用GPIO_Init函數(shù)初始化GPIO
GPIO_Init(GPIOB, &GPIO_InitStructure);
//第三步,控制GPIO口
while(1)
{
GPIO_ResetBits(GPIOB,GPIO_Pin_12);
Delay_ms(100);
GPIO_SetBits(GPIOB,GPIO_Pin_12);
Delay_ms(100);
GPIO_ResetBits(GPIOB,GPIO_Pin_12);
Delay_ms(100);
GPIO_SetBits(GPIOB,GPIO_Pin_12);
Delay_ms(700);
}
}
(4)按鍵控制LED
- 實(shí)際效果:兩個(gè)按鍵對(duì)應(yīng)兩個(gè)LED,按一次亮,再按一次滅。
?
? 按鍵1連接PB1,按鍵2連接PB11;LED1連接PA1,LED2連接PA2,使用模塊化編程,代碼如下:
①LED.c
#include "stm32f10x.h" // Device header
void LED_Init(void)
{
//RCC使能時(shí)鐘
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
//初始化GPIO
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_2;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
//使兩個(gè)端口默認(rèn)高電平,使LED處于未點(diǎn)亮的狀態(tài)
GPIO_SetBits(GPIOA,GPIO_Pin_1 | GPIO_Pin_2);
}
//點(diǎn)亮對(duì)應(yīng)的LED
void LED_ON(unsigned char i)
{
if(i==1)
{
GPIO_ResetBits(GPIOA,GPIO_Pin_1);
}
if(i==2)
{
GPIO_ResetBits(GPIOA,GPIO_Pin_2);
}
}
//熄滅對(duì)應(yīng)的LED
void LED_OFF(unsigned char i)
{
if(i==1)
{
GPIO_SetBits(GPIOA,GPIO_Pin_1);
}
if(i==2)
{
GPIO_SetBits(GPIOA,GPIO_Pin_2);
}
}
//通過(guò)檢測(cè)輸出數(shù)據(jù)寄存器的數(shù)據(jù),得到當(dāng)前的LED狀態(tài),再用相反作用的函數(shù)使其狀態(tài)變化
void LED_Turn(unsigned char i)
{
if(i == 1)
{
if(GPIO_ReadOutputDataBit(GPIOA,GPIO_Pin_1) == 0)//檢測(cè)輸出數(shù)據(jù)寄存器的數(shù)據(jù)是否為0
{
GPIO_SetBits(GPIOA,GPIO_Pin_1); //若為0,即LED點(diǎn)亮?xí)r,對(duì)應(yīng)數(shù)據(jù)位置1,即熄滅
}
else
{
GPIO_ResetBits(GPIOA,GPIO_Pin_1);
}
}
if(i == 2)
{
if(GPIO_ReadOutputDataBit(GPIOA,GPIO_Pin_2) == 0)//檢測(cè)輸出數(shù)據(jù)寄存器的數(shù)據(jù)是否為0
{
GPIO_SetBits(GPIOA,GPIO_Pin_2); //若為0,即LED點(diǎn)亮?xí)r,對(duì)應(yīng)數(shù)據(jù)位置1,即熄滅
}
else
{
GPIO_ResetBits(GPIOA,GPIO_Pin_2);
}
}
}
- 51單片機(jī)使用按鍵控制LED亮滅時(shí),是直接將數(shù)據(jù)取反,但32不是直接對(duì)寄存器進(jìn)行操作,而是調(diào)用已經(jīng)封裝好的庫(kù)函數(shù),因此不能直接取反。所以STM32通過(guò)函數(shù)檢測(cè)輸出數(shù)據(jù)寄存器的數(shù)據(jù),得到當(dāng)前的LED狀態(tài),再用相反作用的函數(shù)使其狀態(tài)變化以達(dá)到取反的效果,使用的函數(shù)為:
GPIO_ReadOutputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
②Key.c
#include "stm32f10x.h" // Device header
#include "Delay.h"
void Key_Init(void)
{
//RCC使能時(shí)鐘
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
//初始化GPIO
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_11;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB,&GPIO_InitStructure);
}
//消除抖動(dòng)后返回對(duì)應(yīng)鍵碼
uint8_t Key_GetNum(void)
{
uint8_t KeyNum = 0;
if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_1) == 0)
{
Delay_ms(20);
while(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_1) == 0);
Delay_ms(20); //消除抖動(dòng)
KeyNum = 1;
}
if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_11) == 0)
{
Delay_ms(20);
while(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_11) == 0);
Delay_ms(20); //消除抖動(dòng)
KeyNum = 2;
}
return KeyNum;
}
③main.c
#include "stm32f10x.h" // Device header
#include "Delay.h"
#include "LED.h"
#include "Key.h"
uint8_t KeyNum;
int main(void)
{
LED_Init(); //LED端口初始化
Key_Init(); //按鍵端口初始化
while(1)
{
KeyNum = Key_GetNum();
if(KeyNum == 1)
{
LED_Turn(1);
}
if(KeyNum == 2)
{
LED_Turn(2);
}
}
}
(5)光敏傳感器控制蜂鳴器
- 實(shí)際效果:當(dāng)光敏傳感器被遮蔽時(shí),蜂鳴器鳴響。
- 光敏傳感器:當(dāng)亮度高于閾值時(shí),輸出指示燈亮,表示輸出低電平;當(dāng)亮度低于閾值時(shí),輸出指示燈滅,表示輸出高電平;閾值可通過(guò)上面的電位器調(diào)節(jié)。
- 光敏傳感器初始化時(shí),需要選擇上拉工作模式,因?yàn)楣饷魝鞲衅鞯墓ぷ髟砭褪?strong>將光敏電阻與上拉電阻串聯(lián),通過(guò)分壓來(lái)實(shí)現(xiàn)對(duì)亮度的感知。
? 蜂鳴器連接PB12口,光敏傳感器連接PB13口,使用模塊化編程,代碼如下:
①Buzzer.c
#include "stm32f10x.h" // Device header
void Buzzer_Init(void)
{
//RCC使能時(shí)鐘
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
//初始化GPIO
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);
//使蜂鳴器默認(rèn)靜默
GPIO_SetBits(GPIOB,GPIO_Pin_12);
}
//蜂鳴器鳴響
void Buzzer_ON(void)
{
GPIO_ResetBits(GPIOB,GPIO_Pin_12);
}
//蜂鳴器靜默
void Buzzer_OFF(void)
{
GPIO_SetBits(GPIOB,GPIO_Pin_12);
}
//蜂鳴器狀態(tài)翻轉(zhuǎn)
//通過(guò)檢測(cè)輸出數(shù)據(jù)寄存器的數(shù)據(jù),得到當(dāng)前的蜂鳴器狀態(tài),后使用函數(shù)改變蜂鳴器當(dāng)前狀態(tài)
void Buzzer_Turn(void)
{
if(GPIO_ReadOutputDataBit(GPIOB,GPIO_Pin_12) == 0)//檢測(cè)輸出數(shù)據(jù)寄存器的數(shù)據(jù)是否為0
{
GPIO_SetBits(GPIOB,GPIO_Pin_12); //若為0,即蜂鳴器鳴響,對(duì)應(yīng)數(shù)據(jù)位置1,即使蜂鳴器靜默
}
else
{
GPIO_ResetBits(GPIOB,GPIO_Pin_12);
}
}
②LightSensor.c文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-430091.html
#include "stm32f10x.h" // Device header
//光敏傳感器初始化
void LightSensor_Init(void)
{
//RCC使能時(shí)鐘
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
//初始化GPIO
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //使用上拉輸出模式
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);
}
//返回光敏傳感器的電平情況
uint8_t LightSensor_Get(void)
{
return GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_13);
}
③main.c文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-430091.html
#include "stm32f10x.h" // Device header
#include "Delay.h"
#include "Buzzer.h"
#include "LightSensor.h"
int main(void)
{
Buzzer_Init(); //蜂鳴器初始化
LightSensor_Init(); //光敏傳感器初始化
while(1)
{
if(LightSensor_Get() ==1)//如果光敏傳感器接收的亮度低于閾值,則蜂鳴器鳴響
{
Buzzer_ON();
}
else
{
Buzzer_OFF();
}
}
}
到了這里,關(guān)于江科大自化協(xié)STM32學(xué)習(xí)筆記(部分C語(yǔ)言知識(shí)、STM32簡(jiǎn)介和GPIO口的使用)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!