0
点赞
收藏
分享

微信扫一扫

STM32F103C8T6点亮LED

相关简介

根据所看视频中的演示写下相关的笔记,利用 PC13 引脚点亮LED,也就是STM32上面自带的小黄灯。

在STM32芯片中不同的芯片用于片上外设的地址、大小是不一样的,在C8T6中用于片上外设的地址为:0x4000 0000~0x5FFF FFFF,共512MB的内存。我们常用的引脚对应的地址如下表所示:

总线

端口名

地址范围





APB2

GPIOG

0x4001 2000 - 0x4001 23FF

GPIOF

0x4001 2000 - 0x4001 23FF

GPIOE

0x4001 1800 - 0x4001 1BFF

GPIOD

0x4001 1400 - 0x4001 17FF

GPIOC

0x4001 1000 - 0x4001 13FF

GPIOB

0X4001 0C00 - 0x4001 0FFF

GPIOA

0x4001 0800 - 0x4001 0BFF

在上述表格中端口名地址范围例如0x4001 2000是叫做基地址,每个寄存器会占据四个字节,也就是说偏移地址为0x04。

GPIO寄存器的相关内容

每一个GPIO寄存器对有下面七个不同的相关配置寄存器:

STM32F103C8T6点亮LED_STM32F103C8T6

各个相关的配置寄存器对应的如下图所示:

1.端口配置低寄存器(GPIOx_CRL)(x=A..E)

STM32F103C8T6点亮LED_引脚_02

通过四位来确定引脚的相关功能,即MODE0和CNF0两个确定引脚1的输入、输出模式和相关的速度。

2.端口配置高寄存器(GPIOx_CRH)(x=A..E)

STM32F103C8T6点亮LED_引脚_03

3.端口输入数据寄存器(GPIOx_IDR)(x=A..E)

STM32F103C8T6点亮LED_寄存器_04

4.端口输出数据寄存器(GPIOx_ODR)(x=A..E)

STM32F103C8T6点亮LED_寄存器_05

5.端口设置/清楚寄存器(GPIOx_BSRR)(x=A..E)

STM32F103C8T6点亮LED_STM32F103C8T6_06

6.端口清楚寄存器(GPIOx_BRR)(x=A..E)

STM32F103C8T6点亮LED_LED_07

STM32F103C8T6点亮LED_STM32F103C8T6_08

7.端口配置锁定存器(GPIOx_LCKR)(x=A..E)

当执行正确的写序列设置了位16(LCKK)时,该寄存器用来锁定端口位的配置。位[15:0]用于锁定GPIO端口的配置。在规定的写入操作期间,不能改变LCKP[15:0]。当对相应的端口位执行了 LOCK序列后,在下次系统复位之前将不能再更改端口位的配置。 每个锁定位锁定控制寄存器(CRL, CRH)中相应的4个位。

STM32F103C8T6点亮LED_引脚_09

APB2 外设时钟使能寄存器(RCC_APB2ENR)

STM32F103C8T6点亮LED_STM32F103C8T6_10

STM32F103C8T6点亮LED_寄存器_11

STM32F103C8T6点亮LED_输出模式_12

原理分析

由于PC13的一边已经和3.3V的Vcc连接,因此要想让PC13控制的小灯点亮只能输出低电平。因此需要配置MODE来控制输出的最大速度,一般而言10MHz就可以了,CNF则选择“通用推挽输出模式”,这一模式是最常用的模式,当然其他的模式也有其对应的使用场景;然后到GPIOx_CRH找到引脚13对应的MODE13和NFC13进行配置即可;最后对程序进行时钟的配置,也就是对位4进行选择即可因此点亮LED的顺序就按照下述步骤进行。

点亮LED的顺序

1.打开引脚对应的时钟

RCC寄存器地址的地址为0x4002 1000,然后RCC_APB2ENR的对应于RCC寄存器的偏移地址是0x18,所以RCC_APB2ENR的地址为0x4002 1018,而为了让单片机明白这是一个地址而不是数据因此应该转变为(*unsigned int)0x4002 1018,取地址中的值,应为*(*unsigned int)0x4002 1018,最后让第四位变成1,表达式为

(*unsigned int)0x4002 1018 |= (1<<4)

2.配置输出,确定输出模式

对所要控制的引脚的MODE和CNF进行清零,然后再进行配置。如果直接配置的话,对应位可能无法得到想要的值。进行下面的相关配置:

*(unsigned int* ) 0x40011004 &= ~(0x0F<<(20));
*( unsigned int* ) 0x40011004 |= (1<< <20);

3.输出低电平

相关代码如下:

*(unsigned int*) 0x4001 100C&=~(1<<13);   //输出低电平,点亮
*(unsigned int*) 0x40011004 |= (1< <20); //输出高电平,熄灭

代码实现

1.地址直接实现

//main.c中的代码

int main(){
*(unsigned int*)0x40021018 |=(1<<4); //打开GPIOC时钟
*(unsigned int*)0x40011004 &=~(0x0F<<(4*5)); //配置输出模式
*(unsigned int*)0x40011004 |=(1<<(4*5));
*(unsigned int*)0x4001100C &=~(1<<13); //配置输出低电平

while(1);
}

void SystemInit(void){

}

2.库函数定义实现

.h头文件一般会放初始化的定义、函数的定义等内容。有两种不同的引用方法,分别对应不同的文件:

1.<>是keil自带的头文件,只要写上去就能够自动的到相应的文件夹中去进行加载;

2.“”自定义的头文件,使用的时候必须指明路径。

//main.h 头文件

#define RCC_APB2ENR *((unsigned int* )0x40021018)
#define GPIOC_CRH *((unsigned int* )0x40011004)
#define GPIOC_ODR *((unsigned int*)0x4001100C)
#include "main.h"

int main(){
RCC_APB2ENR|=(1<<2); //打开GPIOC时钟
GPIOA_CRH &=~(0x0F<<(4*0)); //配置输出模式
GPIOA_CRH |=(1<<(4*0));
GPIOA_ODR &=~(1<<8); //配置输出低电平
GPIOA_ODR =(1<<8); //配置输出高电平

while(1);
}

void SystemInit (void){

}

举报

相关推荐

0 条评论