完成昨天的蜂鳴器+按鍵+led代碼
led:
原理圖:
代碼部分:
先定義led.h
1 1 #ifndef __LED_H 2 2 #define __LED_H 3 3 4 4 #include "stm32f10x.h" 5 5 #include "delay.h" 6 6 7 7 /* 管腳宏定義*/ 8 8 #define LED1_PORT GPIOE 9 9 #define LED1_PIN 2 10 10 #define LED2_PORT GPIOE 11 11 #define LED2_PIN 3 12 12 #define LED3_PORT GPIOE 13 13 #define LED3_PIN 4 14 14 #define LED4_PORT GPIOE 15 15 #define LED4_PIN 5 16 /* 操作宏定義 */ 17 enum LED_CONDITION{OFF,ON}; 18 #define LED1(x) (x)?GPIO_ResetBits(LED1_PORT,GPIO_Pin_2):GPIO_SetBits(LED1_PORT,GPIO_Pin_2) // 1 -- 打開 0 -- 關閉 19 #define LED2(x) (x)?GPIO_ResetBits(LED2_PORT,GPIO_Pin_3):GPIO_SetBits(LED2_PORT,GPIO_Pin_3) 20 #define LED3(x) (x)?GPIO_ResetBits(LED3_PORT,GPIO_Pin_4):GPIO_SetBits(LED3_PORT,GPIO_Pin_4) 21 #define LED4(x) (x)?GPIO_ResetBits(LED4_PORT,GPIO_Pin_5):GPIO_SetBits(LED4_PORT,GPIO_Pin_5)
enum:枚舉 https://www.runoob.com/cprogramming/c-enum.html
#define LED1(x) (x)?GPIO_ResetBits(LED1_PORT,GPIO_Pin_2):GPIO_SetBits(LED1_PORT,GPIO_Pin_2) // 1 -- 打開 0 -- 關閉
#define又稱宏定義,標識符為所定義的宏名,簡稱宏。
定義變量 LED1
就是x是1執行第一種情況,是0執行第二種情況
x=1是假,A為假,則C
GPIO_SetBits(LED1_PORT,GPIO_Pin_2 打開
x=1是真,A為真,則B
GPIO_ResetBits(LED1_PORT,GPIO_Pin_2) 關閉
這里老師講的設置led翻轉
寄存器ODR就是控制對應引腳的高低電平,每組16位,與寄存器ODR的低16位一致,故若想讓LED燈剛開始是滅的,需要輸出高電平,那么就將對應的位置1即可,
#define LED1_TOGGLE (LED1_PORT->ODR ^= (1 << LED1_PIN)) #define LED2_TOGGLE (LED2_PORT->ODR ^= (1 << LED2_PIN)) #define LED3_TOGGLE (LED3_PORT->ODR ^= (1 << LED3_PIN)) #define LED4_TOGGLE (LED4_PORT->ODR ^= (1 << LED4_PIN))
^=是C/C++的一個符合運算符。表示異或賦值。
如:
a^=b相當於:a=a^b;
舉例:(LED1_PORT->ODR ^= (1 << LED1_PIN))
LED1_PORT->ODR^=1 << LED1_PIN
1<<2= 0000 0001 變為 0000 0100
如果原本是亮的,0000 0100
0000 0100^=0000 0100=00000000
變為0,不亮
在定義函數
/* 函數*/ void LED_Config(int condition); void LED_Breath(void); void LED_Twinkle(void);
#endif
整體代碼:led.h

1 #ifndef __LED_H 2 #define __LED_H 3 4 #include "stm32f10x.h" 5 #include "delay.h" 6 7 /* 管腳宏定義 */ 8 #define LED1_PORT GPIOE 9 #define LED1_PIN 2 10 #define LED2_PORT GPIOE 11 #define LED2_PIN 3 12 #define LED3_PORT GPIOE 13 #define LED3_PIN 4 14 #define LED4_PORT GPIOE 15 #define LED4_PIN 5 16 17 /* 操作宏定義*/ 18 enum LED_CONDITION{OFF,ON}; 19 #define LED1(x) (x)?GPIO_ResetBits(LED1_PORT,GPIO_Pin_2):GPIO_SetBits(LED1_PORT,GPIO_Pin_2) // 1 -- ´ò¿ª £¬ 0 -- ¹Ø±Õ 20 #define LED2(x) (x)?GPIO_ResetBits(LED2_PORT,GPIO_Pin_3):GPIO_SetBits(LED2_PORT,GPIO_Pin_3) 21 #define LED3(x) (x)?GPIO_ResetBits(LED3_PORT,GPIO_Pin_4):GPIO_SetBits(LED3_PORT,GPIO_Pin_4) 22 #define LED4(x) (x)?GPIO_ResetBits(LED4_PORT,GPIO_Pin_5):GPIO_SetBits(LED4_PORT,GPIO_Pin_5) 23 24 #define LED1_TOGGLE (LED1_PORT->ODR ^= (1 << LED1_PIN)) 25 #define LED2_TOGGLE (LED2_PORT->ODR ^= (1 << LED2_PIN)) 26 #define LED3_TOGGLE (LED3_PORT->ODR ^= (1 << LED3_PIN)) 27 #define LED4_TOGGLE (LED4_PORT->ODR ^= (1 << LED4_PIN)) 28 29 /* 函數定義 */ 30 void LED_Config(int condition); 31 void LED_Breath(void); 32 void LED_Twinkle(void); 33 34 #endif
再led.c主代碼
#include "led.h" /*********************************************************************************** 函數功能: LED初始化 形參:condition -- 初始狀態(ON、OFF) 返回值:無 ***********************************************************************************/ /* 管腳: LED1 PE2 LED2 PE3 LED3 PE4 LED4 PE5 */
首先LED_Config 函數
開關燈
這里老師用了二種方法
void LED_Config(int condition) {
1.寄存器法
#if 1 /* 寄存器法 */ // 1.時鍾使能 -- GPIOE端口時鍾 RCC->APB2ENR |= (0x1<<6); // 2.模式配置(通用推挽輸出) GPIOE->CRL &= ~(0xFFFF<<8); //清零 -- [23:8]位 GPIOE->CRL |= (0x3333<<8); //置位 // 3.初始狀態 if(condition == OFF) GPIOE->ODR |= (0xF<<2); else GPIOE->ODR &= ~(0xF<<2);
配置 RCC->APB2ENR 寄存器 使能時鍾端口
打開STM32中文參考手冊,先找到第七章中關於RCC寄存器(APB2外設使能寄存器),找到可以發現以下:
根據電路圖可知,我們需要對IO端口E的時鍾進行使能,有根據手冊可知是第6位置置置為1表示開啟。
#if 1
/* 寄存器法 */
// 1.時鍾使能 -- GPIOE端口時鍾
RCC->APB2ENR |= (0x1<<6);
1移動6位 使第六位變為1 開啟 使能
// 2.模式配置(通用推挽輸出)
GPIOE->CRL &= ~(0xFFFF<<8); //清零 -- [23:8]位
GPIOE->CRL |= (0x3333<<8); //置位
0xFFFF 左移動8位 1111 1111 1111 1111 變為 1111 1111 0000 0000 0xFF00
GPIOE->CRL =GPIOE->CRL & 0000 0000 1111 1111
后面的都變為0
0x3333左移動 8位置 0100 0100 0100 0100 變為 0x3300
然后初始化狀態
// 3.初始狀態
if(condition == OFF)
GPIOE->ODR |= (0xF<<2);
else
GPIOE->ODR &= ~(0xF<<2);
如果關閉 0xF <<2 = 1111 變為 1111 00
GPIOE->ODR 同或 相等為1
所以如果關閉 2位置上 與1同或
0與1為0 關閉
如果開啟
與1111 00 位與
2位置上 1&1 1 開啟
a &= b就是 a= a & b
0xF是二進制的1111,左移1位就是在右邊加個0,也就是11110,左移8位就在右邊加8個0,也就是1111 0000 0000
char類型的話只有8位,就是后面8個0,前面的4個1移出去了。
2.庫函數法
//1.時鍾使能 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE,ENABLE); //2.模式配置 GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_5; GPIO_Init(GPIOE, &GPIO_InitStructure); //3.初始狀態 if(condition == OFF){ GPIO_SetBits(GPIOE,GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_5); } else{ GPIO_ResetBits(GPIOE,GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_5); } #endif
正常定義
這里利用了RCC_APB2PeriphClockCmd函數
最后寫函數功能
/*********************************************************************************** 函數功能: LED 函數接口 ***********************************************************************************/ /* * 呼吸燈(模擬PWM波) */ void LED_Breath(void) { int i = 0; for(i=0;i<1000;i++) //逐漸變亮 { LED1(ON);LED2(ON);LED3(ON);LED4(ON); Delay_nop_nus(i); LED1(OFF);LED2(OFF);LED3(OFF);LED4(OFF); Delay_nop_nus(1000-i); } for(i=0;i<1000;i++) //逐漸變暗 { LED1(OFF);LED2(OFF);LED3(OFF);LED4(OFF); Delay_nop_nus(i); LED1(ON);LED2(ON);LED3(ON);LED4(ON); Delay_nop_nus(1000-i); } } /* * LED閃爍 */ void LED_Twinkle(void) { Delay_nop_nms(500); LED1_TOGGLE;LED2_TOGGLE;LED3_TOGGLE;LED4_TOGGLE; }
結束
編寫主函數 main
main.h
#ifndef __MAIN_H #define __MAIN_H #include "stm32f10x.h" #include "delay.h" #include "led.h" #endif
mian.c
#include "main.h" int main(void) {
LED_Config(ON); while(1) { LED_Breath(); //呼吸燈 LED_Twinkle(); //閃爍燈 } }
然后照這個格式寫蜂鳴器和按鍵
蜂鳴器 BEEP:
beep.h
#ifndef _BEEP_H_ #define _BEEP_H_ #include "stm32f10x.h" #include "led.h" #define BEEP(x) (x)?GPIO_SetBits(GPIOC,GPIO_Pin_0):GPIO_ResetBits(GPIOC,GPIO_Pin_0) // 1 -- 打開 , 0 -- 關閉 #define BEEP_TOGGLE (GPIOC->ODR ^= (0x1<<0)) void Beep_Config(uint8_t condition); void Beep_Twinkle(void); #endif
#define BEEP_TOGGLE (GPIOC->ODR ^= (0x1<<0))
也是蜂鳴器翻轉
BEEP_TOGGLE =GPIOC->ODR異或1
取反
這個蜂鳴器端口正好是pc0
所以0位置 <<0
GPIOC->ODR ^= (0x1<<0) 即為
GPIOC->ODR= GPIOC->ODR 異或 1
如果為開啟的時候
GPIOC->ODR為 1 響 高電平
響的時候 1異或1 為0
關閉
condition借用了
led.h
enum LED_CONDITION{OFF,ON};
beep.c
寄存器法
#include "beep.h" /*********************************************************************************** 函數功能: BEEP初始化 形參:condition -- 初始狀態(ON、OFF) 返回值:無 ***********************************************************************************/ /* 管腳: BEEP -- PC0(通用推挽輸出) */ void Beep_Config(uint8_t condition) { //1.時鍾使能 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE); //2.配置模式 GPIO_InitTypeDef GPIO_InitStruct; GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStruct.GPIO_Pin = GPIO_Pin_0; GPIO_Init(GPIOC,&GPIO_InitStruct); //3.初始化 if(condition == OFF) GPIO_ResetBits(GPIOC,GPIO_Pin_0); else GPIO_SetBits(GPIOC,GPIO_Pin_0); }
/*********************************************************************************** 函數功能: BEEP函數接口 ***********************************************************************************/ /* * BEEP蜂鳴器間斷響 */ void Beep_Twinkle(void) { Delay_nop_nms(1000); BEEP_TOGGLE; }
最后main.c
記得main.h加進去 beep.h
#ifndef __MAIN_H #define __MAIN_H #include "stm32f10x.h" #include "delay.h" #include "led.h" #include "beep.h" #endif
#include "main.h" int main(void) { LED_Config(ON); Beep_Config(OFF); //剛開始關閉 while(1) { //LED_Breath(); //呼吸燈 //LED_Twinkle(); //閃爍燈 Beep_Twinkle();//蜂鳴器間斷響 } }
最后按鍵代碼 key:
先寫key.h
#ifndef _KEY_H_ #define _KEY_H_ #include "stm32f10x.h" #include "delay.h" #define KEY1 GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_0) #define KEY2 GPIO_ReadInputDataBit(GPIOC,GPIO_Pin_4) #define KEY3 GPIO_ReadInputDataBit(GPIOC,GPIO_Pin_5) #define KEY4 GPIO_ReadInputDataBit(GPIOC,GPIO_Pin_6) void KEY_Config(void); uint8_t KEY_GetVal(void); #endif
GPIO_ReadInputDataBit 讀I/O口的電平 1或者0
按鍵不需要關閉開啟
只要知道壓差
再寫key.c
#include "key.h" /*********************************************************************************** 函數功能: KEY初始化 ***********************************************************************************/ /* 管腳: KEY1 -- PA0(浮空輸入模式) 空閑低電平,按下高電平 KEY2 -- PC4(浮空輸入模式) 空閑高電平,按下低電平 KEY3 -- PC5(浮空輸入模式) KEY4 -- PC6(浮空輸入模式) */ void KEY_Config(void) { //1.時鍾使能 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOC,ENABLE); //2.配置模式 GPIO_InitTypeDef GPIO_InitStruct; GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStruct.GPIO_Pin = GPIO_Pin_0; GPIO_Init(GPIOA,&GPIO_InitStruct); GPIO_InitStruct.GPIO_Pin = GPIO_Pin_4 | GPIO_Pin_5 |GPIO_Pin_6; GPIO_Init(GPIOC,&GPIO_InitStruct); }
在寫函數KEY_GetVal
得到key的返回值
/*********************************************************************************** 函數功能: KEY函數接口 ***********************************************************************************/ uint8_t KEY_GetVal(void) { uint8_t key_val; if(KEY1) { Delay_nop_nus(10); if(KEY1) { while(KEY1); key_val = 1; } } if(!KEY2) { Delay_nop_nus(10); if(!KEY2) { while(!KEY2); key_val = 2; } } if(!KEY3) { Delay_nop_nus(10); if(!KEY3) { while(!KEY3); key_val = 3; } } if(!KEY4) { Delay_nop_nus(10); if(!KEY4) { while(!KEY4); key_val = 4; } } return key_val; }
最后編寫main代碼
只要加上就行
#include "main.h" int main(void) { LED_Config(ON); Beep_Config(OFF); //剛開始關閉 KEY_Config(); while(1) { //LED_Breath(); //呼吸燈 //LED_Twinkle(); //閃爍燈 //Beep_Twinkle();//蜂鳴器間斷響 if(KEY_GetVal()==1) //led1 BEEP_TOGGLE;//BEEP翻轉 相當於開 } }
最后附上源代碼:
https://wwa.lanzoui.com/iFi1Pvcghgh