STMCU小助手
发布时间:2022-2-2 20:00
|
ARM处理器家族
想要操作stm32的外设通常可以使用寄存器或者stm32库,在当今stm32库已经十分成熟,并且操作十分简单。 寄存器:寄存器则是内置于各个 IP 外设中,是一种用于配置外设功能的存储器,就是一种内存,并且有相对应的地址。 GPIO:通用输入输出接口 按键:通过输入电平的高低感知来得到按键的按下与否。 led灯:通过输出高低电平控制led的亮与灭。 GPIO也可以作为串口数据的收发管脚或AD接口等复用功能,根据数据手册配置相应的功能寄存器。 GPIO寄存器MODER 32位两位为一组,分为了16个,分别对应每一组GPIO的16个 管脚。如PA0-PA15。 点灯:学习嵌入式开发最开始的操作就是点灯,以下使用寄存器操作和库函数操作来点灯。 寄存器:从技术参考手册中可以找到ODR 寄存器的地址偏移是: 0CH,这个偏移地址是基于端口的起始地址而言的。在 STM32 中,每个外设都有一个起始地址,叫做外设基址,外设的寄存器就以这个基地址为标准按照顺序排列,跟结构体里面的成员差不多。 假设我们需要点亮的灯是由GPIOB-0这个管脚去控制的,找到GPIOB对应的基地址,再加上ODR的偏移地址就可以去实现输出功能。 ![]()
![]() 器了: #define GPIOB_ODR *(volatile unsigned long *)0x40010C0C 有了这个寄存器定义,我们就可以直接操作 GPIOB_ODR 了。虽然配置了 ODR 寄存器,但是这个时候还不能点亮 LED ,因为 STM32 的 IO 口还要配置方向,这个由端口配置寄存器来控制。端口配置寄存器分为高低两个,每 4bit 控制一个 IO 口,所以端口配置低寄存器: CRL 控制这 IO 口的低 8 位,端口配置高寄存器: CRH控制这 IO 口的高 8位。在 4 位一组的控制位中, CNFy[1:0] 用来控制端口的输入输出,MODEy[1:0] 用来控制输出模式的速率,即输出时, IO 电平翻转的速度。 输入有三种模式,输出有 4 中模式,我们在控制 LED 的时候选择通用推挽输出。 输出速率有三种模式: 2M、10M 、50M,这里我们选择 2M。 同 GPIOB_ODR 一样,我们也可以算出 GPIO_CRL 的地址为: 0x40010C00。那么设置PB0 为通用推挽输出,输出速率为 2M 的代码则如下所示: #define GPIOB_CRL *(volatile unsigned long *)0x40010C00 // 配置 PB0 为通用推挽输出,输出速率为 2M GPIOB_CRL = (2<<0) | (0<<2);
![]() 当我们设置了 IO 口的方向,并在相应的输出寄存器里面输入了值的时候,以为现在总算可以点亮 LED 了吧,其实还差最后一步。 STM32 外设很多,为了降低功耗,每个外设都对应着一个时钟,在系统复位的时候这些时钟都是被关闭的,如果想要外设工作,必须把相应的时钟打开。 STM32 的所有外设的时钟由一个专门的外设来管理,叫 RCC(reset and clockcontrol ), RCC 在 STM32 中文参考手册的第六章。 STM32 的外设因为速率的不同,分别挂载到三条总系上: AHB 、APB2 、APB1 ,APB为高速总线, APB2 次之, APB1 再次之。 所有的 IO 口都挂载到 APB2 总线上,属于高速外设。时钟由 APB2 外设时钟使能寄存器 (RCC_APB2ENR) 来控制,其中 PB 端口的时钟由该寄存器的位 3 写 1 使能。
同 ODR 和 CRL,我们可以算出 RCC_APB2ENR 的地址为: 0x40021018。那么使能PB 口的时钟代码则如下所示:#define RCC_APB2ENR *(volatile unsigned long *)0x40021018 // 开启端口 B 时钟 RCC_APB2ENR |= 1<<3; 我们虽然开了端口时钟,那这个时钟到底是多大?时钟到底是从哪里来的? 如果我们用的是库,那么有个库函数 SystemInit ,会帮我们把系统时钟设置成 72M 。现在我们没有使用库,那现在时钟是多少? 答案是 8M,当外部 HSE 没有开启或者出现故障的时候,系统时钟由内部低速时钟 LSI 提供,现在我们是没有开启 HSE,所以系统默认的时钟是 LSI=8M 。 如果你想自己先尝鲜,那么看 RCC 外设中的:时钟控制寄存器 (RCC_CR) 和时钟配置寄存器(RCC_CFGR) 这两个寄存器即可。 控制了电平,配置了方向,开启了时钟,经过这三步,我们总算可以控制一个 LED了。 现在我们完整组织下用 STM32 控制一个 LED 的代码:
这种就是比较愚蠢的配置方式,每次配置一个外设就去从参考手册中去找,浪费时间且容易出错,但新手入门是需要理解并且操作学习一下的。 如果要以寄存器配置的话,会将所有的寄存器位置都先定义好,这样就不用一个个去找。实际开发过程中很少使用寄存器操作,一般都是库函数的操作,下面介绍库的操作。 keil的stm32环境自行去百度配置,篇幅太长就不写出了。 固件库分析:看看每个文件的作用是什么,这对我们能否清晰的调用库函数编程非常重要。 STM32 由 Cortex-M3 内核和内核之外的各种外设组成,库在编写的时候也遵循这中组成结构,把代码分成两大部分,一种是操作内核外设的, 另外一种是内核之外的外设,为了听起来不那么绕,下面我们把内核之外的外设用处理器外设来代替。
![]()
直接写库函数操作了:
Mode和Speed相关结构体也是被设定好的,可以自行查找这里就不写出来了,直接赋值就可以了,十分方便并且相对于寄存器操作便于理解。 GPIO_Init(GPIO_TypeDef *, GPIO_InitTypeDef *);第一个参数,说明它将要对GPIOB 端口进行初始化。初始化的配置以第二个参数 GPIO_InitStructure 结构 体的成员值为准。这个结构体的成员,我们在调用GPIO_Init()前,已对它们 赋予了控制参数。 |
【福利三:逢7发帖赢大礼】4、基于STM32G070板子SPI flash 移植SFUD库
【福利三:逢7发帖赢大礼】基于STM32G070板子的uart shell移植设计
【福利三:逢7发帖赢大礼】3、基于STM32G070板子的YModem串口协议通信
【福利三:逢7发帖赢大礼】2、基于STM32G070板子的OLED移植U8G2库
实战经验 | ClassB功能安全认证代码与应用代码分区的实现要点
STM32G0 系列 I2C 通信异常典型案例分析与解决方案总结
经验分享 | LAT1490 两个STM32G0 I2C 通信异常的案例分析
经验分享 | STM32G0 I2C bootloader Go 命令后调试连接失败:DBG_SWEN 位复位修复
经验分享 | STM32G0B1 待机模式意外唤醒深度解析:RTC 结构体未初始化的隐形坑
经验分享 | STM32G0B1 待机模式意外唤醒深度解析:RTC 结构体未初始化的隐形坑
微信公众号
手机版