STM32
直播中

凤毛麟角

8年用户 861经验值
私信 关注
[问答]

如何利用STM32CubeMX实现按键点个灯?

如何利用STM32CubeMX实现按键点个灯?

回帖(2)

武梨格

2021-11-26 15:45:38
前言

相信在看完上一篇非常详细的“简单”教程之后,即便是一个小白,对与STM32CubeMX也是了如指掌了。那么接下来进入单片机学习最关键的环节,点灯,俗话说:点灯是芯片开发最精髓的部分(我说的都是俗话)。那么学习完点灯也就对STM32HAL库的学习有着质的飞跃了。通过点灯我将对GPIO的用法进行一个最全面的介绍。
材料

正点原子探索者开发板,芯片为STM32F407ZGT6
开发板的原理图
STM32F4系列HAL库开发手册
STM32CubeMX
keil5

新建及配置工程

具体新建过程就不详细说了,还不懂的小朋友看STM32CubeMX实战教程(一)——软件入门。好我们直接来到这个界面,老办法,先配置一下时钟,这个实验具体时钟是多少影响不大。





那么接下来打开我们STM32开发板的原理图,分别找到按键和LED的位置,可以看到有两个可编程LED,和四个按键,从中我们可以获得几点信息。



  • led接了上拉电阻,低电平导通
  • 三个按键下拉,低电平有效
  • 一个按键上拉,高电平有效






另外找到芯片对应的引脚号,LED分别是PF9、PF10,按键分别是PE2、PE3、PE4










记下来之后直接回到我们新建的STM32CubeMX工程中找到对应的引脚,这里我们使能五个引脚,其中LED对应的PF9、PF10选择GPIO_Output





而按键对应的则是PE2、PE3、PE4,选择GPIO_Input即输入





接下来我们在左侧的System Core一栏里面找到GPIO一项可以对刚刚使能的GPIO进行配置





先看到LED的配置,这五行分别是



  • 有效电平状态(高/低电平有效)
  • 输出模式(推挽/开漏输出)
  • 上下拉(不上拉或下拉/上拉/下拉输出)
  • 引脚速度(极高/高/中/低速)
  • 重命名
    在本次实验中,引脚的输出速度并不重要,所以可不必考虑,名字则可以根据用户习惯,在程序中仅仅是多了一个宏定义,而输出的方式则是需要考虑到驱动LED的引脚需要一定的驱动能力





    接下来是按键,输入模式中有三行选择,实际上是两行,因为GPIO模式不可选
  • 上下拉(不上拉或下拉/上/下拉)
  • 重命名
    这里选择上拉同样是因为原理图中按键是接地的,所以要提供内部上拉,低电平有效
    所有前期配置到这里就基本完成了,其他地方基本不需要去动,因为没有用到其他外设,接下来就可以生成代码,在keil里面进行进一步配置。为什么不能在STM32CubeMX完成所有配置呢?这里需要强调一点:STM32CubeMX只能配置所有的初始化,而单片机具体的工作,在这个软件里面是无法完成的,就像一间公司招进来很多员工,人事部可以让你调配到某个部门,而具体工作则不是人事部需要分配的
    但毕竟这时候我们又可以战术性地喝点水,偷个懒了。

HAL库之GPIO

在进入代码之前,先要给大家介绍一下HAL库里面的GPIO部分,和标准库一样,HAL库将所有的外设库都分了类并封装在不同的 .c文件下,那么我们该怎么去学会运用给我们提供的库函数呢。理所应当地,要会用一样东西当然就要知道它的功能,以及适用的情况,HAL库也是这么一个道理,这时候我比较推荐去看HAL库的HAL库开发手册,虽然在封装后的 .c 文件中已经有对于函数相对全面的介绍,但是在手册中不但更加完善清晰,而且有很多的适用场合说明,方便理解 ,接下来我以GPIO为例,去对手册进行一个较为全面的说明。
ps:手册是全英的,经费不够,没法全文翻译,见谅
外设结构

从目录可以看到,手册将每一种外设都封装成如下结构,前文介绍的是程序寄存器层面的封装,中间介绍的是库函数接口描述(这里也是我们重点要看的部分),最下面是一些宏定义,上下两层一般情况也不需要看。





继续展开中间层,从函数的介绍描述到使用方法都一目了然了,那么对于GPIO这种简单的外设就不从最开始介绍起了,可以直接进入函数功能的讲解。




API

HAL库中给我们驱动GPIO提供的API函数接口并不多,但也足矣,每个函数都可以直接点击,便会直接跳转到具体函数功能描述界面。













  • GPIO使能是在STM32CubeMX代码生成后会自动调用的,不需要手动配置
  • HAL_GPIO_DeInit当用户不再用到某个GPIO时可以调用,相当于复位GPIO寄存器,较少用
  • ReadPin、WritePin、TogglePin这三个函数分别是GPIO状态的读、写、反转操作
  • 最后两个函数则是在开启外部中断后才需要用到的中断处理函数和中断回调函数,会在后面的教程中介绍
    而函数中需要填写的参数也可以在函数的具体介绍中找到,所以这个手册还是很方便的


进入代码
接下来,生成代码,进入工程,编译,喜提两个鸭蛋,这些就不多说了,遇到什么bug也可以回STM32CubeMX实战教程(一)——软件入门看看。


int main(void)
{
  /* USER CODE BEGIN 1 */


  /* USER CODE END 1 */
  


  /* MCU Configuration--------------------------------------------------------*/


  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();


  /* USER CODE BEGIN Init */


  /* USER CODE END Init */


  /* Configure the system clock */
  SystemClock_Config();


  /* USER CODE BEGIN SysInit */


  /* USER CODE END SysInit */


  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  /* USER CODE BEGIN 2 */


  /* USER CODE END 2 */




  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */


    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}


进来直接看到main函数里面的**MX_GPIO_Init();**然后追到GPIO初始化的地方


void MX_GPIO_Init(void)
{


  GPIO_InitTypeDef GPIO_InitStruct = {0};


  /* GPIO Ports Clock Enable */
  __HAL_RCC_GPIOE_CLK_ENABLE();
  __HAL_RCC_GPIOC_CLK_ENABLE();
  __HAL_RCC_GPIOF_CLK_ENABLE();
  __HAL_RCC_GPIOH_CLK_ENABLE();


  /*Configure GPIO pin Output Level */
  HAL_GPIO_WritePin(GPIOF, LED0_Pin|LED1_Pin, GPIO_PIN_SET);


  /*Configure GPIO pins : PEPin PEPin PEPin */
  GPIO_InitStruct.Pin = key0_Pin|key1_Pin|key2_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
  GPIO_InitStruct.Pull = GPIO_PULLUP;
  HAL_GPIO_Init(GPIOE, &GPIO_InitStruct);


  /*Configure GPIO pins : PFPin PFPin */
  GPIO_InitStruct.Pin = LED0_Pin|LED1_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_PULLUP;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
  HAL_GPIO_Init(GPIOF, &GPIO_InitStruct);


}


可以看到这里确实是调用了HAL_GPIO_Init();对我们刚刚在STM32CubeMX上面配置的GPIO进行了初始化,具体是怎么初始化的不需要我们深入了解,总之现在可以直接用啦。
另外,我们可以打开main.h这个头文件,可以看到我们之前的命名,也就是端口号的宏定义


/* Private defines -----------------------------------------------------------*/
#define key0_Pin GPIO_PIN_2
#define key0_GPIO_Port GPIOE
#define key1_Pin GPIO_PIN_3
#define key1_GPIO_Port GPIOE
#define key2_Pin GPIO_PIN_4
#define key2_GPIO_Port GPIOE
#define LED0_Pin GPIO_PIN_9
#define LED0_GPIO_Port GPIOF
#define LED1_Pin GPIO_PIN_10
#define LED1_GPIO_Port GPIOF


这就意味着我们可以直接使用刚刚的命名进行GPIO的操作也是没有问题的
随后回到main函数的while循环中并添加如下代码,这里说明一下,HAL_Delay(); 是HAL库提供的毫秒级延时函数,这里有一个坑,就是有时候会卡死,具体原因会在后面的教程中进行分析。


  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
        if(HAL_GPIO_ReadPin(key0_GPIO_Port,key0_Pin)==0)
        {
                HAL_Delay(100);
                if(HAL_GPIO_ReadPin(key0_GPIO_Port,key0_Pin)==0)
                {
                        HAL_GPIO_WritePin(LED0_GPIO_Port,LED0_Pin,GPIO_PIN_RESET);
                }
        }
        if(HAL_GPIO_ReadPin(key1_GPIO_Port,key1_Pin)==0)
        {
                HAL_Delay(100);
                if(HAL_GPIO_ReadPin(key1_GPIO_Port,key1_Pin)==0)
                {
                        HAL_GPIO_WritePin(LED0_GPIO_Port,LED0_Pin,GPIO_PIN_SET);
                }
        }
        if(HAL_GPIO_ReadPin(key2_GPIO_Port,key2_Pin)==0)
        {
                HAL_Delay(100);
                if(HAL_GPIO_ReadPin(key2_GPIO_Port,key2_Pin)==0)
                {
                        HAL_GPIO_TogglePin(LED1_GPIO_Port,LED1_Pin);
                        HAL_GPIO_TogglePin(LED0_GPIO_Port,LED0_Pin);
                }
        }       
    /* USER CODE END WHILE */


    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */


经过前面的介绍,这段代码也是非常容易了,key0按下时点亮LED0,key1按下时熄灭LED0,key2按下时反转两个LED的状态。可能这个时候会有疑问,为什么SET是熄灭,RESET是点亮呢。其实SET和RESET在这里的意思仅仅是输出高/低电平,并不知道LED在什么状况下会亮,而我们之前在STM32CubeMX上面所配置的高/低电平有效仅仅是保证了初始化完毕之后LED是熄灭的,这也可以回到GPIO的初始化函数中看到调用了


  /*Configure GPIO pin Output Level */
  HAL_GPIO_WritePin(GPIOF, LED0_Pin|LED1_Pin, GPIO_PIN_SET);



下载验证

具体下载方法这里不再重复,可查看STM32CubeMX实战教程(一)——软件入门,工程源文件我已经上传,非常抱歉由于CSDN官网上传的资源必须要设定积分,否则几乎无法通过审核,这里就没有办法免费开发给大家,不过源码在教程里已经非常详细了。 另外如果没有HAL库开发手册可以去ST官网自行下载,都是免费的。
这是工程及源码《按键点个灯——基于STM32CubeMX》
结语

非常感谢大家的阅读,如有不当或者错误的地方,欢迎指正,谢谢支持。
一个字一个字敲出来不容易,如果觉得有帮助,点个赞再走呗
祝大家事业蒸蒸日上!
奥里给~
举报

jinyi7016

2021-11-29 09:56:21
两个IO,一个输入,一个输出,输入的是按键,输出的是LED灯
举报

更多回帖

发帖
×
20
完善资料,
赚取积分