STM32G474按钮输入和点灯

2024-08-20 19:04
文章标签 stm32g474 按钮 点灯 输入

本文主要是介绍STM32G474按钮输入和点灯,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

在获取到工程模板后,学习某个CPU的第一步通常都是IO口操作。因此按钮输入和点灯,就是本次学习的第一个程序。先从简单入手。

和GPIO操作有关的函数如下:
__HAL_RCC_GPIOA_CLK_ENABLE();//使能GPIOA时钟
__HAL_RCC_GPIOB_CLK_ENABLE();//使能GPIOB时钟
__HAL_RCC_GPIOC_CLK_ENABLE();//使能GPIOC时钟
__HAL_RCC_GPIOD_CLK_ENABLE();//使能GPIOD时钟
__HAL_RCC_GPIOF_CLK_ENABLE();//使能GPIOF时钟

HAL_GPIO_Init(GPIO_TypeDef  *GPIOx, GPIO_InitTypeDef *GPIO_Init)
根据GPIO_InitTypeDef型结构变量指定的参数初始化GPIOx的外设寄存器

HAL_GPIO_WritePin(GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin, GPIO_PinState PinState)
PinState=0,GPIOx端口的GPIO_Pin引脚输出低电平;
PinState=1,GPIOx端口的GPIO_Pin引脚输出高电平

HAL_GPIO_TogglePin(GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin)
GPIOx端口的GPIO_Pin的输出电平翻转

HAL_GPIO_ReadPin(GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin)
读取"GPIOx端口的第GPIO_Pin引脚"输入的电平值

HAL_GPIO_DeInit(GPIO_TypeDef  *GPIOx, uint32_t GPIO_Pin)
将"GPIOx端口的GPIO_Pin引脚"的外设寄存器恢复到"复位时的默认值"

HAL_GPIO_LockPin(GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin)
锁定GPIO引脚GPIO_Pin的配置;当GPIO_Pin执行了"锁键的写入时序"后,在下次系统复位前将不能再更改端口位的配置;

1、LED灯初始化

#include "LED.h"

void LED_Init(void);

//函数功能:配置PC13为输出,无上拉或下拉,输出速度为5MHz
void LED_Init(void)
{
  GPIO_InitTypeDef GPIO_InitStruct = {0};

  __HAL_RCC_GPIOC_CLK_ENABLE();                   //GPIOC时钟使能

  GPIO_InitStruct.Pin = GPIO_PIN_13;              //选择引脚号码
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;     //推挽输出模式
    GPIO_InitStruct.Pull = GPIO_NOPULL;             //引脚上拉和下拉都没有被激活
//    GPIO_InitStruct.Pull = GPIO_PULLUP;           //设置上拉
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;    //引脚的输出速度为5MHz
  HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
    //根据GPIO_InitStruct结构变量指定的参数初始化GPIOC的外设寄存器

    LED1_Off();
}

#ifndef __LED_H__
#define __LED_H__

#include "stm32g4xx_hal.h"

#define LED1_On()      HAL_GPIO_WritePin(GPIOC,GPIO_PIN_13,GPIO_PIN_RESET)

//输出低电平开灯


#define LED1_Off()     HAL_GPIO_WritePin(GPIOC,GPIO_PIN_13,GPIO_PIN_SET)

//输出高电平关灯


#define LED1_Toggle()  HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_13)

//LED1引脚输出电平翻转

extern void LED_Init(void);

#endif /*__ GPIO_H__ */

2、Key初始化程序

#include "Key.h"

void Key_Init(void);

//函数功能:将PA12引脚配置为输入引脚
void Key_Init(void)
{
  GPIO_InitTypeDef GPIO_InitStruct = {0};

  __HAL_RCC_GPIOB_CLK_ENABLE();                   //GPIOB时钟使能

  GPIO_InitStruct.Pin = GPIO_PIN_15;               //选择第15脚
    GPIO_InitStruct.Pull = GPIO_PULLUP;             //引脚上拉被激活
//  GPIO_InitStruct.Pull = GPIO_NOPULL;           //引脚上拉和下拉都没有被激活
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_MEDIUM; //配置GPIO速度为中速
    GPIO_InitStruct.Mode = GPIO_MODE_INPUT;         //设置引脚工作模式为输入模式
    HAL_GPIO_Init(GPIOB,&GPIO_InitStruct);
    //根据GPIO_InitStruct结构变量指定的参数初始化GPIOB的外设寄存器
}

#ifndef __Key_H__
#define __Key_H__

#include "stm32g4xx_hal.h"


#define Key_LevelValue() HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_15) //读取Key1的电平值

extern void Key_Init(void);

#endif /* __Key_H */

3、delay.c程序

#include "delay.h"static uint8_t  fac_us=0;							//us延时倍乘数			   
static uint16_t fac_ms=0;							//ms延时倍乘数,在ucos下,代表每个节拍的ms数void My_delay_us(__IO uint32_t nCount);//systick中断服务函数,1ms中断一次
//在调用HAL_Init()时,SysTick定时器初始化为使能中断
void SysTick_Handler(void)
{
}//函数功能:delay函数初始化
//在调用HAL_Init()时,已经对SysTick定时器初始化了,因此这里无需初始化
void delay_init(void)
{uint32_t reload;fac_us=SystemCoreClock/1000000;//相当于将170MHz经过1000000分频用作SysTick的输入时钟,即周期为1us reload=SystemCoreClock/1000000;//相当于将170MHz经过1000000分频用作SysTick的输入时钟,即周期为1us reload*=1000;//SysTick溢出时间为1000*1us=1ms//reload为24位寄存器,最大值:16777216,在170MHz下,约合0.098s左右	fac_ms=1;
}//函数功能:延时nus微妙
//nus:要延时的us数.	
//nus:0~204522252(最大值即2^32/fac_us@fac_us=168)	    								   
void delay_us(uint32_t nus)
{		uint32_t ticks;uint32_t told,tnow,tcnt=0;uint32_t reload=SysTick->LOAD;//读取SysTick的LOAD寄存器的值ticks=nus*fac_us; //计算需要的节拍数 told=SysTick->VAL;//刚进入时的计数器值while(1){tnow=SysTick->VAL;//读SYSTICK计数器值	if(tnow!=told){	    if(tnow<told)tcnt+=told-tnow;	//SysTick定时器是一个递减的计数器.else tcnt+=reload-tnow+told;	    told=tnow;if(tcnt>=ticks)break;			//时间超过/等于要延迟的时间,则退出.}		}										    
}//函数功能:延时nms毫秒
//nms:要延时的ms数
//nms:0~65535
void delay_ms(uint32_t nms)
{  delay_us((uint32_t)(nms*1000));//普通方式延时
}//延时nms,不会引起任务调度
//nms:要延时的ms数
void delay_xms(uint32_t nms)
{uint32_t i;for(i=0;i<nms;i++) delay_us(1000);
}

4、Clock_Config.c程序

#include "Clock_Config.h"
#include "stdio.h"  //getchar(),putchar(),scanf(),printf(),puts(),gets(),sprintf()void SystemClock_Config(void);
void Print_HCLK_PCLK1_PCLK2(void);void SystemClock_Config(void)
{RCC_OscInitTypeDef RCC_OscInitStruct = {0};RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1_BOOST);//配置主内部调节器输出电压//修改PWR->CR1寄存器bit10:9(VOS[1:0]),VOS[1:0]=01b,电压缩放范围选择"Range 1"//Configure the main internal regulator output voltageRCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;//记录修改对象,告诉后面的函数将要对“HSE时钟”进行配置RCC_OscInitStruct.HSEState      = RCC_HSE_ON;RCC_OscInitStruct.PLL.PLLState  = RCC_PLL_ON;RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;RCC_OscInitStruct.PLL.PLLM      = RCC_PLLM_DIV2;//RCC_PLLCFGR寄存器bit7:4(PLLM[3:0]),PLLM[3:0]=0001b,PLLM的值为2RCC_OscInitStruct.PLL.PLLN = 85;//RCC_PLLCFGR寄存器bit14:8(PLLN[3:0]),PLLN[6:0]=0x55,PLLN为的值为85RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;//RCC_PLLCFGR寄存器bit17(PLLP),PLLP=1,PLLP的分频值为17RCC_OscInitStruct.PLL.PLLQ = RCC_PLLQ_DIV2;//RCC_PLLCFGR寄存器bit22:21(PLLQ[1:0]),PLLQ[1:0]=01,PLLQ的分频值为2RCC_OscInitStruct.PLL.PLLR = RCC_PLLR_DIV2;//RCC_PLLCFGR寄存器bit26:25(PLLR[1:0]),PLLR[1:0]=01,PLLR的分频值为2
/*
f(VCO clock) = (HSE_VALUE / PLLM) * PLLN
f(PLL_P) = f(VCO clock) / PLLP
f(PLL_Q) = f(VCO clock) / PLLQ
f(PLL_R) = f(VCO clock) / PLLR
HSE_VALUE = 8000000,外部晶振为8MHz
PLL_VCO = (HSE_VALUE / PLLM) * PLLN = (8000000/2)*85=340000000Hz=340MHz
SYSCLK = PLL_VCO / PLLR = 340000000 / 2 = 170000000Hz = 170MHz
PLL “P” clock = PLL_VCO / 2 = 340000000/2 =170000000Hz = 170MHz
PLL “Q” output clock frequency = VCO frequency / PLLQ = 340000000 / 2 = 170000000Hz = 170MHz
*/if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK){//配置“HSE时钟”和“PLL时钟”Error_Handler();}/** Initializes the CPU, AHB and APB buses clocks*/RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;//记录修改对象,告诉后面的函数将要修改HCLK,SYSCLK,PCLK1,PCLK2等时钟RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;//记录修改对象,告诉后面的函数将PLLCLK用作系统时钟RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;//AHB时钟(HCLK)的分频值RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;//配置RCC_CFGR寄存器bit10:8(PPRE1[2:0]),APB1时钟(PCLK1)的分频值RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;//配置RCC_CFGR寄存器bit13:11(PPRE2[2:0]),APB2时钟(PCLK2)的分频值//APB2外设:HRTIM,TIM1,TIM8,TIM15,TIM16,TIM17,TIM20,SPI1,SPI4,USART1,SAI1,SYSCFG/COMP/OPAMP/VREFBUFif (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_4) != HAL_OK){//配置HCLK,SYSCLK,PCLK1,PCLK2时钟//HCLK为170MHz,PCLK1时钟为170MHz,PCLK2时钟为170MHzError_Handler();}SystemCoreClockUpdate();//更新SystemCoreClock的值
}

5、main.c程序

#include "main.h"
//#include "cmsis_os.h"
#include "stdio.h"  //getchar(),putchar(),scanf(),printf(),puts(),gets(),sprintf()
#include "sys.h"
#include "Clock_Config.h"
#include "Key.h"
#include "LED.h"
#include "delay.h"//STM32G474输入输出测试程序
int main(void)
{STACK_Init();HAL_Init();//复位所有的外设//初始化FLASH接口//将SysTick定时器配置1ms中断SystemClock_Config();//Configure the system clockdelay_init();delay_ms(1000);Key_Init();LED_Init();//配置PC13为输出,无上拉或下拉,输出速度为5MHzwhile (1){if( Key_LevelValue()==0 )//如果按钮一直被按下,则灯会闪烁{LED1_Toggle(); //LED1引脚输出电平翻转delay_ms(500);}}
}//函数功能:在发生错误时,将执行此函数。
void Error_Handler(void)
{__disable_irq();while (1){printf("Error\r\n");}
}

6、测试结果

当一直按下PB15时,绿色LED灯会不停地闪烁。

 

STM32G474最小系统板,BOOT0需要10K/15K电阻到GND,保证程序从FLASH启动。商家的开发问题还是有的。

这篇关于STM32G474按钮输入和点灯的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1090917

相关文章

【测试】输入正确用户名和密码,点击登录没有响应的可能性原因

目录 一、前端问题 1. 界面交互问题 2. 输入数据校验问题 二、网络问题 1. 网络连接中断 2. 代理设置问题 三、后端问题 1. 服务器故障 2. 数据库问题 3. 权限问题: 四、其他问题 1. 缓存问题 2. 第三方服务问题 3. 配置问题 一、前端问题 1. 界面交互问题 登录按钮的点击事件未正确绑定,导致点击后无法触发登录操作。 页面可能存在

C# 防止按钮botton重复“点击”的方法

在使用C#的按钮控件的时候,经常我们想如果出现了多次点击的时候只让其在执行的时候只响应一次。这个时候很多人可能会想到使用Enable=false, 但是实际情况是还是会被多次触发,因为C#采用的是消息队列机制,这个时候我们只需要在Enable = true 之前加一句 Application.DoEvents();就能达到防止重复点击的问题。 private void btnGenerateSh

解决Office Word不能切换中文输入

我们在使用WORD的时可能会经常碰到WORD中无法输入中文的情况。因为,虽然我们安装了搜狗输入法,但是到我们在WORD中使用搜狗的输入法的切换中英文的按键的时候会发现根本没有效果,无法将输入法切换成中文的。下面我就介绍一下如何在WORD中把搜狗输入法切换到中文。

当你输入一个网址后都发生什么

原文:http://igoro.com/archive/what-really-happens-when-you-navigate-to-a-url/  作为一个软件开发者,你一定会对网络应用如何工作有一个完整的层次化的认知,同样这里也包括这些应用所用到的技术:像浏览器,HTTP,HTML,网络服务器,需求处理等等。 本文将更深入的研究当你输入一个网址的时候,后台到底发生了一件件什么样的事~

PNG透明背景按钮的实现(MFC)

问题描述: 当前要在对话框上添加一个以两个PNG图片作为背景的按钮,PNG图的背景是透明的,按钮也要做出相同的透明效果。并且鼠标不在按钮上时,按钮显示"bg1.png";鼠标移动到按钮上时,按钮显示"bg2.png" 开发环境为VS2010。 解决办法: 使用GDI+库装载PNG图片,并使用MFC Button Control和CMFCButton类结合,调用CMFCButton

在 Qt Creator 中,输入 /** 并按下Enter可以自动生成 Doxygen 风格的注释

在 Qt Creator 中,当你输入 /** 时,确实会自动补全标准的 Doxygen 风格注释。这是因为 Qt Creator 支持 Doxygen 以及类似的文档注释风格,并且提供了代码自动补全功能。 以下是如何在 Qt Creator 中使用和显示这些注释标记的步骤: 1. 自动补全 Doxygen 风格注释 在 Qt Creator 中,你可以这样操作: 在你的代码中,将光标放在

龙芯+FreeRTOS+LVGL实战笔记(新)——05部署主按钮

本专栏是笔者另一个专栏《龙芯+RT-Thread+LVGL实战笔记》的姊妹篇,主要的区别在于实时操作系统的不同,章节的安排和任务的推进保持一致,并对源码做了改进和优化,各位可以先到本人主页下去浏览另一专栏的博客列表(目前已撰写36篇,图1所示),再决定是否订阅。此外,也可以前往本人在B站的视频合集(图2所示)观看所有演示视频,合集首个视频链接为: 借助RT-Thread和LVGL

致远个性化之--发起流程页面,去掉【查看流程】按钮

需求 近期在做的项目中,遇到一个需求,想把发起流程页面中的【查看流程】按钮去掉,只让员工预测流程,知道自己的事项流程走向,不让看全局流程图。包含PC端和移动端,以及微协同端。 如下图效果示例: 实现 此需求,只能通过修改页面代码实现。在此不分析实现过程,现把具体实现方式呈现如下,各位如有需求可参照设置。适用版本V9.0,其他版本未进行测试,估计不会有大的差别! PC端 找到文件

【Markdown】输入空格方式

文章目录 1.nbsp2. ensp3. emsp4.thinsp5. zwnj6. zwj7. 其它 1.nbsp &nbsp;为“不换行空格”,全称“No-Break Space”,它是最常见和我们使用最多的空格,大多数的人可能只接触了 ,它是按下space键产生的空格。在HTML中,如果你用空格键产生此空格,空格是不会累加的(只算1个)。要使用html实体表示才可累加,该

如何在Excel中创建一个VBA宏,并设置一个按钮来执行这个宏

下面是一个详细的步骤指南 步骤1:创建VBA宏 1. 打开Excel并按 `Alt + F11` 打开VBA编辑器。 2. 在VBA编辑器中,选择 `Insert` > `Module` 来插入一个新的模块。 3. 将以下代码粘贴到模块中: ```vba Sub CreateNewSheet()' 声明一个工作表对象Dim newSheet As Worksheet' 添加一个新的工作表S