不老树 2024-01-25 19:03 采纳率: 40%
浏览 4

为什么下面这个程序没有出现错误却不能正常点亮led灯呢

#include "stm32f10x.h" // Device header
#include "Delay.h"

int main(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);

GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_SetBits(GPIOA,GPIO_Pin_0);

}

  • 写回答

2条回答 默认 最新

  • CSDN-Ada助手 CSDN-AI 官方账号 2024-01-25 20:06
    关注

    【相关推荐】



    • 你可以看下这个问题的回答https://ask.csdn.net/questions/7528451
    • 你也可以参考下这篇文章:两个led并联和一个电阻串联两个灯不能同时亮问题
    • 您还可以看一下 韦东山老师的韦东山升级版嵌入式视频之快速入门课程中的 LED驱动程序框架小节, 巩固相关知识点
    • 除此之外, 这篇博客: 控制LED灯和蜂鸣器的按键实验中的 不支持连续按 部分也许能够解决你的问题, 你可以仔细阅读以下内容或跳转源博客中阅读:

      当有键按下并且没有松开,只作一次键输入,不当作连续输入。
      led.h中的代码

      #ifndef __LED_H
      #define __LED_H
      
      void LED_Init(void);
      
      #endif
      
      
      

      led.c中的代码

      #include "stm32f10x.h"//顶级头文件引用
      #include "led.h"
      
      void LED_Init()
      {
      	GPIO_InitTypeDef GPIO_InitStruct;//创建GPIO结构体变量
      	
      	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOE,ENABLE);//PB组和PE组IO口时钟使能
      	
      	GPIO_InitStruct.GPIO_Mode=GPIO_Mode_Out_PP;//推挽输出
      	GPIO_InitStruct.GPIO_Pin=GPIO_Pin_5;//引脚5
      	GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;//输出最大速度是50MHZ
      	
      	GPIO_Init(GPIOB,&GPIO_InitStruct);//PB5初始化
      	GPIO_SetBits(GPIOB,GPIO_Pin_5);//PB5初始化为高电平,LED0灭
      	
      	GPIO_Init(GPIOE,&GPIO_InitStruct);//PE5初始化
      	GPIO_SetBits(GPIOE,GPIO_Pin_5);//PE5初始化为高电平,LED1灭
      }
      
      

      beep.h中的代码

      #ifndef __BEEP_H
      #define __BEEP_H
      
      void BEEP_Init(void);
      
      #endif
      
      

      beep.c中的代码

      #include "stm32f10x.h"//顶级头文件引用
      #include "beep.h"
      
      void BEEP_Init()
      {
      	GPIO_InitTypeDef GPIO_InitStruct;//创建GPIO结构体变量
      	
      	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);//在LED初始化函数中已经将PB组IO口使能过了,这里可以不使能
      	
      	GPIO_InitStruct.GPIO_Mode=GPIO_Mode_Out_PP;//推挽输出
      	GPIO_InitStruct.GPIO_Pin=GPIO_Pin_8;//引脚5
      	GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;//输出最大速度是50MHZ
      	
      	GPIO_Init(GPIOB,&GPIO_InitStruct);//PB8初始化
      	GPIO_ResetBits(GPIOB,GPIO_Pin_8);//PB5初始化为低电平,蜂鸣器不响
      }
      
      

      key.h中的代码

      #ifndef __KEY_H
      #define __KEY_H
      #include "stm32f10x.h"//引用顶级头文件
      #include "sys.h"//使用位带操作的头文件
      #define KEY0 GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_4)
      #define KEY1 GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_3)
      #define KEY2 GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_2)
      #define WK_UP GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_0)//宏定义按键名就是IO的值
      
      #define KEY0_PRES 1
      #define KEY1_PRES 2
      #define KEY2_PRES 3
      #define WK_UP_PRES 4//定义键按下后返回的值
      
      #define LED0 PBout(5)
      #define LED1 PEout(5)
      #define beep PBout(8)//使用位带操作加宏定义,直接对硬件名字进行操作
      
      void KEY_Init(void);
      
      uint8_t KEY_Scan(void);//键盘扫描函数
      #endif
      
      

      这里充分使用了宏定义,将每个硬件的名字都赋予了意义,在主程序中直接对硬件名字操作以及使用就可以。
      为了方便改变LED灯以及蜂鸣器的状态,我们使用位带操作的方法,这样就可以直接对LED灯以及蜂鸣器的状态进行取反。
      其中unit8_t类型的变量是STM32固件库中定义的变量类型。

      typedef unsigned          char uint8_t;
      

      可以看到,它的本质是一个无符号的char类型,大小只有一个字节。因为STM32的空间比较小,尽量使用占内存较小的变量。

      key.c中的代码

      #include "stm32f10x.h"
      #include "delay.h"
      #include "key.h"
      
      void KEY_Init()
      {
      	GPIO_InitTypeDef GPIO_InitStruct;//创建GPIO结构体变量
      	
      	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE|RCC_APB2Periph_GPIOA,ENABLE);//使能PE和PA组IO口
      	
      	GPIO_InitStruct.GPIO_Mode=GPIO_Mode_IPU;//设置成上拉输入
      	GPIO_InitStruct.GPIO_Pin=GPIO_Pin_4|GPIO_Pin_3|GPIO_Pin_2;//PE4,PE3,PE2引脚,也就是KEY0,KEY1,KEY2按键
      	
      	GPIO_Init(GPIOE,&GPIO_InitStruct);//按键初始化为上拉输入
      	
      	GPIO_InitStruct.GPIO_Mode=GPIO_Mode_IPD;//设置为下拉输入
      	GPIO_InitStruct.GPIO_Pin=GPIO_Pin_0;//PA引脚,也就是WK_UP按键
      	
      	GPIO_Init(GPIOA,&GPIO_InitStruct);//按键初始化为下拉输入
      }
      
      uint8_t KEY_Scan()
      {
      	static uint8_t key = 1;//储存键的状态,没有键按下时是1
      	if(key&&(KEY0==0|KEY1==0|KEY2==0|WK_UP==1))//是否有键按下
      	{
      		delay_ms(10);//延时消抖
      		if(key&&(KEY0==0|KEY1==0|KEY2==0|WK_UP==1))//是否真的有键按下
      		{
      			key=0;//有键按下,储存为0
      			if(KEY0==0)
      				return KEY0_PRES;//KEY0按下
      			else if(KEY1==0)
      				return KEY1_PRES;//KEY1按下
      			else if(KEY2==0)
      				return KEY2_PRES;//KEY2按下
      			else if(WK_UP==1)//最好加上if,如果只有else的话可除了前面三个键的情况还可能有其他情况干扰WK_UP键的状态
      				return WK_UP_PRES;//WK_UP按下
      		}
      	}
      	else if(KEY0==1&&KEY1==1&&KEY2==1&&WK_UP==0)//为了会更加灵敏
      		key=1;//没有键按下,储存1
      	return 0;//没有键按下,返回0
      }
      
      

      键盘扫描函数的功能就是扫描每个与硬件相连按键的IO口的状况,然后通过这个状况来判断是否有键按下,不同的键按下对应着不同的处理。
      注意:
      判断按键是否按下时,需要进行消抖处理,通常消抖都是通过延时消抖,还可以采用消抖电路来消抖。
      消抖的原因:
      由于外界干扰,以及按键上的弹簧产生的机械作用,按键上的电平会在没有人按下的时候发生微小的变化,如果不作消抖处理,CPU就会将这些由其他因素引起的电平变化当作是键输入来处理,这样就产生了BUG,所以我们要进行消抖。
      当检测到按键上有电平变化时,进行延时处理,一般10ms就够。如果是其他因素引起的电平变化,10ms之内就电平就会恢复,如果是用户按键导致的电平变化,那么在这10ms内就不会恢复到原来的电平状态,就可以认为是有键输入,并且进行相应的处理。
      是不是有个疑问?
      如果我在10ms内按下键并松开,是不是CPU就不会当作键输入处理?
      是这样的,只要你手速够快,就可以骗过CPU,但是我们平常按键时,按一下并松开的时长肯定会超过10ms的。
      让按键更加灵敏

      else if(KEY0==1&&KEY1==1&&KEY2==1&&WK_UP==0)
      

      这是判断没有键输入的语句,这种情况是与有键输入的情况对立的。如果写成只有一个else就笼统的概括没有键输入的情况,这样就会导致按键不灵敏,有时候需要按好几次才会出现对应的反应。

      main.c中的代码

      #include "led.h"
      #include "beep.h"
      
      int main()
      {
      	delay_init();//延时初始化
      	
      	LED_Init();//led初始化
      	
      	BEEP_Init();//蜂鸣器初始化
      	
      	KEY_Init();//按键初始化
      	
      	while(1)
      	{
      		uint8_t ret=KEY_Scan();
      		if(ret)
      		{
      			switch(ret)
      			{
      				case KEY0_PRES:
      					LED0=!LED0;
      					LED1=!LED1;//同时反转俩个LED灯
      					break;
      				case KEY1_PRES:
      					LED0=!LED0;//反转LED0
      					break;
      				case KEY2_PRES:
      					LED1=!LED1;//反转LED1
      					break;
      				case WK_UP_PRES:
      					beep=!beep;//蜂鸣器状态反转
      					break;
      			}
      		}
      		else
      			delay_ms(10);//每隔10ms扫描一次键盘
      	}
      }
      

      当按下右键时,同时控制俩个LED灯的状态发生反转,当按下下键和左键则分别只控制一个LED灯的状态发生反转,当按下上键时,蜂鸣器的状态发生反转。


    如果你已经解决了该问题, 非常希望你能够分享一下解决方案, 写成博客, 将相关链接放在评论区, 以帮助更多的人 ^-^
    评论

报告相同问题?

问题事件

  • 创建了问题 1月25日