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启动。商家的开发问题还是有的。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/407327.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

深度理解指针(2)

hello各位小伙伴们&#xff0c;关于指针的了解我们断更了好久了&#xff0c;接下来这几天我会带领大家继续我们指针的学习。 目录 数组名的理解 使用指针访问一维数组 一维数组传参的本质 二级指针 指针数组 使用指针数组来模仿二维数组 数组名的理解 我们首先来看一段…

【开源社区】Elasticsearch(ES)中 exists 查询空值字段的坑

文章目录 1、概述2、使用 null_value 处理空值3、使用 exists 函数查询值为空的文档3.1 使用场景3.2 ES 中常见的空值查询方式3.3 常见误区3.4 使用 bool 查询函数查询空值字段3.5 exists 函数详解3.5.1 bool 查询的不足3.5.3 exists 的基本使用 3.6 完美方案 1、概述 本文主要…

单例模式 详解

单例模式 简介: 让类只初始化一次, 然后不同的地方都能获取到同一个实例 这是非常常用的一种模式, 系统稍微大一点基本上都会用到. 在系统中, 不同模块的总管理类都已单例模式居多 这里我们不仅使用c实现单例模式, 也会用python2实现一遍 python代码 想要看更详细的python单…

手动下载Sentinel-1卫星精密轨道数据

轨道信息对于InSAR&#xff08;干涉合成孔径雷达&#xff09;数据处理至关重要&#xff0c;因为它影响从初始图像配准到最终形变图像生成的整个过程。不准确的轨道信息会导致基线误差&#xff0c;这些误差会以残差条纹的形式出现在干涉图中。为了消除由轨道误差引起的系统性误差…

Swift 6.0 如何更优雅的抛出和处理特定类型的错误

概述 从 Swift 语言诞生那天儿起&#xff0c;它就不厌其烦一遍又一遍地向秃头码农们诉说着自己的类型安全和高雅品味。 不过遗憾的是&#xff0c;作为 Swift 语言中错误处理这最为重要的一环却时常让小伙伴们不得要领、满腹狐疑。 在本篇博文中&#xff0c;您将学到如下内容&…

基于网格尺度的上海市人口分布空间聚集特征分析与冷热点识别

在上篇文章提到了同一研究空间在不同尺度下的观察可能会带来不同的见解和发现&#xff0c;这次我们把尺度缩放到网格&#xff0c;来看网格尺度下的空间自相关性、高/低聚类&#xff0c;这些&#xff0c;因为尺度缩放到网格尺度了&#xff0c;全国这个行政区范围就显的太大了&am…

基于Shader实现的UGUI描边解决方案遇到的bug

原文链接&#xff1a;https://www.cnblogs.com/GuyaWeiren/p/9665106.html 使用这边文章介绍的描边解决方案时遇到了一些问题&#xff0c;就是文字的描边经常会变粗&#xff0c;虽然有的时候也可以正常显示描边&#xff0c;但是运行一会儿描边就不正常了&#xff0c;而且不正常…

UDP+TCP

一、UDP协议 1.recvfrom:recvform(int sockfd,void *buf,size_t len,int flags,struct sockaddr *src_addr,socklen_t *addrlen); 参数&#xff1a;socket的fd; 保存数据的空间地址 &#xff1b; 空间大小&#xff1b; 默认接收方式&#xff08;默认阻塞&#xf…

【案例56】安全设备导致请求被拦截

问题现象 访问相关报表 第二次访问发现有相关的连接问题 问题分析 服务器访问相关节点&#xff0c;发现相关节点无此问题。从客户的客户端访问缺有问题。在nclog中发现如下日志&#xff0c;链接被重置。 直接访问服务器无丢包现象。客户端未开防火墙。装了杀毒软件已经卸载。…

简单记录:两台服务器如何超快速互传文件/文件夹

在服务器间传输文件和文件夹是一个常见的任务&#xff0c;尤其是在需要同步数据或进行备份时。以下是使用 scp 命令在两台服务器之间进行文件传输的基本步骤。 服务器A 至 服务器B&#xff1a;文件传输指南 前提条件 确保服务器A和服务器B之间网络互通。确认您有权限访问目标…

C语言 之 整数在内存中的存储、大小端字节序和字节序的判断

文章目录 整数在内存中的存储大小端字节序和字节序判断大小端有大小端的原因高位和地位怎么区分&#xff1f;图例判断机器大端还是小端的例题 整数在内存中的存储 整数的2进制表示方法有三种&#xff0c;即 原码、反码和补码 三种表示方法均有符号位和数值位两部分&#xff0c…

微信小程序获取当前位置并自定义浮窗

1、在腾讯地图api申请key&#xff08;添加微信小程序的appid&#xff09;。 每个Key每日可以免费使用100次&#xff0c;超过次数后会导致地图不显示。可以多申请几个Key解决。WebService API | 腾讯位置服务腾讯地图开放平台为各类应用厂商和开发者提供基于腾讯地图的地理位置…

当AI成为你的私人医生,与AI“医”路同行的奇妙体验

“ 从挂号到诊疗&#xff0c;再到后续的健康管理&#xff0c;人工智能&#xff08;AI&#xff09;正以一种全新的方式融入我们的生活。上海市第一人民医院的创新实践&#xff0c;便是这一变革的生动注脚。 ” AI就医助理&#xff1a;从“助手”到“伙伴” 当你踏入医院大门…

猜数3次-python

题目要求&#xff1a; 定一个数字&#xff08;1-10&#xff0c;随机产生&#xff0c;通过3次判断来猜出数字&#xff09; 数字随机产生&#xff0c;范围1-10有三次机会猜测数字&#xff0c;通过3层嵌套判断实现每次猜不中会提示大了或者小了 ps&#xff1a;补充随机函数 imp…

Spring源码解析(34)之Spring事务回滚流程

一、前言 在上一个篇章我们主要介绍了Spring事务的运行流程&#xff0c;也带着一步步debug看了整个事务的运行流程&#xff0c;但是还是欠缺了Spring事务的回滚的流程。 在上篇也主要介绍了Spring事务的传播特性&#xff0c;这里还是要看一下Spring事务的传播特性&#xff0c;因…

定制开发AI智能名片商城小程序:重塑品牌曝光的创新推手

摘要&#xff1a;随着移动互联网技术的飞速发展&#xff0c;小程序作为一种轻量级应用形态&#xff0c;正逐步成为企业品牌传播与商业变现的重要渠道。本文将探讨在品牌定位中&#xff0c;如何将“定制开发AI智能名片商城小程序”作为品牌曝光的核心推手&#xff0c;通过强化品…

力扣 | 最长公共子序列 | 动态规划 | 最长公共子序列长度、最长公共子序列

文章目录 一、1143. 最长公共子序列二、求最长公共子序列三、变式一、1035. 不相交的线二、1312. 让字符串成为回文串的最少插入次数 一、1143. 最长公共子序列 LeetCode&#xff1a;1143. 最长公共子序列 这是一道典型的二维动态规划问题&#xff0c;甚至面试都能被面到。 这…

c++ | 模板进阶

前言 本篇博客讲解c中的模板的一些其他知识 &#x1f493; 个人主页&#xff1a;普通young man-CSDN博客 ⏩ 文章专栏&#xff1a;C_普通young man的博客-CSDN博客 ⏩ 本人giee: 普通小青年 (pu-tong-young-man) - Gitee.com 若有问题 评论区见&#x1f4dd; &#x1f389;欢…

推荐一个国内Midjourney镜像站,限时充值享5折优惠 结尾附实测图片

作为一名绘画爱好者&#xff0c;你是否曾梦想过将脑海中的画面转化为现实&#xff1f;现在&#xff0c;有了群嘉智创平台&#xff08;ai.qunzjia.cn&#xff09;&#xff0c;这一切都将成为可能。群嘉智创是国内领先的AI对话与Midjourney绘画服务平台&#xff0c;通过接入国内多…

[Meachines] [Easy] Legacy nmap 漏洞扫描脚本深度发现+MS08-067

信息收集 IP AddressOpening Ports10.10.10.4TCP:135,139,445 $ nmap -p- 10.10.10.4 --min-rate 1000 -sC -sV -Pn PORT STATE SERVICE VERSION 135/tcp open msrpc Microsoft Windows RPC 139/tcp open netbios-ssn Microsoft Windows n…