4、stm32F103入门学习--点亮LED(寄存器操作)

写在最前面

通过点亮LED入门,采用两种方式,本节采用寄存器操作,下一节采用库函数操作,寄存器操作主要帮助大家理解stm32底层是怎么实现的,在此基础上再采用库函数操作,虽然以后基本以库函数操作为主,但是理解寄存器操作也非常重要!

启动文件添加

在上一小节中有这么一张图,左侧栏除了“main.c”,还有“startup_stm32f10x_hd.s”。以后随着学习的深入大家会知道很多工作Keil软件给我们完成了,我们只是在进行逻辑编程。那么记住在一段程序前需要一段启动程序,以后讲解这一段启动程序。
在这里插入图片描述
在官方提供的固件库中可以按以下路径找寻启动文件。

F:\STM32F103官方固件库\【固件库】STM32F10x_StdPeriph_Lib_V3.5.0\Libraries\CMSIS\CM3\DeviceSupport\ST\STM32F10x\startup\arm

在下图中可以看到很多启动文件,后缀名都为.s,s是start的意思。怎么选择合适的启动文件呢?

在这里插入图片描述
给大家推荐下学习的资料。首先官方资料,非常详细,基本所有教程都是以此为基础。等会儿会用到“ST选型手册.pdf”。

在这里插入图片描述
野火的教程也不错,截取其中的一个图,可以看到根据FLASH的大小选择启动文件。
在这里插入图片描述查看ST选型手册.pdf,截图如下,看到我的单片机flash为64k,所以选取“startup_stm32f10x_md.s”。
在这里插入图片描述
至于上节为什么选用““startup_stm32f10x_hd.s””也可以,有可能说明选稍大的问题不大。但是尽量根据标准去选。

在没有启动文件的情况下编译可以看到,会出现错误,所以启动文件必不可少!举个例子,比如老师在课堂上课,看起来很简单铃声响了去指定教室上课就行。其实学校做了大量工作包括课程设定、教室安排等工作。所以我们能在Keil写程序是因为Keil前期后期做了大量工作。
在这里插入图片描述
将startup_stm32f10x_md.s放置到main.c同文件夹中。
在这里插入图片描述
打开Keil软件,跟添加main.c方式一样,双击“Source Group 1”,出现如下对话框,并没有看到启动文件,这是因为显示的文件类型都是.c。点击箭头所指。
在这里插入图片描述
选择“All files”,此时可以看到启动文件。添加即可。

在这里插入图片描述
再次编译,编译正常。

在这里插入图片描述
关于程序部分,一部分是熟知的main函数,另一部分是SystemInit函数。关于main函数大家都可以接受,SystemInit函数不可或缺,在以后讲启动文件再具体介绍。现在先默认写着,里面是空函数。

相关寄存器配置介绍

不管是库函数操作还是HAL操作(最近很流行),本质上都是对寄存器的操作。
看下配套开发版的原理图。根据原理图可知PC13为低电平可以点亮LED。那么怎么使PC13为低电平呢?
是否跟51单片机一样在相应的位写0就可以了?并不是,举个例子,比如烧饭,以前大锅柴火烧,烧熟了差不多。现在烧饭基本用电饭煲,不仅可以烧熟,还能根据自己的口味选择还能定时等等。所以说,stm32配置引脚更加复杂,但是更加强大。不仅要配置低电平还要配置是输入还是输出,如果是输出的话还要配置输出速度。接下里具体给大家介绍。
根据原理图可知

在提供的“STM32F10x系列编程手册(中文)”手册中看到GPIO寄存器7种类型。
在这里插入图片描述
首先看下8.2.1端口配置低寄存器,通过该寄存器具体介绍下。
先解释下(GPIOx_CRL)(x=A…E)的意思。stm32f103引脚有多有少,多则144个,少则48个(我用的板子)。所以会把这些引脚分成组,A、B、C、D…每组最多16个引脚,注意,是最多,并不是一定要有16个引脚!
图1下图可以看到,48引脚的单片机只分成了A、B、C、D(PA、PB、PC、PD)组。GPIO英语的全称是General-purpose input/output,翻译过来就是通用的IO口。GPIOA_CRL的意思是控制A口的CRL寄存器。
在这里插入图片描述
再回到上面的CTRL寄存器图,“偏移地址0x00”。那么偏移是相对于谁偏移的,应该有个基准!先给大家举个例子,要盖一幢商务大楼,外面盖完了如果里面是空的,是不行的,所以要盖一层层,一层层盖了也不行,在每一层隔处一个个房间,这样一幢商务大楼才能使用。我们单片机内存也是,整一大块是不能用的,也要隔成一个个房间才能使用,每个房间相当于寄存器,要么有人(相当于为1),要么没人(相当于为0)。所以要查下GPIOC安排在几楼!

在官方提供的手册中(P28)可以看到GPIOC的地址范围是0x40011000~0x400113FF。所以它的起始地址是0x40011000,也就是基地址!偏移地址0x00后还是0x40011000。
在这里插入图片描述再回到CTRL寄存器图,先不讲复位值,先看下面的图。一共有32个位,0~31。也就是CTRL寄存器有32位,这也是为什么叫做stm32的原因,以前的51单片机是8位单片机也就是一次性最多能处理8个位。
看红色框部分(0位3位),CNF0和MODE0。再看4位7位,CNF1和MODE1。说明GPIOC中的第0位需要CNF0和MODE0这4各位来控制,GPIOC中的第1位需要CNF1和MODE1这4各位来控制。具体可以控制哪些呢,在往下看。

在这里插入图片描述以MODE0为例,占了两个位,每个为可以表示0或1,所以可以表示4种情况!一般情况下是输出模式,在下表中的MODEy[1:0]就可以看到①,有输出和输入模式,假设选择“01”表示输出模式,最大速度为10MHZ,再去看CNFy[1:0],根据输入输出的不同有不同的选择,那么我们刚才选的是输出模式,所以看②,选择“00”,具体不展开什么叫通用推完输出模式,有机会再讲。
在这里插入图片描述所以假设GPIOC第0位要输出低电平的话首先要配置这4位,0b00 01。但是我们的引脚是GPIOC13,而
CTRL寄存器图中共32位,4个位一组,只能配置GPIOC0~GPIOC7。所以看CTRH寄存器。
在这里插入图片描述
GPIOC_CRH控制的是GPIOC的第8位~第15位。大家应该看到了GPIOC_CRL和GPIOC_CRH基本一样,一个控制低8位,一个控制高8位。注意下GPIOC_CRH的偏移地址是0x04。
复位值的意思是也就是刚上电时的值,或者按复位键后的值,把0x4444 4444展成2进制,就可以知道,每个引脚的初始状态(0100)为浮空输入模式。

在这里插入图片描述通过以下代码实现通用推挽输出模式,不懂可以留言。

GPIOC_CRH &= ~(0x0F<<(4*5));
GPIOC_CRH |= (1<<(4*5));

再看8.2.3和8.2.4,一个用于配置输入,一个用于配置输出。那么我们看输出。

在这里插入图片描述
因为每个GPIO组只有16个引脚,所以ODR寄存器只用了低16位,高16位保留。
在这里插入图片描述

GPIOC_ODR &= ~(1<<13);//配置输出低电平
GPIOC_ODR |= (1<<13);//配置输出高电平

我们去银行取钱或者存钱都是在窗口排队,可能一个窗口10来号人,就像我们以前学的51单片机。所有的时间基准都是以唯一的晶振为主。但是现在银行推出了VIP服务,也就是你的存款足够多,他会对你进行一对一服务!我们的stm32就是VIP服务,每个引脚使用都需要开启相应的时钟功能!,一定要记住我们是VIP。

在6.3.7小节中可以看到,位4表示开启相应的GPIOC时钟,它的偏移地址是0x18,再找下它的基地址。

在这里插入图片描述
根据上图知道我们要找的是RCC_APB2ENR时钟,从下图可以看到时钟控制的起始地址是0x40021000。那么RCC_APB2ENR的基地址是0x4002 1000,加上偏移地址后是0x4002 1018。

RCC_APB2ENR |=(1<<4);//打开GPIOC时钟

在这里插入图片描述

综上,可以写出main函数的伪代码

int main(void)
{
	RCC_APB2 |=(1<<4);//打开时钟
	GPIOC_CRH &= ~(0x0F<<(4*5));//配置输出模式
    GPIOC_CRH |= (1<<20);
    GPIOC_ODR&=~(1<<13);//配置输出低电平
}

转换成可实用的代码

int main(void)
{
	*(unsigned int*)0x4002 1018 |=(1<<4);//打开时钟
	*(unsigned int*)0x40011004 &= ~(0x0F<<(4*5));//配置输出模式
    *(unsigned int*)0x40011004 |= (1<<20);
    *(unsigned int*)0x4001 100C&=~(1<<13)//配置输出低电平
}

编写完整程序烧录到单片机,看到LED正常点亮。在程序中我们也能看到,一个函数里不一定需要头文件,以前写51程序的时候第一句就是#include<reg52.h>,已形成固定模式,如果了解单片机本质的话就知道为什么不用写了。这节是从最最底层、完全暴力的方式点亮LED,可读性比较差。
在这里插入图片描述
在下下小节中我们把程序进一步完善,因为最终趋向于库函数操作,看看怎么从寄存器操作演变成库函数操作。在下一节中,主要讲C语言知识,因为这节有关一些C语言知识没有展开,以后碰到c语言知识点的话也在下一节补充。

评论 26
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值