LED流水灯

基于寄存器与基于固件库的 stm32 LED 流水灯

一、创建一个 keil 工程(寄存器版)
打开 keil,点击 Project,选择 New uVision Project
选择 CPU 型号,根据开发板进行选择

在线添加库文件
用寄存器控制 STM32 时,不需要在线添加库文件,可以直接关掉。
添加文件
① 添加已经存在文件
在新建的工程中添加启动文件(startup_stm32f10x_hd.s),该文件可以先到固件库中复制到此处 startup_stm32f10x_hd.s。
② 创建新文件
stm32f10x.h
手动新建,用于存放寄存器映射的代码,暂时为空。
main.c
手动新建,用于存放 main 函数,暂时为空。
配置魔术棒选项卡
①Target 设置

②Output 设置

③Listing 设置

④Debug 设置

⑤Utilities 设置

⑥Debug Settings 设置

二、基于寄存器 stm32 LED 流水灯

寄存器的定义

寄存器的功能是存储二进制代码,它是由具有存储功能的触发器组合起来构成的。一个触发器可以存储 1 位二进制代码,故存放 n 位二进制代码的寄存器,需用 n 个触发器来构成。

GPIO (通用输入输出端口)
STM32 可控制的引脚。

此图引用零死角玩转 STM32——F103 指南版中对 GPIO 介绍,具体介绍可参考该书。
GPIO 的工作模式

typedef enum
{
GPIO_Mode_AIN = 0x0, // 模拟输入
GPIO_Mode_IN_FLOATING = 0x04, // 浮空输入
GPIO_Mode_IPD = 0x28, // 下拉输入
GPIO_Mode_IPU = 0x48, // 上拉输入
GPIO_Mode_Out_OD = 0x14, // 开漏输出
GPIO_Mode_Out_PP = 0x10, // 推挽输出
GPIO_Mode_AF_OD = 0x1C, // 复用开漏输出
GPIO_Mode_AF_PP = 0x18 // 复用推挽输出
} GPIOMode_TypeDef;

输入模式:上拉和下拉输入的电平由上拉或者下拉,浮空输入的电平是不确定的,完全由外部的输入决定,一般接按键的时候用的是这个模式。模拟输入则用于 ADC 采集。 输出模式:推挽模式时双 MOS 管以轮流方式工作,输出数据寄存器 GPIOx_ODR 可控制 I/O 输出高低电平。开漏模式时,只有 N-MOS 管工作,输出数据寄存器可控制 I/O 输出高阻态或低电平。

编写 LED 的代码(该过程需要参考 STM32F10 的手册)
stm32f10x.h

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

/*总线基地址,GPIO 都挂载到 APB2 上 /
#define APB2PERIPH_BASE (PERIPH_BASE + 0x10000)
#define AHBPERIPH_BASE (PERIPH_BASE +0x20000)
/GPIOC 外设基地址
/
#define GPIOC_BASE (APB2PERIPH_BASE + 0x1000)
//GPIOC_BASE=0x40000000+0x10000+0x1000=0x40011000,该地址为 GPIOC 的基地址
/ GPIOB 寄存器地址,强制转换成指针 */
#define GPIOC_CRL (unsigned int)(GPIOC_BASE+0x00)
#define GPIOC_CRH (unsigned int)(GPIOC_BASE+0x04)
#define GPIOC_IDR (unsigned int)(GPIOC_BASE+0x08)
#define GPIOC_ODR (unsigned int)(GPIOC_BASE+0x0C)
#define GPIOC_BSRR (unsigned int)(GPIOC_BASE+0x10)
#define GPIOC_BRR (unsigned int)(GPIOC_BASE+0x14)
#define GPIOC_LCKR (unsigned int)(GPIOC_BASE+0x18)

/RCC 外设基地址/
#define RCC_BASE (AHBPERIPH_BASE + 0x1000)
/RCC 的 AHB1 时钟使能寄存器地址,强制转换成指针/
#define RCC_APB2ENR (unsigned int)(RCC_BASE+0x18)

main.c::

int main(void)
{
// 配置 RCC 寄存器,开启 GPIOC 端口时钟配置 RCC 寄存器
*(unsigned int )0x40021018 |=(1<<4);
// 配置 CRL 寄存器,配置 PC2 为通用推挽输出,速度为 10M
//
(unsigned int )GPIOC_CRL |=(1<<(42));
(unsigned int )0x40011000 |=(1<<(42));
//配置 ODR 寄存器,清空控制 PC2 的端口位

while (1)
{
}
}
编译会出现下面问题

在 main.c 添加下面函数

// 函数为空,目的是为了骗过编译器不报错
void SystemInit(void)
{
}

编译烧录后,效果如下:

https://img-blog.csdnimg.cn/20201129201442110.jpg?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQzMjc5NTc5,size_16,color_FFFFFF,t_70#pic_center

引用---原文链接:https://blog.csdn.net/qq_43279579/article/details/110320013

posted @ 2023-10-17 22:57  verthy  阅读(30)  评论(0)    收藏  举报