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

 

posted @ 2021-10-14 20:27  halfup  阅读(665)  评论(1编辑  收藏  举报