硬件状况
DS0灯接线方式
链路:3.3V --- DS0 --- LED0 --- PB5 | --- CPU
分析:
PB5, 为高电平, 那么DS0灯 熄灭
PB5, 为低电平, 那么DS0灯 亮
PB5的配置
配置PB5引脚为输出模式, 输出高电平(灭), 输出低电平(亮),配置为推挽输出
PB5 - GPIOB组控制器对应的第5个引脚,CPU核访问GPIOB控制器内部的寄存器
寻找GPIOB控制器内部的寄存器
寻找寄存器
GPIOx_CRL
GPIOA_CRL
GPIOB_CRL
GPIOC_CRL
GPIOD_CRL
...
GPIO每一组的控制器都会有一个CRL寄存器
寄存器地址 = 控制器首地址 + 寄存器偏移量
控制器首地址 = GPIOB_BASE
寄存器偏移量 = 寄存器说明
总线
st公司将控制器分成3堆,每堆称为一条总线,一共有三条总线
使用的PB5属于GPIO,在APB2这根总线中
//三根总线地址
#define PERIPH_BASE ((unsigned int)0x40000000)//所有控制器的基地址
#define APB1PERIPH_BASE PERIPH_BASE //APB1总线外设的基地址
#define APB2PERIPH_BASE (PERIPH_BASE + 0x10000) //APB2总线外设的基地址
#define AHBPERIPH_BASE (PERIPH_BASE + 0x20000) //AHB总线外设的基地址
#define GPIOA_BASE (APB2PERIPH_BASE + 0x0800) //GPIOA控制器基地址
#define GPIOB_BASE (APB2PERIPH_BASE + 0x0C00) //GPIOB控制器基地址
PB的寄存器位置-GPIOB_CRL
#define GPIOB_CRL (*(unsigned int *)(GPIOB_BASE +0x00))
#define GPIOB_CRH (*(unsigned int *)(GPIOB_BASE +0x04))
#define GPIOB_ODR (*(unsigned int *)(GPIOB_BASE +0x0C))
例如:
GPIOB_CRL
GPIOB_BASE + CRL寄存器的偏移量 = GPIOB_BASE + 0X00
拿到了GPIOB_CRL的首地址
GPIOE_CRL
首地址 = GPIOE_BASE + 0X00
GPIOB_CRL
首地址 = GPIOB_BASE + 0X00
MODE5[1:0] - 描述GPIOB5的模式
[21:20] = 11 配置PB5为输出模式, 最大速度50MHz
CNF5[1:0] - 确定了输入/输出模式, 具体模式选择
[23:22] = 00 推挽输出
配置PB5为推挽输出, 50MHz
输出高低电平-GPIOB_ODR
GPIOB_ODR
首地址 = GPIOB_BASE + 0X0C
ODR5 - GPIOB的第5个引脚
[5] = 0, PB5输出低电平, 亮
= 1, PB5输出高电平, 灭
GPIOB控制器的时钟-RCC_APB2ENR
RCC控制器位于AHB总线
#define PERIPH_BASE ((unsigned int)0x40000000)
#define AHBPERIPH_BASE (PERIPH_BASE + 0x20000)
#define RCC_BASE (AHBPERIPH_BASE + 0x1000)
单灯闪亮代码实现
#include "stm32f10x.h"
void delay(unsigned int i){
while(i--);
}
// @brief SystemInit函数, 防止报错
void SystemInit(void)
{
// ....
}
// @brief main函数, 入口函数
int main(void){
// DS0灯
// 1.打开GPIOB控制器的时钟 [3] = 1
RCC_APB2ENR |= (1 << 3);
// 2.配置GPIOB5为推挽输出, 50MHz
// GPIOB_CRL [23:20] = 0011
GPIOB_CRL &= ~(0XF << 20); // [23:20] = 0000
GPIOB_CRL |= (3 << 20); // [21:20]=11 [23:20] = 0011
while(1){
// 开灯
GPIOB_ODR &= ~(1 << 5);
// 延时
delay(0xfffff);
// 关灯
GPIOB_ODR |= (1 << 5);
// 延时
delay(0xfffff);
}
跑马灯实现
接线
需要将J10接到PE管脚上
接线如图:
代码实现
// main.c
#include "stm32f10x.h"
void delay(unsigned int i){
while(i--);
}
// @brief SystemInit函数, 防止报错
void SystemInit(void)
{
// ....
}
// @brief main函数, 入口函数
int main(void){
// 跑马灯
// 1.打开GPIOE控制器的时钟 [6] = 1
RCC_APB2ENR |= (1 << 6);
// 2.配置GPIOE为推挽输出, 50MHz
// GPIOE_CRL = 0x33333333
GPIOE_CRL &= ~(0xffffffff << 0);
GPIOE_CRL |= (0x33333333 << 0);
while(1){
//从0到7依次循环
for(int i = 0;i<8;i++){
//开灯
GPIOE_ODR &=~(1<<i);
delay(0xf0ff);
//关灯
GPIOE_ODR |=(1<<i);
delay(0xf0ff);
}
}