目录

代码分享

代码说明

1.LED初始化:

2.按键检测:

3.LED状态切换:

4.消抖处理:

硬件连接说明

扩展功能(可选)

推挽输出与开漏输出


代码分享

key.h文件

#ifndef _KEY_H
#define _KEY_H
#include "stm32f10x.h"

void Key_Init(void);
uint8_t Key_GetNum(void);

#endif

key.c文件

#include "stm32f10x.h"
#include"Delay.h"
#include"key.h"
void Key_Init()
{
	
	 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
	
	 GPIO_InitTypeDef GPIO_InitStrucure;
	 GPIO_InitStrucure.GPIO_Mode=GPIO_Mode_IPU;
	 GPIO_InitStrucure.GPIO_Pin=GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_4|GPIO_Pin_5;
	 GPIO_Init(GPIOB,&GPIO_InitStrucure);
	
}

uint8_t Key_GetNum(void)
{
	uint8_t KeyNum=0;
	if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_0)==0)
	{
		Delay_ms(20);
		while(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_0)==0);
		Delay_ms(20);
		KeyNum=1;
	}
	if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_1)==0)
	{
		Delay_ms(20);
		while(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_1)==0);
		Delay_ms(20);
		KeyNum=2;
	}
	if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_4)==0)
	{
		Delay_ms(20);
		while(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_4)==0);
		Delay_ms(20);
		KeyNum=3;
	}
	if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_5)==0)
	{
		Delay_ms(20);
		while(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_5)==0);
		Delay_ms(20);
		KeyNum=4;
	}
	return KeyNum;
}

main.c文件

#include "stm32f10x.h"
#include "Delay.h"
#include "key.h"

uint8_t KeyNum;

int main(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;
    
    // 使能GPIOA和AFIO时钟
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO, ENABLE);
    
    // 重映射PA15为普通IO口
    GPIO_PinRemapConfig(GPIO_Remap_SWJ_Disable, ENABLE);
    
    // 初始化LED引脚(GPIOA_Pin_8)
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;  // 推挽输出
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;        // PA8
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; // 50MHz速度
    GPIO_Init(GPIOA, &GPIO_InitStructure);
    
    // 初始状态:LED熄灭(假设低电平点亮,高电平熄灭)
    GPIO_WriteBit(GPIOA, GPIO_Pin_8, Bit_SET);
    
    // 初始化按键
    Key_Init();
    
    while (1)
    {
        // 获取按键值
        KeyNum = Key_GetNum();
        
        // 当按键1被按下时
        if (KeyNum == 1)
        {
            // 切换LED状态
            if (GPIO_ReadOutputDataBit(GPIOA, GPIO_Pin_8) == Bit_SET)
            {
                // 当前是高电平(熄灭),切换为低电平(点亮)
                GPIO_WriteBit(GPIOA, GPIO_Pin_8, Bit_RESET);
            }
            else
            {
                // 当前是低电平(点亮),切换为高电平(熄灭)
                GPIO_WriteBit(GPIOA, GPIO_Pin_8, Bit_SET);
            }
        }
    }
}

代码说明

1.LED初始化:

将GPIOA的Pin8配置为推挽输出模式

初始状态设置为高电平(假设LED是低电平点亮,所以初始状态为熄灭)

2.按键检测:

调用Key_Init()初始化按键引脚(GPIOB的Pin0、Pin1、Pin4、Pin5)

在While(1)循环中持续检测按键状态

3.LED状态切换:

当检测到按键1(GPIOB_Pin_0)被按下时:

        读取当前LED引脚的状态

        如果是高电平(熄灭),切换为低电平(点亮)

        如果是低电平(点亮),切换为高电平(熄灭)

4.消抖处理:

按键消抖已在key.c文件中通过DeLay_ms(20)实现,确保按键操作稳定

硬件连接说明

LED :连接到GPIOA的Pin8引脚,建议串联一个220Ω电阻到GND

按键 :连接到GPIOB的Pin0引脚,一端接GPIOB_Pin0,另一端接GND

扩展功能(可选)

如果需要使用其他按键(如GPIOB_Pin_1、Pin_4、Pin_5)控制不同功能,可以在 key.c 中完善 Key_GetNum() 函数,返回不同的按键值,然后在 main.c 中添加对应的处理逻辑。例如:

// 在key.c中完善Key_GetNum()函数
uint8_t Key_GetNum(void)
{
    uint8_t KeyNum = 0;
    
    // 检测按键1(Pin0)
    if (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_0) == 0)
    {
        Delay_ms(20);
        while (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_0) == 0);
        Delay_ms(20);
        KeyNum = 1;
    }
    
    // 检测按键2(Pin1)
    if (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_1) == 0)
    {
        Delay_ms(20);
        while (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_1) == 0);
        Delay_ms(20);
        KeyNum = 2;
    }
    
    // 检测按键3(Pin4)
    if (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_4) == 0)
    {
        Delay_ms(20);
        while (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_4) == 0);
        Delay_ms(20);
        KeyNum = 3;
    }
    
    // 检测按键4(Pin5)
    if (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_5) == 0)
    {
        Delay_ms(20);
        while (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_5) == 0);
        Delay_ms(20);
        KeyNum = 4;
    }
    
    return KeyNum;
}

然后在 main.c 中添加对应的处理:

while (1)
{
    KeyNum = Key_GetNum();
    
    switch (KeyNum)
    {
        case 1:
            // 切换LED状态
            if (GPIO_ReadOutputDataBit(GPIOA, GPIO_Pin_8) == Bit_SET)
            {
                GPIO_WriteBit(GPIOA, GPIO_Pin_8, Bit_RESET);
            }
            else
            {
                GPIO_WriteBit(GPIOA, GPIO_Pin_8, Bit_SET);
            }
            break;
            
        case 2:
            // 其他功能...
            break;
            
        // 其他按键处理...
    }
}

推挽输出与开漏输出

工作原理对比

1.推挽输出(GPIO Mode_Out PP)

高电平输出:        P-MOS管导通,N-MOS管截止,直接输出VDD(如3.3V)

低电平输出:        N-MOS管导通,P-MOS管截止,直接输出GND(0V)
驱动能力:        高低电平都有较强的驱动能力(可直接驱动LED、继电器等负载)
外部电路:        无需外部上拉电阻

2.开漏输出(GPIo_Mode_Out_OD)

高电平输出:        MOS管截止,引脚处于高阻态(需要外部上拉电阻才能输出高电平)

低电平输出:        MOS管导通,输出GND(0V)
驱动能力:        仅低电平有驱动能力,高电平驱动能力取决于外部上拉电阻

外部电路:        必须外接上拉电阻(否则高电平状态不确定)

LED控制场景分析

1.推挽输出的适用性

对于LED控制,推挽输出通常是首选,原因如下:

无需外部元件:        直接驱动LED,电路简洁
电平稳定:        高低电平由GPIO直接输出,电压稳定
驱动能力强:        可驱动多个LED或亮度更高的LED
响应速度快:        无外部上拉电阻的延迟

2.开漏输出的适用性

开漏输出在LED控制中可以使用,但有条件:

必须加外部上拉电阻:否则高电平无法正常输出,LED可能闪烁或不亮
适合电平匹配:如果LED使用的电源与MCU不同(如5V LED),可通过上拉电阻连接到5V,实现电平转换

高低电平影响的考虑

在LED控制中,高低电平的影响主要体现在:

1.LED连接方式

共阴接法(LED负极接地):需要GPIO输出低电平点亮,高电平熄灭

        推挽输出:低电平直接GND,驱动可靠

        开漏输出:低电平直接GND,但高电平需上拉电阻

共阳接法(LED正极接VDD):需要GPIO输出高电平点亮,低电平熄灭

        推挽输出:高电平直接VDD,驱动可靠

        开漏输出:高电平必须依赖上拉电阻,否则无法点亮

2.驱动能力

推挽输出:

        高电平驱动能力:约20mA(具体取决于MCU型号)

        低电平驱动能力:约20mA

开漏输出:

        高电平驱动能力:由上拉电阻和电源决定(I=(Vcc-Vout/R上拉)

        低电平驱动能力:与推挽输出相近(约20mA)

代码示例对比

推挽输出

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;  // 推挽输出
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);

开漏输出(需外部上拉电阻)

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;  // 开漏输出
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
// 外部需接:GPIOA8 -> 上拉电阻(1kΩ) -> VDD

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐