7 . 如何使用寄存器点亮一个LED灯
Posted 技术世界低调点儿
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了7 . 如何使用寄存器点亮一个LED灯相关的知识,希望对你有一定的参考价值。
如何点亮LED
本篇讲解用寄存器在stm32 开发板上点亮一个LED灯 , 原理图如下:
相同网络标号表示它们是连接在一起的,因此LED1-LED8 发光二极管阴极是连接在STM32 的PC0-PC7 管脚上。如果要使D1 指示灯亮,只需要控制PC0 管脚输出低电平,如果要使D1 指示灯灭,只需控制PC0 输出高电平。对于其他的LED 控制方法一样。我们所要实现的功能是点亮D1 发光二极管,即让STM32 的PC0 管脚输出一个低电平。
下面就开始使用寄存器来操作STM32 使PC0 输出一个低电平。要操作STM32寄存器,我们就需要使用C 语言对其封装,这部分程序我们都放在stm32f10x.h中。具体代码如下:
#define PERIPH_BASE ((unsigned int)0x40000000) //外设的起始地址
#define APB2PERIPH_BASE (PERIPH_BASE + 0x00010000) // APB2总线的基地址,因为GPIO是挂在APB2总线上
#define GPIOC_BASE (APB2PERIPH_BASE + 0x1000) //GPIOC的基地址,这里直接找到GPIOC
#define GPIOC_CRL *(unsigned int*)(GPIOC_BASE+0x00) // 以下是封装GPIO的七个寄存器的地址
#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)
#define AHBPERIPH_BASE (PERIPH_BASE + 0x20000) / /AHB总线的基地址,因为时钟外设是挂在AHB总线上
#define RCC_BASE (AHBPERIPH_BASE + 0x1000) //reset and control clock 基地址
#define RCC_APB2ENR *(unsigned int*)(RCC_BASE+0x18) //时钟使能寄存器
要控制PC0 输出低电平,需知道GPIO 这个外设它是挂接在哪个总线上的,通过Block2 外设基地址及APB2 总线的偏移地址就可以得到APB2 外设的基地址。GPIO 就是挂接在APB2 总线上的,根据GPIOC 的偏移地址就可以得到GPIOC 外设的基地址,GPIOC 外设内部含有很多个寄存器,比如GPIOC_CRL、GPIOC_CRH 端口配置寄存器、GPIOC_BSRR 置位复位寄存器等,通过他们各自的偏移地址就可以获取对应的寄存器地址,然后要操作地址里面的内容就需要使用到指针,将其强制转换为unsigned int指针类型,然后在通过一个指针来操作该地址里面的内容。
在STM32 中凡是使用到外设功能,都要使能对应的外设时钟,否则即使配置好端口初始化也无法正常使用。因此还需要知道时钟RCC 外设的基地址,通过《STM32F103ZET6 数据手册》“4 Memory mapping”的“存储器映射”章节可以知道RCC 时钟外设是挂接在AHB 总线上,根据其偏移值可以得到RCC 时钟外设的基地址,然后可通过《STM32F1xx 中文参考手册》的“6 小容量、中容量和大容量产品的复位和时钟控制(RCC)”的“6.3.7 APB2 外设时钟使能寄存器(RCC_APB2ENR)”可找到对应的端口RCC 使能寄存器,只要将GPIOC 端口时钟使能即可。
使用C 语言封装好寄存器后,就开始编写main 函数,打开main.c 文件,程序代码如下:
#include "stm32f10x.h" (1)
void SystemInit() (2)
int main()
RCC_APB2ENR |= 1<<4; (3) //使能APB2中的GPIOC时钟,默认模式,后续会继续讲解时钟的选择和配置
GPIOC_CRL &= ~( 0x0F<< (4*0)); // 清零低四位
GPIOC_CRL |= (3<<4*0); (4)//设置输出模式和输出速度,默认是通用推挽输出
GPIOC_BSRR=(1<<(16+0)); (5)//重置引脚的值为0,输出低电平
while(1)
在上述代码后面我们标注了序号,下面按照序号顺序介绍:
(1)包含stm32f10x.h 头文件,在这个头文件中我们定义的都是寄存器,因此如果要在其他文件中使用这些寄存器就需要把这个头文件包含进来,否则编译就会报错。
(2)SystemInit 函数,程序运行的时候先进入这个函数进行STM32 的初始化,如果不写这个函数编译器就会报错。这里我们编写这个函数,里面并不对其操作。
(3)开启GPIOC 时钟。要使PC0 正常工作输出一个低电平,必须要打开它的时钟。RCC_APB2ENR 寄存器是在stm32f10x.h 头文件中定义好的,此寄存器的第4 位是控制GPIOC 外设的时钟使能位,只有该位为1 时才使能,如果为0 即关闭GPIOC 时钟。所以要让1 左移4 位。
(4)配置GPIOC 为通用推挽输出模式。STM32 的GPIO 模式有很多,可根据CRx 寄存器设置,CRL 对应GPIO 的低8 位,CRH 对应GPIO 的高8 位。如果不是特殊需求,一般输出采用推完输出模式。我们要让PC0 管脚输出一个低电平,故使用推完输出模式。只要查下《STM32F1xx 中文参考手册》GPIO 配置寄存器内容就可以知道此寄存器内每4 位控制一个管脚。
(5)使PC0 输出低电平。GPIOC_BSRR 为置位复位寄存器, 只要查下《STM32F1xx 中文参考手册》GPIO 置位复位寄存器内容就可以知道,其高16 位用于复位,如果当高16 位某位为1,表示那一位管脚输出低电平,为0 不影响其输出电平。如果当低16 位的某位为1,表示那一位管脚输出高电平,为0 不影响其输出电平。所以要让1 左移16+0 位。
至此 ,程序完成,编译之后,介绍 以下代码大小:
从编译信息可以看出,我们的代码占用FLASH 大小为:540 字节(220+320),所用的SRAM 大小为:1024 个字节(1024+0)。
这里我们解释一下,编译结果里面的几个数据的意义:
Code:表示程序所占用FLASH 的大小。
RO-data:即Read Only-data,表示程序定义的常量,存储在FLASH 内。
RW-data:即Read Write-data,表示已被初始化的变量,存储在SRAM 内。
ZI-data:即Zero Init-data,表示未被初始化的变量,存储在SRAM 内。
有了这个就可以知道你当前使用的flash 和sram 大小了,所以,一定要注意的是程序的大小不是.hex 文件的大小,而是编译后的Code 和RO-data 之和
以上是关于7 . 如何使用寄存器点亮一个LED灯的主要内容,如果未能解决你的问题,请参考以下文章