STM32寄存器&HAL库方式的LED程序

本文详细介绍使用STM32F103系列芯片控制LED灯的原理与实践,包括寄存器映射、GPIO端口初始化及编程实现,提供C语言代码示例,并介绍如何利用STM32CubeMX和Keil进行项目开发。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

一、原理学习。学习和理解STM32F103系列芯片的地址映射和寄存器映射原理;了解GPIO端口的初始化设置三步骤(时钟配置、输入输出模式设置、最大速率设置)。

1.什么是寄存器

2.STM32F103系列芯片的地址映射和寄存器映射原理

3.了解GPIO端口的初始化设置三步骤(时钟配置、输入输出模式设置、最大速率设置)。

二、假设你手中已有 STM32最小系统核心板(STM32F103C8T6)+面板板+3只红绿蓝LED,并搭建了电路,分别GPIOA-5、GPIOB-9、GPIOC-14 这3个引脚上控制LED灯(最高时钟2Mhz),轮流闪烁,间隔时长1秒。

GPIO端口初始化设置:

 输入输出模式和输出速率设置

①C语言实现流水灯

三、安装 stm32CubeMX,用cubemx完成初始化过程,采用HAL库编程实现。

5.keil仿真调试

四、在Keil下用软件仿真运行上面代码,并用虚拟逻辑分析仪观察 对应管脚上的输出波形(高低电平转换),看是否是1秒的周期。


一、原理学习。学习和理解STM32F103系列芯片的地址映射和寄存器映射原理;了解GPIO端口的初始化设置三步骤(时钟配置、输入输出模式设置、最大速率设置)。

1.什么是寄存器

寄存器的功能是存储二进制代码,它是由具有存储功能的触发器组合起来构成的。一个触发器可以存储1位二进制代码,故存放n位二进制代码的寄存器,需用n个触发器来构成。 [1] 

按照功能的不同,可将寄存器分为基本寄存器和移位寄存器两大类。基本寄存器只能并行送入数据,也只能并行输出。移位寄存器中的数据可以在移位脉冲作用下依次逐位右移或左移,数据既可以并行输入、并行输出,也可以串行输入、串行输出,还可以并行输入、串行输出,或串行输入、并行输出,十分灵活,用途也很广(百度百科)

我的理解:我觉得cpu是厨师,那么寄存器就像个冰箱一样,cpu要完成某项操作,就要取出寄存器里面的命令来进行操作

2.STM32F103系列芯片的地址映射和寄存器映射原理

根据每个单元功能的不同,以功能为名给这个内存单元取一个别名,这个别名就是我们经常说的寄存器,这个给已经分配好地址的有特定功能的内存单元取别名的过程就叫寄存器映射。

3.了解GPIO端口的初始化设置三步骤(时钟配置、输入输出模式设置、最大速率设置)。

GPIO工作原理:

 输入输出模式设置:

上拉电阻:把不确定的信号通过电阻连接到高电平信号初始化为高电平

下拉电阻:把不确定的信号通过电阻连接到低电平信号初始化为低电平

上拉输入:会经过上拉电阻,从而初始化成高电平,通过ttl施密特触发器(将模拟信号转变为数字信号)数字信号单片机可识别,从而单片机可以开始读

下拉输入:会经过下拉电阻,从而初始化成低电平,通过ttl施密特触发器(将模拟信号转变为数字信号)数字信号单片机可识别,从而单片机可以开始读

浮空输入:引脚不接高低电平,引脚浮空,他可以直接通过ttl施密特触发器,所以它的电压是不确定的(通常用于iic,usart)

模拟输入:不经过上拉电阻和下拉电阻,也不通过施密特触发器,直接到外设模块模拟输入,用于ad转换,用于 ADC

开漏输出:可以输出高电平和低电平,但是如果需要得到高电平需要上拉电阻才行,通过输出数据寄存器到输出控制电路,经过mos管才到gpio口

开漏复用输出:是用复用功能进行输出,通过输出数据寄存器到输出控制电路,经过mos管才到gpio口,一般用于(发送,接收,信号,使动)(TX1,  MOSI,  MISO,SCK,SS)

推挽输出:可以输出高电平和低电平,通过输出数据寄存器到输出控制电路,经过mos管才到gpio口

推挽复用输出:可以输出高电平和低电平,通过输出数据寄存器到输出控制电路,经过mos管才到gpio口 ,可以用于(iic的sda,scl)

(1)GPIO初始化步骤:
第一步:使能GPIOx口的时钟
第二步:指明GPIOx口的哪一位,这一位的速度大小以及模式
第三步:调用GPIOx初始化函数进行初始化
第四步:调用GPIO-SetBits函数,进行相应位的置位

对单个GPIO口的初始化:

GPIO_InitTypeDef GPIO_InitStructure;
第一步:使能GPIOA的时钟:
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);

第二步:设置GPIOA参数:输出OR输入,工作模式,端口翻转速率
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_6| GPIO_Pin_7| GPIO_Pin_8; //设定要操作的管脚
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //设置为推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; // IO口速度为50MHz

第三步:调用GPIOA口初始化函数,进行初始化。
GPIO_Init(GPIOA, &GPIO_InitStructure); //根据设定参数初始化GPIOA

第四步:调用GPIO-SetBits函数,进行相应为的置位。
GPIO_SetBits(GPIOA,GPIO_Pin_0); //输出高

对于多个GPIO口的初始化如下:

GPIO_InitTypeDef GPIO_InitStructure;
第一步:使能GPIOA,GPIOE的时钟:
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE, ENABLE);

第二步:设置GPIOA,GPIOE参数:输出OR输入,工作模式,端口翻转速率
第三步:调用GPIOA口初始化函数,进行初始化。
第四步:调用GPIO-SetBits函数,进行相应为的置位。

把第二、三、四步合并分别设置GPIOA和GPIOE
先设置GPIOA
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4; // 第四个口,PA4
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //设置为推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; // IO口速度为50MHz
GPIO_Init(GPIOA,&GPIO-InitST); //根据设定参数初始化GPIOA
GPIO_SetBits(GPIOA,GPIO_Pin_4); //输出高

再设置GPIOE
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3; // 第三个口,PE3
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //设置为推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; // IO口速度为50MHz
GPIO_Init(GPIOE,&GPIO-InitST); //根据设定参数初始化GPIOE
GPIO_SetBits(GPIOE,GPIO_Pin_3); //输出高

二、假设你手中已有 STM32最小系统核心板(STM32F103C8T6)+面板板+3只红绿蓝LED,并搭建了电路,分别GPIOA-5、GPIOB-9、GPIOC-14 这3个引脚上控制LED灯(最高时钟2Mhz),轮流闪烁,间隔时长1秒。

存储器映射:


LED灯宏设置:

#define GPIOC_BASE (APB2PERIPH_BASE + 0x1000)
#define APB2PERIPH_BASE (PERIPH_BASE + 0x10000)
#define PERIPH_BASE ((uint32_t)0x40000000)

 寄存器映射:

给已分配好地址(通过存储器映射实现)的有特定功能的内存单元取别名的过程就叫寄存器映射。

GPIO端口初始化设置:

1.时钟配置

找到时钟使能寄存器映射基地址

时钟控制名字叫做RCC,属于AHB总线

 GPIOA、GPIOB、GPIOC三个端口都属于APB2总线

 2.找到端口偏移地址以及对应端口所在位置

 3.使能对应端口时钟

//----------------APB2使能时钟寄存器 ---------------------
#define RCC_APB2ENR		*((unsigned volatile int*)0x40021018)

	RCC_APB2ENR|=1<<2|1<<3|1<<4;			//APB2-GPIOA、GPIOB、GPIOC外设时钟使能	

 输入输出模式和输出速率设置

本次实验采用通用推挽输出模式,最高输出时钟频率2Mhz。分别用到A4、B5、C14三个引脚。其中A4、B5属于端口配置低寄存器偏移地址为0x00,C13属于端口配置高寄存器偏移地址为0x04。

配置对应引脚寄存器,基地址+偏移量
设置推挽输出并设置最大速度为2Mhz

//----------------GPIOA配置寄存器 -----------------------
#define GPIOA_CRL		*((unsigned volatile int*)0x40010800)
//----------------GPIOB配置寄存器 -----------------------
#define GPIOB_CRL		*((unsigned volatile int*)0x40010C00)
//----------------GPIOC配置寄存器 -----------------------
#define GPIOC_CRH		*((unsigned volatile int*)0x40011004)

	GPIOA_CRL&=0xFFF0FFFF;		//设置位 清零	
	GPIOA_CRL|=0x00020000;		//PA4推挽输出,把第19、18、17、16位变为0010
	
	GPIOB_CRL&=0xFF0FFFFF;		//设置位 清零	
	GPIOB_CRL|=0x00200000;		//PB5推挽输出,把第23、22、21、20变为0010
	 
	GPIOC_CRH&=0xFF0FFFFF;		//设置位 清零	
	GPIOC_CRH|=0x00200000;		//PC14推挽输出,把第23、22、21、20变为0010

①C语言实现流水灯

#include "stm32f10x.h"
//----------------APB2使能时钟寄存器 ---------------------
#define RCC_APB2ENR		*((unsigned volatile int*)0x40021018)
//----------------GPIOA配置寄存器 -----------------------
#define GPIOA_CRL		*((unsigned volatile int*)0x40010800)
#define	GPIOA_ODR		*((unsigned volatile int*)0x4001080C)
//----------------GPIOB配置寄存器 -----------------------
#define GPIOB_CRL		*((unsigned volatile int*)0x40010C00)
#define	GPIOB_ODR		*((unsigned volatile int*)0x40010C0C)
//----------------GPIOC配置寄存器 -----------------------
#define GPIOC_CRH		*((unsigned volatile int*)0x40011004)
#define	GPIOC_ODR		*((unsigned volatile int*)0x4001100C)


//延时函数
 void Delay()
 {
   u32 i=0;
   for(;i<5000000;i++);
 }
 int main(void)
 {	
	RCC_APB2ENR|=1<<2|1<<3|1<<4;			//APB2-GPIOA、GPIOB、GPIOC外设时钟使能	
	
	GPIOA_CRL&=0xFFF0FFFF;		//设置位 清零	
	GPIOA_CRL|=0x00020000;		//PB5推挽输出
	GPIOA_ODR&=~(1<<4);			//设置初始灯为灭
	
	GPIOB_CRL&=0xFF0FFFFF;		//设置位 清零	
	GPIOB_CRL|=0x00200000;		//PB5推挽输出
	GPIOB_ODR&=~(1<<5);			//设置初始灯为灭
	 
	GPIOC_CRH&=0xF0FFFFFF;		//设置位 清零	
	GPIOC_CRH|=0x02000000;		//PB5推挽输出
	GPIOC_ODR&=~(1<<14);			//设置初始灯为灭		
	 

	 

	while(1){
		//A灯
		GPIOA_ODR|=1<<4;		//PB5高电平
	 	Delay();
		GPIOA_ODR&=~(1<<4);		//PB5低电平,因为是置0,所以用按位与


		
		//B灯
		GPIOB_ODR|=1<<5;		//PB5高电平
	 	Delay();
		GPIOB_ODR&=~(1<<5);		//PB5低电平,因为是置0,所以用按位与


		
		
		//C灯
		GPIOC_ODR|=1<<14;		//PB5高电平
	 	Delay();
		GPIOC_ODR&=~(1<<14);		//PB5低电平,因为是置0,所以用按位与


		
		}
}

三、安装 stm32CubeMX,用cubemx完成初始化过程,采用HAL库编程实现。

 1.实验工具:

  • STM32CubeMX
  • KEIL5
  • mcuisp
  • STM32F103C8T6的最小核心板

2.安装stm32CubeMX 

 3.安装HAL库

(1)打开安装好的STMCubeMX

 (2)点击HELP->Manage embedded software packages :

(3)会跳出来一个选择型号界面 勾选上你要安装的HAL库, 点击“Install Now” 直到安装成功

4.新建项目

 (1)回到STMCubeMX的主界面,创建新项目:

 (2)在part name里选择自己的芯片,点击信息栏中的具体芯片信息选中,点击start project:

(3)点击system core,进入SYS,在debug下选择serial wire:

 (4)配置时钟,进入上面的rcc,有两个时钟,一个是hse和lse,我们要用是GPIO接口,而这些接口都在APB2里:

 接下来观察时钟架构,APB2总线的时钟由hse控制,同时在这个界面得把PLLCLK右边选上

(5)将hse那里设为Crystal/Ceramic Resonator:

 (6)接下来就是点击相应的引脚设置输出寄存器了,就是output那一项,一共选了三个,是PA4,PB9,PC15:

 (7)点击project manager,配置好自己的路径和项目名,然后IDE那项改为MDK-ARM:

5.keil仿真调试

(1)打开.uvprojx文件(或者在上一步选择open project)

 打开main.c文件,滑倒主函数那一部分:

main代码:

SystemClock_Config();//系统时钟初始化
  MX_GPIO_Init();//gpio初始化
  while (1)
  {		
		HAL_GPIO_WritePin(GPIOA,GPIO_PIN_4,GPIO_PIN_RESET);//PA4亮灯
		HAL_GPIO_WritePin(GPIOB,GPIO_PIN_9,GPIO_PIN_SET);//PB9熄灯
		HAL_GPIO_WritePin(GPIOC,GPIO_PIN_15,GPIO_PIN_SET);//PC15熄灯
		HAL_Delay(1000);//延时1s
		HAL_GPIO_WritePin(GPIOA,GPIO_PIN_4,GPIO_PIN_SET);//PA4熄灯
		HAL_GPIO_WritePin(GPIOB,GPIO_PIN_9,GPIO_PIN_RESET);//PB9亮灯
		HAL_GPIO_WritePin(GPIOC,GPIO_PIN_15,GPIO_PIN_SET);//PC15熄灯
		HAL_Delay(1000);//延时1s		
		HAL_GPIO_WritePin(GPIOA,GPIO_PIN_4,GPIO_PIN_SET);//PA4熄灯
		HAL_GPIO_WritePin(GPIOB,GPIO_PIN_9,GPIO_PIN_SET);//PB9熄灯
		HAL_GPIO_WritePin(GPIOC,GPIO_PIN_15,GPIO_PIN_RESET);//PC15亮灯
		HAL_Delay(1000);//延时1s
	}

(3)电路连接

根据设计的程序连接电路:
对于USB转TTL模块和stm32f103c8t6连接:
GND — GND
3v3 — 3v3
TXD — A10
RXD — A9

总电路:
红——B9
绿——C15
黄——A4

 (4)烧录运行

四、在Keil下用软件仿真运行上面代码,并用虚拟逻辑分析仪观察 对应管脚上的输出波形(高低电平转换),看是否是1秒的周期。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值