基于Keil使用寄存器方式点亮LED灯

一、 准备环境

需要用到:MDK和STM32PACK
安装教程:

点击跳转:https://blog.youkuaiyun.com/qq_45264808/article/details/108899662

下载链接:

MDK-5.10和STM32pack(CMSIS 3.20.4、stm32F1 1.0.4)下载链接1
提取码:rlns
STM32pack:下载链接2

二、 编写stm32程序

1.创建工程

打开Keil,点击顶栏Project:
在这里插入图片描述
创建工程:
在这里插入图片描述
在此处选择芯片,本次选择STM32F103RB
在这里插入图片描述
按教程勾选CMSIS和Device中的选项,若未看到这几个选项请检查安装的步骤有没有正确进行:
在这里插入图片描述

2.新建文件

点击左上角新建文件
在这里插入图片描述

3. 编写代码

//宏定义,用于存放stm32寄存器映射
#define PERIPH_BASE           ((unsigned int)0x40000000)//AHB
#define APB2PERIPH_BASE       (PERIPH_BASE + 0x10000)
#define GPIOA_BASE            (APB2PERIPH_BASE + 0x0800)
//GPIOA_BASE=0x40000000+0x10000+0x0800=0x40010800,该地址为GPIOA的基地址
#define GPIOB_BASE            (APB2PERIPH_BASE + 0x0C00)
//GPIOB_BASE=0x40000000+0x10000+0x0C00=0x40010C00,该地址为GPIOB的基地址
#define GPIOC_BASE            (APB2PERIPH_BASE + 0x1000)
//GPIOC_BASE=0x40000000+0x10000+0x1000=0x40011000,该地址为GPIOC的基地址
#define GPIOD_BASE            (APB2PERIPH_BASE + 0x1400)
//GPIOD_BASE=0x40000000+0x10000+0x1400=0x40011400,该地址为GPIOD的基地址
#define GPIOE_BASE            (APB2PERIPH_BASE + 0x1800)
//GPIOE_BASE=0x40000000+0x10000+0x0800=0x40011800,该地址为GPIOE的基地址
#define GPIOF_BASE            (APB2PERIPH_BASE + 0x1C00)
//GPIOF_BASE=0x40000000+0x10000+0x0800=0x40011C00,该地址为GPIOF的基地址
#define GPIOG_BASE            (APB2PERIPH_BASE + 0x2000)
//GPIOG_BASE=0x40000000+0x10000+0x0800=0x40012000,该地址为GPIOG的基地址
#define GPIOA_ODR_Addr    (GPIOA_BASE+12) //0x4001080C
#define GPIOB_ODR_Addr    (GPIOB_BASE+12) //0x40010C0C
#define GPIOC_ODR_Addr    (GPIOC_BASE+12) //0x4001100C
#define GPIOD_ODR_Addr    (GPIOD_BASE+12) //0x4001140C
#define GPIOE_ODR_Addr    (GPIOE_BASE+12) //0x4001180C
#define GPIOF_ODR_Addr    (GPIOF_BASE+12) //0x40011A0C   
#define GPIOG_ODR_Addr    (GPIOG_BASE+12) //0x40011E0C 
 
#define BITBAND(addr, bitnum) ((addr & 0xF0000000)+0x2000000+((addr &0xFFFFF)<<5)+(bitnum<<2))
#define MEM_ADDR(addr)  *((volatile unsigned long  *)(addr))
 
 #define LED0  MEM_ADDR(BITBAND(GPIOA_ODR_Addr,8))
//#define LED0 *((volatile unsigned long *)(0x422101a0)) //PA8
//定义typedef类型别名
typedef  struct
{
   volatile  unsigned  int  CR;
   volatile  unsigned  int  CFGR;
   volatile  unsigned  int  CIR;
   volatile  unsigned  int  APB2RSTR;
   volatile  unsigned  int  APB1RSTR;
   volatile  unsigned  int  AHBENR;
   volatile  unsigned  int  APB2ENR;
   volatile  unsigned  int  APB1ENR;
   volatile  unsigned  int  BDCR;
   volatile  unsigned  int  CSR;
} RCC_TypeDef;
 
#define RCC ((RCC_TypeDef *)0x40021000)
//定义typedef类型别名
typedef  struct
{
volatile  unsigned  int  CRL;
volatile  unsigned  int  CRH;
volatile  unsigned  int  IDR;
volatile  unsigned  int  ODR;
volatile  unsigned  int  BSRR;
volatile  unsigned  int  BRR;
volatile  unsigned  int  LCKR;
} GPIO_TypeDef;
//GPIOA指向地址GPIOA_BASE,GPIOA_BASE地址存放的数据类型为GPIO_TypeDef
#define GPIOA ((GPIO_TypeDef *)GPIOA_BASE)
 
void  LEDInit( void )
{
     RCC->APB2ENR|=1<<2;  //GPIOA 时钟开启
     GPIOA->CRH&=0XFFFFFFF0;
     GPIOA->CRH|=0X00000003; 
}
 
//粗略延时
void  Delay_ms( volatile  unsigned  int  t)
{
     unsigned  int  i,n;
     for (n=0;n<t;n++)
         for (i=0;i<800;i++);
}

int main(void)
{
	 LEDInit();
     while (1)
     {
         LED0=0;//LED熄灭
         Delay_ms(500);//延时时间
         LED0=1;//LED亮
         Delay_ms(500);//延时时间
     }
}

注意:若中文在代码中乱码,可以顶栏中单击:
Edit->configuration
在这里插入图片描述

点击保存
在这里插入图片描述
在这里插入图片描述

3.编译程序

Ⅰ首先添加至group中

在这里插入图片描述

Ⅱ 点击编译

在这里插入图片描述
Ⅲ 检查是否报错
0 error时才编译成功
在这里插入图片描述

进行仿真

Ⅰ 编译设置

点击魔法棒后进行如下勾选
在这里插入图片描述
点击setting:
在这里插入图片描述
最后点击load即可烧录到stm32

### 使用寄存器编程点亮LED的方法 通过寄存器编程控制嵌入式系统的硬件资源是一种高效的方式,尤其适用于需要精确控制的场景。以下是基于STM32控制器的寄存器编程方法,用于点亮LED。 #### 1. 原理说明 在嵌入式系统中,GPIO(通用输入输出)引脚可以通过配置其对应的寄存器来实现不同的功能。对于点亮LED的操作,通常需要将某个GPIO引脚设置为推挽输出模式,并通过改变该引脚的状态(高电平或低电平),使LED亮起或熄灭[^2]。 #### 2. GPIO寄存器的功能描述 STM32控制器中的GPIO模块包含多个寄存器,其中以下几个寄存器与本次操作密切相关: - **GPIOx_MODER**:定义引脚的工作模式(输入、输出等)。例如,要将某引脚设为输出模式,需修改此寄存器的相关位。 - **GPIOx_OTYPER**:指定输出类型(开漏或推挽)。为了获得更高的电流驱动能力,一般选择推挽输出模式。 - **GPIOx_OSPEEDR**:设定输出速度。虽然大多数情况下默认值即可满足需求,但在某些高速应用场景下可能需要注意调整。 - **GPIOx_PUPDR**:配置上下拉电阻状态,默认可以选择下拉以防止浮空。 - **GPIOx_ODR** 或 **GPIOx_BSRR**:用于设置或清除特定引脚的输出值。前者可以直接读取当前状态后再更新;后者允许单独置位或复位某一比特而无需关心其他部分的数据[^4]。 #### 3. 实现步骤详解 尽管不使用流程词表述,这里按照逻辑顺序提供完整的解决方案: ##### 配置工作环境 确保已安装必要的工具链,包括但不限于Keil MDK软件及其配套组件如ARMCC编译器以及调试接口驱动(ST-Link/CH340)[^3]。 ##### 初始化目标外设 编写初始化函数完成如下任务: 1. 解锁相应端口的CRH/CRL区域以便进一步更改; 2. 设置MODER字段使得所选针脚成为普通数字信号出口而非模拟用途或其他特殊角色; 3. 调整OTYPER使其支持双向强驱动力度即所谓的Push-Pull形式运作; 4. 如果必要的话还可以调节OSPEEDR提高切换速率不过这一步骤往往影响不大除非特别强调实时性能指标; 5. 对于PUDPR则推荐采用Pull Down策略减少干扰风险同时保持稳定待机电压水平直到正式启用为止。 下面给出一段示范性质的C语言源码片段展示如何执行上述各项设定动作: ```c #include "stm32f1xx.h" void GPIO_Init(void){ RCC->APB2ENR |= RCC_APB2ENR_IOPAEN; // Enable clock access to Port A // Set PA5 as output (push-pull mode, low speed is sufficient here) GPIOA->CRL &= ~(0xF << 20); // Clear bits related to pin 5 configuration GPIOA->CRL |= (0x1 << 20); // Select general purpose output mode // Optional but recommended: set pull-down resistor initially when idle. GPIOA->ODR &= ~(1<<5); // Ensure initial state pulls down the line before active driving begins later on... } ``` 调用`GPIO_Init()`之后便完成了基础准备工作接下来只需简单操控输出数据寄存器就能达成预期效果比如让红色指示持续发光可通过以下命令行实现: ```c GPIOA->BSRR = (1<<5); // Turn ON Red LED connected at Pin 5 of PORT A by setting it HIGH instantly without affecting other pins simultaneously within same register operation cycle! // Alternatively you may also use ODR directly though BSRR offers more flexibility sometimes especially during rapid toggling sequences where atomicity matters most critically under interrupt contexts etc.. ``` 反之如果希望关闭这个器件那么只需要执行相反的动作也就是将其拉回到零伏特位置上去就可以了同样非常简便快捷而且效率极高因为这一切都发生在硬件层面几乎没有任何额外延迟成本存在. #### 4. 总结 综上所述,借助寄存器级指令可以极其精细地掌控每一个细节从而达到最佳优化目的无论是功耗还是响应时间等方面都能体现出明显优势因此值得深入研究掌握这项技能无疑会对未来从事此类项目开发带来巨大帮助[^1]. ---
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值