2021/10/12智能家具嵌入式實訓第三天 蜂鳴器+按鍵代碼 (1)


 

完成昨天的蜂鳴器+按鍵+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
View Code

 

再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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM