改进寄存器点亮LED代码
野火霸道开发板学习笔记
信息说明
- 开发板: 野火霸道V2
- 芯片型号: STM32F103ZET6
- 下载器型号: 野火fireDAP下载器(高速版)
- 软件环境: Keil5(MDK-ARM V5.15)
- 芯片包型号: Keil.STM32F1xx_DFP.1.1.0 注: 亲测版本2.4.0不可用
- 操作系统 : Win11
寄存器点亮LED改进
原理分析
主要是对外设进行宏定义方便使用
在stm32f10x.h文件中
// 外设 peripherals
#define PERIPH_BASE ((unsigned int)0x40000000) // 寄存器组起始地址
#define APB1PERIPH_BASE PERIPH_BASE // APB1 peripheral
#define APB2PERIPH_BASE (PERIPH_BASE + 0x10000) // APB2 peripheral
#define AHBPERIPH_BASE (PERIPH_BASE + 0x20000) // AHB peripheral // DMA1开始, 方便计算
#define RCC_BASE (AHBPERIPH_BASE + 0x1000) // RCC
#define GPIOB_BASE (APB2PERIPH_BASE + 0x0C00) // GPIOB
#define RCC_APB2ENR *(unsigned int *)(RCC_BASE + 0x18) // RCC_APB2ENR
#define GPIOB_CRL *(unsigned int *)(GPIOB_BASE + 0x00) // GPIOB_CRL
#define GPIOB_CRH *(unsigned int *)(GPIOB_BASE + 0x04) // GPIOB_CRH
#define GPIOB_ODR *(unsigned int *)(GPIOB_BASE + 0x0C) // GPIOB_ODR
其中外设基地址查表, 如下图
值得注意的是AHB是从DMA1为基地址, 为了方便计算偏移量, 故AHB的基地址未定义为SDIO处地址
具体的外设使用指针方法可以直接操作, 如将GPIOB_CRL定义为*(unsigned int *)类型后, 对GPIOB_CRL的操作可以操纵该内存所对应的寄存器
具体的外设的绝对地址通过查表得知偏移量, 绝对地址 = 基地址 + 偏移量
如GPIOB_CRL
GPIOB的起始地址为0x4001 0C00
GPIOx_CRL的偏移地址为0x00
故GPIOB_CRL的绝对地址为0x4001 0C00 + 0x00 = 0x4001 0C00
由以上原理进行宏定义, 其余部分在Note03中由详细讲解
注: C语法补充
#if a // a为表达式
// 若a为真, 则编译以下内容, 若a为假, 则if以下else以上内容不编译
#elif b
// 相当于else if
#else
// 相当于else
#endif // 结束条件编译
main文件:
#include "stm32f10x.h"
int main(void)
{
# if 0 // 直接操作寄存器
*(unsigned int *)0x40021018 |= (1 << 3); // 打开时钟, 控制RCC_APB2ENR寄存器, 实现IO端口B时钟开启
/*
* RCC_APB2ENR寄存器(Address : 0x40021000(RCC) + 0x18)
* Bit3 : IOPBN : IO端口B时钟使能(I/O port B clock enable)
* 由软件置1或请0
* 0 : IO端口B时钟关闭
* 1 : IO端口B时钟开启
*/
*(unsigned int *)0x40010C00 |= ((1) << (4*0)); // 配置IO口为输出, 控制CRL寄存器, 实现GPIOB端口0为10MHz的推挽输出模式
/*
* GPIOx_CRL 端口配置低寄存器(Address : 0x40010C00(GPIO端口B) + 0x00)
* Bit32 CNF0 : 00 通用推挽输出模式
* Bit10 MODE0 : 01 输出模式, 最大速度10MHz
*
* Notes:
* 分成n个一组, 对清零后的第i组设置成某二进制数, 该数对应的十进制为b
* a |= (b << n * i);
* 此时 |= ((1) << (4 * 0)); // 分成4个一组, 将第0组(即bit3~0)设置为1对应的二进制(即0001B)
*/
*(unsigned int *)0x40010C0C &= ~(1 << 0); // 控制ODR寄存器, 实现GPIOB端口0输出低电平
/*
* GPIOx_ODR 端口输出数据寄存器(Address : 0x40010C00(GPIO端口B)+ 0x0C)
* Bit0 ODR0 : 端口输出数据
*
* Notes:
* 将变量a的Bit n清零, a &= ~(1 << n);
*
* 注 :
* 根据原理图LED_G的阳极为3V3, 阴极接PB0
*/
#else
// *(unsigned int *)0x40021018 |= (1 << 3); // 打开时钟, 控制RCC_APB2ENR寄存器, 实现IO端口B时钟开启
RCC_APB2ENR |= (1 << 3);
/*
* RCC_APB2ENR寄存器(Address : 0x40021000(RCC) + 0x18)
*