STM32-寄存器编程-使用寄存器点亮LED

本文介绍了STM32开发的基础步骤,包括创建工程模板、选择芯片、添加源文件、理解启动文件及寄存器编程。通过实例讲解了如何配置GPIO端口和时钟,实现LED的点亮。同时,提到了固件库编程与寄存器编程的相似性,并提供了STM32外设和时钟配置的相关资源。

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

一、工程文件的建立

1、我们建立一个”工程模板“文件夹,在它下面在新建4个文件夹

Listing存放编译器编译适合产生的C/汇编/链接的列表信息
Project存放工程
Output存放编译产生的调用信息、hex文件、预览信息、封装库等
User存放用户编写的驱动文件

2、打开keil5点击Project新建一个工程放到我们刚建的”工程模板“文件夹中的Project中命名按喜好来就行,这里建议使用英文。

3、 在弹出的界面中我们选中F1系列中103中的任意一款芯片,这里我选的STM31F103R6,因为我们用的Proteus仿真中有这款芯片,等下可以仿真。

4、我们在Project视图栏里对Source Group 1 右击我们的鼠标Add New一个c文件名字随意就好这里建议英文。

 5、我们到keil5的根目录下找到此路径下的启动文件夹这里看你安装在哪里了

 我这里就不详细介绍这些启动文件了这里给张表想要更深的了解这些东西关注我后面我会更新STM32启动文件详解。

启动文件区别
startup_stm32f10x_ld.sld:low-density 小容量,Flash容量为16 ~ 32K
startup_stm32f10x_md.smd:medium-density中容量,Flash容量为64 ~ 128K
startup_stm32f10x_hd.shd:high-density大容量,Flash容量为256 ~ 512K
startup_stm32f10x_xl.sxl:超大容量,Flash容量为512K ~ 1024K
以上4种都属于基本型
startup_stm32f10x_cl.scl:connectivity line devices 互联型
startup_stm32f10x_ld_vl.svl:value line devices 超值型系列
startup_stm32f10x_md_vl.s
startup_stm32f10x_hd_vl.s

6、这里我用的是startup_stm32f10x_ld.s,把他复制到我们建立的工程文件夹中的User文件夹并在我们的工程里添加它。

7、我们可以看看这个启动文件,详细的我会在后面更新的STM32启动文件详解中介绍这里我们只看我们等下需要的部分,找到这个函数Reset_Handler

 129行定义了一个子程序:Reset_Handler。 PROC是子程序定义伪指令。这里就相当于C语言中定义了一个函数,函数名是Reset_Handler。

130行EXPORT表示Reset_Handler这个子程序可以被其他模块调用。相当于C语言中对函数进行声明。[WEAK]表示弱定义,如果编译器发现在别的地方定义了同名的函数,则在链接时用别处的地址进行链接。

131、132行的TMPORT表示定义的标号在其他文件中,在链接的时候需要到其他文件中去寻找。用C语言来解释从其他文件引入函数声明。以便下面对外部函数调用。

SystemInit是需要我们自己实现,需要编写一个同名称的函数,用来初始化STM32的时钟,用来时STM32达到稳定运行。这个函数固件库里有但我们寄存器编程的化还是要写的(但这个函数只要写个空的同名函数就行了,只要骗过编译器我们已经写了,里面可以不用写东西。STM32在我们没有配置时钟的时候会自己使用内部的系统时钟)关注我在后面更新的时钟章节会详细介绍

_main不用我们定义(不要与C语言中的主函数main混淆了)这是一个C库函数,该函数主要功能是:初始化栈、堆,配置系统环境,并在函数最后调用用户编写的主函数,从此进入C的环境。

133行把SystemInit的地址写入到寄存器R0。

134行程序跳转到R0中执行程序,就是执行SystemInit函数。

135行吧_main的地址写入到寄存器R0。

136行程序跳转到R0中执行程序,就是执行_main函数。

137程序结束。

8、看完启动文件我们就可以开始写我们的代码了,哪我们该怎么动手呢,看过我前篇文章STM32-存储器和寄存器中知道,寄存器就是就是给一个已经分配好地址的特殊内存空间的一个别名,既然是地址那么我们就可以用C语言中的指针来操作它。那么我们来实现寄存器映射(不知到什么意思可以翻看我前面STM32-存储器和寄存器文章)。

stm32f10x.h头文件

#ifndef _STM32F103_H_
#define _STM32F103_H_

/*片上外设基地址*/
#define PERIPH_BASE         ((unsigned int) 0x40000000)

/*总线基地址,GPIO挂再在APB2上,详情可以看STM的手册*/
#define APB2PERIPH_BASE     (PERIPH_BASE+0x10000)

/*AHB总线基地址*/
#define AHBPERIPH_BASE      ((unsigned int)0x40020000)

/*GPIOB外设的基地址*/
#define GPIOB_PERIPH_BASE   (APB2PERIPH_BASE+0x0c00)

/*RCC外设基地址*/
#define RCC_BASE     (AHBPERIPH_BASE+0x1000)

/*GPIOB寄存器地址*/
#define GPIO_CRL            *(unsigned int*)(GPIOB_PERIPH_BASE+0x00)
#define GPIO_ODR            *(unsigned int*)(GPIOB_PERIPH_BASE+0x0c)
#define GPIO_BSRR           *(unsigned int*)(GPIOB_PERIPH_BASE+0x10)
#define GPIO_BRR            *(unsigned int*)(GPIOB_PERIPH_BASE+0x14)

/*RCC的使能寄存器地址*/
#define RCC_APB2ENR        *(unsigned int*)(RCC_BASE+0x18)

#endif

这里我吧手册中的存储器印象地址放这里详情可以查看手册STM32FXX手册  https://pan.baidu.com/s/1sk1_DSbL5ZV33I7zqzJEsg 
提取码:pyj1

 寄存器的地址就是在外设GPIOB的地址上加上地址偏移,可以在手册中查看比如CRL(端口配置低寄存器)就是GPIOB_PERIPH_BASE(GPIOB外设基地址)+0x00(偏移地址)后面几个寄存器以此类推。

 main主函数

#include "stm32f103.h"
int main()
{
    /*开启GPIOB端口的时钟,详情可看下文1*/
	RCC_APB2ENR|=((1)<<3);

    /*清空控制PB0的端口位*/
	GPIO_CRL&=~((0x0f)<<(4*0));

    /*配置PB0为通用推挽输出,速度为10MHz,详情可看下文2*/
	GPIO_CRL|=((1)<<(4*0));

    /*PB0输出低电平,详情可看下文3*/
	GPIO_ODR |= (0<<0);

}
void SystemInit()  /*骗过编译器我们已经编写了,详情可以看上面关于启动文件的介绍*/
{

}

1、开启GPIO端口时钟

2、 配置PB0为通用推挽输出,速度为10MHz

3、 PB0输出低电平

9、编译后我们来看看仿真结果可以看出来LED已经被点亮了

其实寄存器编程和固件库编程本质上都一样都是配置各种寄存器,可以看我前面的文章STM32-固件库编程点亮LED对照的看一下,关注我后面我会更新STM32所有特色外设的介绍,STM32时钟篇章

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值