STM32G474按钮输入和点灯

news2024/12/30 3:39:05

在获取到工程模板后,学习某个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 voltage

  RCC_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的值为2
  RCC_OscInitStruct.PLL.PLLN = 85;
	//RCC_PLLCFGR寄存器bit14:8(PLLN[3:0]),PLLN[6:0]=0x55,PLLN为的值为85
  RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
	//RCC_PLLCFGR寄存器bit17(PLLP),PLLP=1,PLLP的分频值为17
  RCC_OscInitStruct.PLL.PLLQ = RCC_PLLQ_DIV2;
	//RCC_PLLCFGR寄存器bit22:21(PLLQ[1:0]),PLLQ[1:0]=01,PLLQ的分频值为2
  RCC_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/VREFBUF
  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_4) != HAL_OK)
  {//配置HCLK,SYSCLK,PCLK1,PCLK2时钟
		//HCLK为170MHz,PCLK1时钟为170MHz,PCLK2时钟为170MHz
    Error_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 clock

	delay_init();
	delay_ms(1000);

  Key_Init();
  LED_Init();//配置PC13为输出,无上拉或下拉,输出速度为5MHz

  while (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.coloradmin.cn/o/2054660.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Redis7基础篇(四)

Redis管道 引入 set k1 v1.......需要往返三次 这是一个比较消耗性能的一件事情 怎么就可以一次性的将这些命令执行 就是使用mset这个方法 这个mset就相当于一个管道 把这些命令做成一个流水线的形式进行处理 解决思路 案例 两个set类型的三个哈希类型的一个list类型的 我们要…

知乎信息流广告效果如何?与其他信息流广告平台有何区别?

广告的有效触达与高效转化成为了品牌营销的核心挑战&#xff0c;知乎作为国内最大的知识分享平台&#xff0c;其信息流广告以其独特的优势脱颖而出&#xff0c;成为众多企业首选的营销工具&#xff0c;云衔科技助力企业实现高效知乎广告投放与代运营服务。 一、知乎信息流广告…

基于STM32+手机APP设计的智能停车场系统——程序源码原理图设计原理设计文档演示视频框图等(文末工程资料下载)

基于STM32手机APP设计的智能停车场系统 演示视频 基于STM32手机APP设计的智能停车场系统 元器件&#xff1a;DHT11、MQ2、STM32F103C8T6、SG90舵机、RC522频射模块、HC-SR04超声波模块、OLED、wifi模块、LED灯、蜂鸣器 功能简介 1、进出停车场时需要刷卡&#xff0c;进行一个…

深度学习-----------------------含并行连结的网络GoogLeNet

目录 含并行连结的网络GoogLeNet最好的卷积层超参数inception块inception 结构inception原始结构inception 降维11卷积核的降维功能GoogLeNet段1&2段3段4&5 Inception 的各种变种Inception V3块&#xff0c;段3Inception V3块&#xff0c;段4Inception V3块&#xff0…

突破FPGA限制:TS-M4i系列数字化仪利用GPU加速实现高效块平均处理

一、应用背景 块或分段内存平均模式常用于在不同应用当中&#xff0c;移除信号中不相干的噪声。不管是哪家的数字化仪制造商&#xff0c;几乎所有基于FPGA实现的块平均模式都会受到块或者段内存大小的限。该限制一般取决于FPGA的容量&#xff0c;最大样品量通常在32k到500k之间…

RS232(旧协议)与RS485(新协议)

RS232: RS485: RS485和RS232是两种常见的串行通信标准&#xff0c;它们在通信距离、速度、拓扑结构等方面存在显著差异。以下是它们的主要区别&#xff1a; 1. 物理层接口 RS232: 使用单端信号传输&#xff0c;即信号通过一根信号线和一根公共地线&#xff08;GND&#xff09…

外呼触发通知发送闪信(mod_cti基于FreeSWITCH)

文章目录 前言联系我们手动外呼配置方法例子一&#xff1a;接收到180或183时触发闪信发送例子二&#xff1a;挂断后触发闪信发送 自动外呼配置方法例子&#xff1a;接收到180或183时触发闪信发送 前言 在呼叫中心中间件中&#xff0c;自动外呼触发闪信发送&#xff0c;我们可以…

电销机器人引领电销变革

以前电销都是都是通过盲打&#xff0c;现在有了电话机器人的出现&#xff0c;为电销公司带来新的篇章。 我们都知道外呼中心的人员离职率始终居高不下&#xff0c;人员的培训频繁成本很高&#xff0c;外部电话水平参差不齐&#xff0c;服务态度不够稳定等问题&#xff0c;都是难…

【硬件模块】震动传感器模块

震动传感器模块实物图 DO&#xff1a;数字信号量输出&#xff0c;接单片机管脚&#xff1b; AO&#xff1a;模拟输出&#xff0c;无效&#xff0c;一般不接。 无震动&#xff0c;DO输出高电平&#xff0c;信号指示灯灭&#xff1b; 有震动&#xff0c;DO输出低电平&#xff0c;…

50道深度NLP和人工智能领域面试题+答案

编者按&#xff1a;分享一个很硬核的免费人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c; 可以当故事来看&#xff0c;轻松学习。 什么是自然语言处理&#xff08;NLP&#xff09;&#xff1f;自然语言处理是一种人工智能领域&#xff0c;致力于使计算机…

letcode 分类练习 BST 530.二叉搜索树的最小绝对差 501.二叉搜索树中的众数 236. 二叉树的最近公共祖先(自底向上的典型例子)

letcode 分类练习 BST 530.二叉搜索树的最小绝对差 501.二叉搜索树中的众数 236. 二叉树的最近公共祖先 BST530.二叉搜索树的最小绝对差501.二叉搜索树中的众数236. 二叉树的最近公共祖先 BST 重要性质&#xff1a;它的中序遍历是一个有序数组 530.二叉搜索树的最小绝对差 BS…

linux 远程访问及控制 (SSH)

目录 一、SSH远程管理 1.1 配置OpenSSH服务端 1.1.1 SSH协议介绍 1.1.2 服务监听选项 1.1.3 用户登录控制 1.1.4 登录验证方式 1.2 使用SSH客户端程序 1.3 密钥对验证的SSH体系 二、TCP Wrapppers访问控制 2.1 TCP Wrappers概述 2.1.1 TCP Wrappers简介 2.1.2 TCP…

会声会影2023安装好后运行显示乱码的解决方法

会声会影2019安装好了之后&#xff0c;打开软件之后&#xff0c;会有个乱码弹窗错误&#xff0c;其实这个乱码提示只有简体中文版本上才会是乱码&#xff0c; 英文版上显示的是″You do not appear to be a register user. Please re-install the application or call custome…

如何像演示PPT幻灯片一样演示PDF文件 - PDF幻灯片使用说明

PDF幻灯片是一款Windows平台下可以让您像演示PPT幻灯片一样全屏演示PDF文件的放映工具软件。 在我们日常工作中&#xff0c;许多幻灯片文件被转换成了PDF格式。这些由幻灯片生成的PDF文件只能被打开查看内容&#xff0c;但是却不能像原始PPT或PPTX文件一样直接用PowerPoint等软…

常量池梳理

参考资料&#xff1a; 参考视频 参考demo 参考博客 说明&#xff1a; 详情见参考demo的文件夹&#xff1a;

JS逆向高阶补充

文章目录 JS逆向高阶补充eval函数Hook函数案例1: Hook eval案例2: Hook JSON.stringify案例3: Hook JSON.parse案例4: Hook Cookie Promise对象&#xff08;1&#xff09;回调函数&#xff08;2&#xff09;基本语法&#xff08;3&#xff09;then函数&#xff08;4&#xff09…

wireShark tcpdump 抓包 ,检测dns

开两个窗口执行 1窗口。tcpdump -i any port 53 -w clirent.pcap2窗口。nslookup ip 过滤目标ip or 域名 统计域名DNS 将 生成的 clirent.pcap使用wireshark 分析 1.queryType : A ipv4 AAAAipv6

[word] 复杂文本如何仅全选word中的表格 (简单跟做即可)

问题描述 在word文档中&#xff0c;有各种形式的文本&#xff0c;有纯文本&#xff0c;有表格&#xff0c;有图片或者更多其它形式参杂在一起&#xff0c;本篇记录解决如何只全选中文档中的所有表格形式的部分&#xff0c;从而方便对表格进行批量修改和操作 环境说明 word版…

【系统架构设计】开发方法(二)

【系统架构设计】开发方法&#xff08;二&#xff09; 软件生命周期软件开发模型统一过程敏捷方法极限编程特征驱动开发Scrum水晶方法开放式源码ASD 软件重用基于架构的软件设计形式化方法 软件生命周期 软件开发模型 统一过程 敏捷方法 所谓敏捷开发&#xff0c;个人认为&…

day01- Web开发介绍-HTML-CS

Web开发介绍 1 什么是web开发 Web&#xff1a;全球广域网&#xff0c;也称为万维网(www World Wide Web)&#xff0c;能够通过浏览器访问的网站。 所以Web开发说白了&#xff0c;就是开发网站的&#xff0c;例如下图所示的网站&#xff1a;淘宝&#xff0c;京东等等 那么我们…