历史上的今天
返回首页

历史上的今天

今天是:2024年08月30日(星期五)

正在发生

2021年08月30日 | 玩转STM32CubeMX | 按键输入

2021-08-30 来源:eefocus

1.实验介绍

本实验介绍如何使用STM32F103的IO口作为输入使用。IO口作为输入使用时,是通过读取IDR的内容来读取IO口的状态的。实验中利用板载的4个按键,来控制板载的两个LED的亮灭和蜂鸣器。其中KEY_UP控制蜂鸣器;K1控制D1,按一次亮再按一次灭;K2控制D2,按一次亮再按一次灭;K3同时控制D1和D2,按一次它们的状态就翻转一次


2.硬件设计

用到的硬件资源有:


*指示灯D1、D2


*蜂鸣器BUZ


*4个按键


硬件连接原理图如下,注意K1、K2、K3是低电平有效的,而KEY_UP是高电平有效,并且外部都没有上下拉电阻,所以需要在STM32F1内部设置上下拉;

STM32F103芯片单个IO口最大输出电流是25mA,而蜂鸣器的驱动电流是30mA左右,整个芯片的输出电流最大为150mA,如果在蜂鸣器上就消耗30mA,那么芯片的其他IO口及外设电流就比较拮据了,因此此处不会直接使用IO口驱动蜂鸣器,而是通过三极管把电流放大后再驱动蜂鸣器,这样IO口只需提供不到1mA的电流就可以控制蜂鸣器

3.软件设计

3.1 STM32CubeMX设置


➡️ RCC设置外接HSE,时钟设置为72M


➡️ PC0和PC2设置为GPIO推挽输出模式、上拉、高速、默认输出电平为高电平


➡️ PB5设置为GPIO推挽输出、高速模式


➡️ PA0设置为GPIO输入下拉模式;PE2、PE3、PE4设置为GPIO输入上拉模式


➡️ 输入工程名,选择工程路径(不要有中文),选择MDK-ARM V5;勾选Generated periphera initialization as a pair of ‘.c/.h’ files per IP ;点击GENERATE CODE,生成工程代码


3.2 MDK-ARM软件编程


➡️ 在gpio.c文件中可以看到PC0、PC1、PB5、PA0、PE2、PE3、PE4管脚的初始化函数


void MX_GPIO_Init(void)

{

  GPIO_InitTypeDef GPIO_InitStruct = {0};


  __HAL_RCC_GPIOE_CLK_ENABLE();        //开启GPIOE时钟

  __HAL_RCC_GPIOC_CLK_ENABLE();        //开启GPIOC时钟

  __HAL_RCC_GPIOA_CLK_ENABLE();        //开启GPIOA时钟

  __HAL_RCC_GPIOB_CLK_ENABLE();        //开启GPIOB时钟

  //LED1/LED2默认输出是电平为高电平

  HAL_GPIO_WritePin(GPIOC, LED1_Pin|LED2_Pin, GPIO_PIN_SET);    

  //BUZ默认输出是电平为低电平    

  HAL_GPIO_WritePin(BUZ_GPIO_Port, BUZ_Pin, GPIO_PIN_RESET);    


  GPIO_InitStruct.Pin = K_LEFT_Pin|K_DOWN_Pin|K_RIGHT_Pin;  //PE2/PE3/PE4

  GPIO_InitStruct.Mode = GPIO_MODE_INPUT;           //输入

  GPIO_InitStruct.Pull = GPIO_PULLUP;               //上拉

  HAL_GPIO_Init(GPIOE, &GPIO_InitStruct);


  GPIO_InitStruct.Pin = LED1_Pin|LED2_Pin;          //PC0/PC1

  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;       //推挽输出

  GPIO_InitStruct.Pull = GPIO_PULLUP;               //上拉

  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;     //高速

  HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);


  GPIO_InitStruct.Pin = K_UP_Pin;                   //PA0

  GPIO_InitStruct.Mode = GPIO_MODE_INPUT;           //输入

  GPIO_InitStruct.Pull = GPIO_PULLDOWN;             //下拉

  HAL_GPIO_Init(K_UP_GPIO_Port, &GPIO_InitStruct);


  GPIO_InitStruct.Pin = BUZ_Pin;                    //PB5

  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;       //推挽输出

  GPIO_InitStruct.Pull = GPIO_NOPULL;               //无上下拉

  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;     //高速

  HAL_GPIO_Init(BUZ_GPIO_Port, &GPIO_InitStruct);

}


➡️ 在工程的应用文件目录下创建key.c文件,编写按键相关函数


/***********************************************************

*函 数 名: KEY_Scan(uint8_t mode)

*功    能: 按键处理函数

*形    参: mode:0 不支持连续按;1 支持连续按

*返 回 值: 返回按键值   0:表示未有按键按下

*                      1:KEY_RIGHT按下   2:KEY_DOWN按下

*                      3:KEY_LEFT按下    4:KEY_UP按下

***********************************************************/

uint8_t KEY_Scan(uint8_t mode)

{

    static uint8_t key = 1;     //按键松开标志

    if(mode == 1){              //支持连按

        key = 1;

    }


    if(key&&(KEY_UP==1||KEY_DOWN==0||KEY_LEFT==0||KEY_RIGHT==0)){

        HAL_Delay(10);          //按键消抖

        key = 0;

        if(KEY_UP==1)           return K_UP_PRES;

        else if(KEY_DOWN==0)    return K_DOWN_PRES; 

        else if(KEY_LEFT==0)    return K_LEFT_PRES; 

        else if(KEY_RIGHT==0)   return K_RIGHT_PRES; 

    }

    else if(KEY_UP==0&&KEY_DOWN==1&&KEY_LEFT==1&&KEY_RIGHT==1){

        key = 1;

    }


    return 0;

}


➡️ 在工程的头文件目录下创建key.h文件,编写相关声明


#ifndef _KEY_H_

#define _KEY_H_


#include "stm32f1xx.h"


//操作HAL库函数读取IO口状态

#define KEY_RIGHT   HAL_GPIO_ReadPin(GPIOE,GPIO_PIN_4)

#define KEY_DOWN    HAL_GPIO_ReadPin(GPIOE,GPIO_PIN_3)

#define KEY_LEFT    HAL_GPIO_ReadPin(GPIOE,GPIO_PIN_2)

#define KEY_UP      HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0)

//定义按键按下时的键值

#define KEY_RIGHT_PRES   1

#define KEY_DOWN_PRES    2

#define KEY_LEFT_PRES    3

#define KEY_UP_PRES      4


uint8_t KEY_Scan(uint8_t mode);


#endif


➡️ 在main.c函数中编写相关程序


int main(void)

{

  /* USER CODE BEGIN 1 */

  uint8_t key;

  /* USER CODE END 1 */

  HAL_Init();

  SystemClock_Config();

  MX_GPIO_Init();

  /* USER CODE BEGIN WHILE */

  while (1)

  {

      key = KEY_Scan(0);

      switch(key){

          case KEY_UP_PRES:

              HAL_GPIO_WritePin(GPIOB,BUZ_Pin,GPIO_PIN_SET);

              HAL_Delay(300);

              HAL_GPIO_WritePin(GPIOB,BUZ_Pin,GPIO_PIN_RESET);

              HAL_Delay(300);

              break;

          case KEY_LEFT_PRES:

              HAL_GPIO_TogglePin(GPIOC,LED1_Pin);

              break;

          case KEY_DOWN_PRES:

              HAL_GPIO_TogglePin(GPIOC,LED2_Pin);

              break;

          case KEY_RIGHT_PRES:

              HAL_GPIO_TogglePin(GPIOC,LED1_Pin);

              HAL_GPIO_TogglePin(GPIOC,LED2_Pin);

              break;

      }

      HAL_Delay(10);

  /* USER CODE END WHILE */

  }

}


4.下载验证

编译无误后下载到开发板,按下KEY_UP蜂鸣器响一下;K1控制D1,按一次亮再按一次灭;K2控制D2,按一次亮再按一次灭;K3同时控制D1和D2,按一次它们的状态就翻转一次


推荐阅读

史海拾趣

Good Sky Electric Co Ltd公司的发展小趣事
电气原理图在摇臂钻床维修中起着至关重要的作用。它详细描绘了设备的电气控制系统和元件之间的连接关系,为维修人员提供了准确的故障排查和检修依据。通过仔细阅读和分析电气原理图,维修人员可以迅速定位故障点并采取相应的修复措施,从而缩短维修时间并降低维修成本。
驰兴电感(Coilank)公司的发展小趣事

为了进一步提升产品的竞争力,驰兴电感积极开展国际合作。公司与国际知名电子元器件厂商建立了长期稳定的合作关系,共同研发新产品、新技术。这些国际合作不仅使驰兴电感能够借鉴国际先进经验和技术,还为公司带来了更多的市场机会和资源。

FINISAR公司的发展小趣事

FINISAR公司(前身为Finisar Corporation)成立于1987年(另有资料称成立于1988年),总部位于美国加利福尼亚州的硅谷地区。公司自创立之初便专注于光通信技术的研发与应用,致力于设计、制造和销售高性能的光模块和光网络设备。在成立初期,FINISAR凭借其创新的技术和高质量的产品,在光通信市场上逐渐崭露头角,为后续的快速发展奠定了坚实基础。

FUJI公司的发展小趣事

随着业务的不断扩展,FINISAR开始在全球范围内布局。公司在中国、马来西亚、美国、澳大利亚、以色列、新加坡、印度、韩国等多个国家设立了子公司和研发中心,形成了全球化的生产和服务网络。这一战略布局不仅增强了FINISAR的市场竞争力,还为公司带来了更多的发展机遇。特别是在中国市场,FINISAR凭借其先进的技术和优质的产品,赢得了众多知名企业的青睐,如思科、IBM、华为等。

倍思特(BEST)公司的发展小趣事

FINISAR在光模块领域取得了多项重要技术创新和突破。例如,公司在1992年推出了首个850nm的千兆多模光纤光收发模块,随后在1995年推出了带数字诊断功能的光收发模块,这些创新产品极大地推动了光通信技术的发展。此外,FINISAR还不断推出新产品以满足市场需求,如SFP光模块、CWDM GBIC光模块等,这些产品均获得了市场的广泛认可。

EDI [Electronic devices inc.]公司的发展小趣事

在1950年代,Eclipse Magnetics公司决定将他们的磁铁涂上红色,并与马蹄形标志和公司颜色相匹配。这个简单的改变在当时看似微不足道,但却成为了一个重要的转折点。红色磁铁不仅提升了产品的视觉吸引力,还增强了品牌识别度。随着红色磁铁的广泛应用,Eclipse Magnetics开始逐渐在电子行业中崭露头角。

问答坊 | AI 解惑

无线收发模块汇总

本帖最后由 paulhyde 于 2014-9-15 09:06 编辑 :P :P :P :P :P :P :P :P :P :P :P 好东西大家一起分享!!!  …

查看全部问答>

采用FPGA的可编程电压源系统原理及设计2

程序中,duty为控制占空比的参数;count为控制分频的参数。通过改变duty和count两个参数,得到占空比及分频数可调的时钟信号,极为方便。 2.2 其他模块的实现     其他控制模块包括地址发生器、DAC控制电路、并/串转换电路。存储数据 ...…

查看全部问答>

哪位大侠能提供一下nor flash M29W128G 的fast program 的代码

nor flash M29W128G 可以32个words fast program, 哪位大哥有这个写的代码,能否给小弟一下,谢谢了。…

查看全部问答>

Camera 应用开发

平台:6410+WINCE6.0 新开一个贴,再讨论一下这个CAMERA应用开发,因为本人一直是做驱动的,现在要写应用,而且是COM接口的directshow,所以有很多东西要向大家请教,    用640X480分辩进行preview 和 拍照都没有问题,但是,我驱动给di ...…

查看全部问答>

6410硬件编解码的一点疑问?

我主要想知道硬件编解码之前的数据是什么格式或者封装的?之后应该就是H.264,MPEG-4之类的吧。之前呢?通过以太网接口的以太网数据帧(应该包含视频流的)能直接通过硬件编解码进行播放吗? 还有TV-in,进来的是什么数据?那个接口是接什么的? ...…

查看全部问答>

大家帮我看看我的内核出了什么问题

第一次来这里,谢谢大家 刚开始做做BSP5.0移植到6.0 现在编出来的内核打印信息如下: Windows CE Kernel for ARM (Thumb Enabled) Built on Sep  6 2006 at 19:14:27 INFO:OALLogSetZones: dpCurSettings.ulZoneMask: 0xb OEM: Not ...…

查看全部问答>

如何禁用蓝牙、红外线等设备?

想写一个过滤驱动,实现禁用蓝牙,红外线等设备, 请问要将过滤驱动挂载在注册表的什么地方? 我发现过载在 注册表HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentConrolSet\\Control\\Class\\{E0CBF06C-CD8B-4647-BB8A-263B43F0F974},在这个位置并不能完 ...…

查看全部问答>

cpu怎么访问硬盘的

各位大侠,小弟有点不明白,32位地址总线的CPU,最大可以读到2@32,也就是4G的地址,那么160G的硬盘,它怎么读到的呢?直接访问好像访问不到吧?谢谢了…

查看全部问答>

msgQreceive返回error,表示什么?

是代表队列没数据,还是什么错误啊?一般都是什么引起的?多谢啊…

查看全部问答>

出一块STM32野火开发板99新

野火STM32开发板,买的是428的套餐,买到手里1个多月,没用过,就是刚到手里的时候吧包装拆开了,现打算350包邮出,有意的可以直接拍下,帮我同学卖的,不刀,要的可以联系我QQ 99044007  照片就不上了,没有任何的使用,所以也不需要看 ...…

查看全部问答>