STM32F429入门(二)

开始学习嵌入式的第二天,发现昨天学习的东西有些遗漏,今天要做个补充😎。那么就从寄存器那一块开始补学吧,昨天没有那么仔细地去学习这个知识。

(一)学会看丝印:

  • 如果有小圆点在芯片上,则从这个小圆点开始逆时针,就是引脚口从1到最大引脚口。

  • 如果没有小圆点在芯片上,则正看芯片,引脚口1在左上角开始,再逆时针。 

     

(二)芯片和外设之间通过各种总线连接,其中主控线(也就是内核控制的部分)有8条,被控总线有7条,主控总线通过一个总线矩阵来连接被控总线,总线矩阵用于主控总线之间的访问仲裁管理,仲裁采用 循环调度算法。总线之间交叉的时候如果有个圆圈则表示可以通信,没有圆圈则表示不可以通信。

(三)STM32有三种启动方式:

  • 从Flash启动(包含系统存储器)

  • 从内部SRAM启动

  • 从外部RAM启动

    这也可以说明,启动总线与三根被控总线有交叉,也就是再总线接口图中有圆圈,这三种存储器就刚好对应三条总线。

    (四)总线基地址

    片上的外设分为四条总线,根据外设速度不同,不同总线挂载着不同的外设,APB挂载低速外设,AHB挂载高速外设(GPIO为高速外设)。相应总线的最低地址我们陈为总线的基地址。

  •  

如图,0x4002 0000为AHB1总线的基地址。

相对外设基地址的偏移:即该总线地址与“片上外设”基地址 0x4000 0000 的差值。方便对外设进行封装使用。

 

(五)外设基地址

总线上挂载着各种外设,这些外设也有自己的地址范围,特定外设的首个地址称为 “XX 外设基地址”,也叫 XX 外设的边界地址。

对于我的理解就是,在确定总线基地址之后,我们在对总线中的外设进行分配地址,而相对地址的偏移,就是相对于总线地址的偏移。

 

(六)外设寄存器

在 XX 外设的地址范围内,分布着的就是该外设的寄存器。以 GPIO 外设为例,GPIO 是通用输入输出端口的简称,简单来说就是 STM32 可控制的引脚,基本功能是控制引脚输出高电平或者低电平。最简单的应用就是把 GPIO 的引脚连接到 LED 灯的阴极,LED 灯的 阳极接电源,然后通过 STM32 控制该引脚的电平,从而实现控制 LED 灯的亮灭。

GPIO 有很多个寄存器,每一个都有特定的功能。每个寄存器为 32bit,占四个字节, 在该外设的基地址上按照顺序排列,寄存器的位置都以相对该外设基地址的偏移地址来描述。

按照以上几层基地址的层次嵌套,我们使用C语言封装后,可以看到以下:

1 /* 外设基地址 */

 

2 #define PERIPH_BASE ((unsigned int)0x40000000)

4 /* 总线基地址 */

5 #define APB1PERIPH_BASE PERIPH_BASE

6 #define APB2PERIPH_BASE (PERIPH_BASE + 0x00010000)

7 #define AHB1PERIPH_BASE (PERIPH_BASE + 0x00020000)

8 #define AHB2PERIPH_BASE (PERIPH_BASE + 0x10000000)

10 /* GPIO外设基地址 */

11 #define GPIOA_BASE (AHB1PERIPH_BASE + 0x0000)

12 #define GPIOB_BASE (AHB1PERIPH_BASE + 0x0400)

13 #define GPIOC_BASE (AHB1PERIPH_BASE + 0x0800)

14 #define GPIOD_BASE (AHB1PERIPH_BASE + 0x0C00)

15 #define GPIOE_BASE (AHB1PERIPH_BASE + 0x1000)

16 #define GPIOF_BASE (AHB1PERIPH_BASE + 0x1400)

17 #define GPIOG_BASE (AHB1PERIPH_BASE + 0x1800)

18 #define GPIOH_BASE (AHB1PERIPH_BASE + 0x1C00)

20 /* 寄存器基地址,以GPIOH为例 */

21 #define GPIOH_MODER (GPIOH_BASE+0x00)

22 #define GPIOH_OTYPER (GPIOH_BASE+0x04)

23 #define GPIOH_OSPEEDR (GPIOH_BASE+0x08)

24 #define GPIOH_PUPDR (GPIOH_BASE+0x0C)

25 #define GPIOH_IDR (GPIOH_BASE+0x10)

26 #define GPIOH_ODR (GPIOH_BASE+0x14)

27 #define GPIOH_BSRR (GPIOH_BASE+0x18)

28 #define GPIOH_LCKR (GPIOH_BASE+0x1C)

29 #define GPIOH_AFRL (GPIOH_BASE+0x20)

30 #define GPIOH_AFRH (GPIOH_BASE+0x24)

所以偏移地址的好处就显而易见了,在封装时,在基地址上加入偏移地址就可以了!😎

(七)举个栗子

如果要使PH10实现输出低/高电平,要怎么实现?

step1:确定总线地址

#define PERIPH_BASE ((unsigned int)0x40000000)

#define AHB1PERIPH_BASE (PERIPH_BASE + 0x00020000)

#define GPIOH_BASE (AHB1PERIPH_BASE + 0x1C00)

#define GPIOH_ODR *(unsignedint*)(GPIOH_BASE+0x14)

step 2 :

//输出低电平

GPIOH_ODR &= ~(1<<10);

以上代码是使1左移10位,后再取反,再与原来的值相与,保存原来的电平状态。如图所示:

 

step 3:

//输出高电平

GPIOH_ODR |= (1<<10);

(八)由于每个寄存器的偏移地址都是4位,类似于结构体的成员,成员地址都是递增的,所以我们使用结构体来封装寄存器列表,也就是上一篇文的所有GPIO寄存器,那就再提及一遍吧:

typedef unsigned int uint32_t; /*无符号32位变量*/

typedef unsigned short int uint16_t; /*无符号16位变量*/

/* GPIO寄存器列表 */

typedef struct {

uint32_t MODER; /*GPIO模式寄存器 地址偏移: 0x00 */

uint32_t OTYPER; /*GPIO输出类型寄存器 地址偏移: 0x04 */

uint32_t OSPEEDR; /*GPIO输出速度寄存器 地址偏移: 0x08 */

uint32_t PUPDR; /*GPIO上拉/下拉寄存器 地址偏移: 0x0C */

uint32_t IDR; /*GPIO输入数据寄存器 地址偏移: 0x10 */

uint32_t ODR; /*GPIO输出数据寄存器 地址偏移: 0x14 */

uint16_t BSRRL; /*GPIO置位/复位寄存器低16位部分 地址偏移: 0x18 */

uint16_t BSRRH; /*GPIO置位/复位寄存器高16位部分 地址偏移: 0x1A */

uint32_t LCKR; /*GPIO配置锁定寄存器 地址偏移: 0x1C */

uint32_t AFR[2]; /*GPIO复用功能配置寄存器 地址偏移: 0x20-0x24 */

} GPIO_TypeDef;

所以我们就可以使用结构体来访问寄存器:

GPIO_TypeDef *GPIOx; //定义一个GPIO_TypeDef类型的结构体指针GPIOx

GPIOx = GPIOH_BASE; //把指针地址设置为宏GPIOH_BASE地址

GPIOx->BSRRL = 0xFFFF; //通过指针访问并修改GPIOH_BSRRL寄存器

GPIOx->MODER = 0xFFFFFFFF; //修改GPIOH_MODER寄存器

GPIOx->OTYPER =0xFFFFFFFF; //修改GPIOH_OTYPER寄存器

uint32_t temp;

temp = GPIOx->IDR; //读取GPIOH_IDR寄存器的值到变量temp中

还有一种更简单的方法,就是定义GPIO端口基地址指针,这种方法比较常见:

/*使用GPIO_TypeDef把地址强制转换成指针*/

#define GPIOA ((GPIO_TypeDef *) GPIOA_BASE)

#define GPIOB ((GPIO_TypeDef *) GPIOB_BASE)

#define GPIOC ((GPIO_TypeDef *) GPIOC_BASE)

#define GPIOD ((GPIO_TypeDef *) GPIOD_BASE)

#define GPIOE ((GPIO_TypeDef *) GPIOE_BASE)

#define GPIOF ((GPIO_TypeDef *) GPIOF_BASE)

#define GPIOG ((GPIO_TypeDef *) GPIOG_BASE)

#define GPIOH ((GPIO_TypeDef *) GPIOH_BASE)

定义以上后,我们可以直接”调用寄存器“:

GPIOA->ODR = 0xFF;

GPIOB->ODR = 0xFF;

... ...

那最后做个总结吧,其实封装就是,从内存映射到寄存器(define),之后用结构体封装,最后再用结构体指针指向从而可以直接使用。(个人理解)

以上只是以GPIO为例子来理解这个东西,其实其他外设也是这么封装的,那么今天的学习就到这吧,希望明天课多的我还可以挤出时间来学习!而且学习不敢像第一天这么敷衍了,漏了好多知识点T T。

### STM32F429BIT6 微控制器引脚配置和功能 对于STM32F429BIT6微控制器而言,其引脚配置和功能可以通过查阅官方数据手册获得详细的表格信息。通常,在这类文档中会提供一张或多张详尽的引脚定义表,其中每一行代表一个单独的引脚,并列出该引脚的功能描述、电气特性以及其他重要参数[^1]。 例如,常见的引脚属性可能包括但不限于: - **引脚编号 (Pin Number)**: 物理位置上的编号。 - **信号名称 (Signal Name)**: 对应于内部电路的具体信号名。 - **I/O 类型**: 输入/输出模式指示。 - **默认状态**: 上电后的初始设置情况。 - **其他用途**: 可能存在的复用选项或特殊功能分配。 为了获取最准确的信息,建议访问ST官方网站并下载最新的《STM32F429参考手册》以及特定型号的数据表来查看完整的引脚列表及其对应的功能说明。由于目前存在网页显示异常的情况影响到部分资源的正常加载,可以尝试通过搜索引擎或其他可靠渠道寻找替代版本的手册文件。 此外,关于如何解析这些引脚配置图表中的具体细节,可以从以下几个方面入手理解: #### 解读引脚图的关键要素 - **多路复用(Multiplexing)**: 许多GPIO端口支持多种外设接口的选择,这意味着同一个物理引脚可以根据编程需求切换不同的逻辑功能。 - **电源管理(Power Management)**: 部分引脚专门用于供电轨连接(VDD, VSS),确保稳定的工作电压供给整个芯片工作所需条件。 - **调试与测试(Debug & Test)**: SWD/JTAG等专用引脚允许开发者利用工具链实现程序烧录、在线调试等功能。 ```c // 示例代码片段:初始化某个具有多重角色的IO引脚作为UART通信线 void setup_uart_pin(void){ GPIO_InitTypeDef GPIO_InitStruct = {0}; __HAL_RCC_GPIOA_CLK_ENABLE(); // 启用GPIOA时钟 /* PA9 -> TX */ GPIO_InitStruct.Pin = GPIO_PIN_9; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; // 复用推挽输出 GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

郑烯烃快去学习

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值