STM32寄存器实现流水灯

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

1.寄存器

寄存器是中央处理器内的组成部分。 寄存器是有限存贮容量的高速存贮部件,它们可用来暂存指令、数据和地址。
简单来说,寄存器就是存放东西的一个空间器物。寄存器可能存放的是指令、数据或地址。
按照功能的不同,可将寄存器分为基本寄存器和移位寄存器两大类。基本寄存器只能并行送入数据,也只能并行输出。移位寄存器中的数据可以在移位脉冲作用下依次逐位右移或左移,数据既可以并行输入、并行输出,也可以串行输入、串行输出,还可以并行输入、串行输出,或串行输入、并行输出,十分灵活,用途也很广。
存放数据的寄存器是最好理解的,如果你需要读取一个数据,直接到这个寄存器所在的地方来问问他,数据是多少就行了。问寄存器这个动作,叫做访问寄存器。不同的数据会存放在不同的寄存器,例如引脚PA2与PB8的高低电平数据(1或0)肯定放在不同的寄存器里,那么怎么区分不同的寄存器呢?通过地址,不同的寄存器有不同的地址,就像老张行李寄存处在101号店铺,老王行李寄存处在258号店铺。
指令、地址寄存器与数据寄存器类似,里边存放的都是0和1,毕竟单片机也只认识机器码,机器码都是0或1,只是特别的规定下,数据寄存器里面存放的0和1表示数据,指令寄存器里存放的表示指令。

2.地址映射和寄存器映射原理

地址映射:由百度词条可知为了保证CPU执行指令时可正确访问存储单元,需将用户程序中的逻辑地址转换为运行时由机器直接寻址的物理地址,这一过程称为地址映射。
寄存器映射:在存储器的区域单元中,每一个单元对应不同的功能,当我们控制这些单元时就可以驱动外设工作。我们可以找到每个单元的起始地址,然后通过 C 语言指针的操作方式来访问这些单元,如果每次都是通过这种地址的方式来访问,不仅不好记忆还容易出错,这时我们可以根据每个单元功能的不同,以功能为名给这个内存单元取一个别名,这个别名就是我们经常说的寄存器,这个给已经分配好地址的有特定功能的内存单元取别名的过程就叫寄存器映射。
请添加图片描述二、GPIO端口初始化

1.时钟配置

本次实验采用GPIOA、B、C三个端口。该三个端口都属于APB2总线

找到时钟使能寄存器映射基地址
找到端口偏移地址以及对应端口所在位置
使能对应端口时钟
大致代码如下:

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

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

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

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

1.找到GPIOx端口基地址
2.配置对应引脚寄存器,基地址+偏移量

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

3.设置输出模式为推挽输出,输出速度为2Mhz

	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

三、代码实现

1.流水灯原理

本次实验采用三个灯实现,亮灯状态用1表示,灭灯状态用0表示。
初始状态为0 0 0,
状态一为1 0 0
状态二为0 1 0
状态三为0 0 1
状态三结束后继续进入状态一,一直循环达到流水灯效果。

2.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<<5);			//设置初始灯为灭
	
	GPIOB_CRL&=0xFF0FFFFF;		//设置位 清零	
	GPIOB_CRL|=0x00200000;		//PB5推挽输出
	GPIOB_ODR&=~(1<<9);			//设置初始灯为灭
	 
	GPIOC_CRH&=0xF0FFFFFF;		//设置位 清零	
	GPIOC_CRH|=0x02000000;		//PB5推挽输出
	GPIOC_ODR&=~(1<<14);			//设置初始灯为灭		
	 

	 

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


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


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


		
		}
}

3.效果展示

在这里插入图片描述

三、STM32CubeMX生成代码使用HAL库点亮流水灯

1.安装STM32CubeMX

在官网直接下载(需要邮箱注册)
安装过程比较简单就不在此过多赘述

2.安装HAL库

1.打开安装好的STMCubeMX并点击HELP->Manage embedded software packages:
请添加图片描述
2.在弹出的界面中找到你需要HAL库,点击install now,到安装成功请添加图片描述3.回到桌面创建新项目
在这里插入图片描述
4.在part name里选择自己的芯片然后点击start project
在这里插入图片描述
3.点击system core,进入SYS,在debug下选择serial wire:
在这里插入图片描述
4.接下来观察时钟架构,APB2总线的时钟由hse控制,同时在这个界面得把PLLCLK右边选上:
在这里插入图片描述5.将hse那里设为Crystal/Ceramic Resonator:
在这里插入图片描述
6.接下来就是点击相应的引脚设置输出寄存器了,就是output那一项,一共选了三个,是PA5,PB9,PC14:
在这里插入图片描述
7.点击project manager,配置好自己的路径和项目名,然后IDE那项改为MDK-ARM:
在这里插入图片描述
8.进入 code generate界面,选择生成初始化.c/.h文件,后面点击generate code,选择open project,然后就到KEIL5了:
在这里插入图片描述

1.弹出界面直接选择opean project,会直接弹出项目文件

2.找到项目main将如下代码替换掉主函数中的代码:

SystemClock_Config();//系统时钟初始化
  MX_GPIO_Init();//gpio初始化
  while (1)
  {		
		HAL_GPIO_WritePin(GPIOA,GPIO_PIN_5,GPIO_PIN_RESET);//PA5亮灯
		HAL_GPIO_WritePin(GPIOB,GPIO_PIN_9,GPIO_PIN_SET);//PB9熄灯
		HAL_GPIO_WritePin(GPIOC,GPIO_PIN_14,GPIO_PIN_SET);//PC14熄灯
		HAL_Delay(1000);//ÑÓʱ1s
		HAL_GPIO_WritePin(GPIOA,GPIO_PIN_5,GPIO_PIN_SET);//PA5熄灯
		HAL_GPIO_WritePin(GPIOB,GPIO_PIN_9,GPIO_PIN_RESET);//PB9亮灯
		HAL_GPIO_WritePin(GPIOC,GPIO_PIN_14,GPIO_PIN_SET);//PC14熄灯
		HAL_Delay(1000);//ÑÓʱ1s		
		HAL_GPIO_WritePin(GPIOA,GPIO_PIN_5,GPIO_PIN_SET);//PA5熄灯
		HAL_GPIO_WritePin(GPIOB,GPIO_PIN_9,GPIO_PIN_SET);//PB9熄灯
		HAL_GPIO_WritePin(GPIOC,GPIO_PIN_14,GPIO_PIN_RESET);//PC14亮灯
		HAL_Delay(1000);//延时1s
	}

在这里插入图片描述

3.电路连接

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

总电路:
绿——B9
黄——C14
红——A5

4.烧录运行

在这里插入图片描述

5.观察GPIO端口的输出波形

1.Target界面中,选择跟正确的晶振大小
在这里插入图片描述
2.degug页面设置
在这里插入图片描述
3.进入degug界面选择逻辑分析仪
在这里插入图片描述
4.选择要观察的引脚
(1)点击Setup Logic Analyzer,添加要观察的引脚
在这里插入图片描述
(2)将grid设置为1s并勾选相关信息
在这里插入图片描述
(3)运行程序并观察波形
在这里插入图片描述

四、总结

通过这次实验学习,充分了解了keil的使用方法和steam32的相关知识,并了解了流水灯的实验

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值