stm32学习笔记04 寄存器点LED灯

270 阅读5分钟

新建工程(寄存器版)

新建工程——选择芯片型号——不用软件包 从下面路径选择相应的启动文件 拷贝并添加 image.png 添加stm相关的头文件

点亮LED灯

1. 将ODR寄存器的相应引脚输出低电平

通过原理图查看需要输出电平的引脚,此为PB0; 通过参考手册查看数据输出寄存器ODR所代表的引脚的地址和其所挂载的总线的地址; 对地址进行操作。

2. 操作端口配置寄存器CRL

端口配置寄存器分“高寄存器(控制8-15)”和“低寄存器(控制0-7脚)”,每四个位控制一个IO口 从参考手册查看地址和配置模式 对地址进行操作 由于是四个一组,对末位置一则为:

 |= ((1)<<(4*0))

3. 配置APB2外设时钟使能寄存器 RCC_APB2ENR

查看参考手册,需要使IOPBEN位,将其置1; 找到RCC,挂载在AHB总线,以AHB总线为基地址,加上其偏移地址

示例(模仿51编程)

#include"stm32f10x.h"

int main(void)
{
	//配置RCC为GPIOB使能
	*(unsigned int *)(0x40021018)|= (1<<3);

	//配置IO口为输出,控制CRL寄存器
	*(unsigned int *)(0x40010C00)|= ((1)<<(4*0));
	
	//控制ODR寄存器
	*(unsigned int *)(0x40010C0C) &= ~(1<<0);
}

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

C语言中对某一位置0或置1而不改变原来的其他位

PB0输出高电平(置位)

(1<<0):1左移0位
PB0 |= (1<<0);

PB0输出低电平(清零)

PB0 &= ~(1<<0);

SystemInit函数会把系统时钟配置成72M

当该函数体为空,或系统时钟未配置,会使用内部的时钟,HSI 频率为8M

GPIO简介

GPIO和引脚有什么区别:GPIO包含在引脚中,属于引脚的一类

image.png

如何查找每个GPIO的功能

数据手册 —— Pinouts and pin description —— Table 5

GPIO 功能框图

image.png

引脚部分电路,两个二极管进行保护

   1. 电机启动的时候,会有很大的反向电动势和反向电流,I/O引脚如果直接接电机,保护二极管起不了作用,会直接烧坏。
   
   2. 如果开发板要接电机,要隔离,要有M298这种类似的电机驱动模块。

输出驱动器 CRL寄存器控制 控制推挽、开漏或关闭

推挽(用的最多)

推:输出高电平,对外输出(灌电流); 挽:输出低电平,电流向内流(拉电流)。

image.png

由于mos管内阻比较小,所以对内输出电流比较大(对TTL电流而言),可以达到25mA,所以可以点亮LED等

开漏

只能输出低电平,不能输出高电平

输出高电平的话需要外接一个上拉电阻,输出电平电压与外接电压一样

image.png

多用于I2C或SMBUS总线

输出数据寄存器

信号来源是 端口位设置/清除寄存器BSRR,如果操作GPIO可以直接设置ODR

复用功能

复用功能不通过ODR,来自片上外设。 如串口,数据来自 数据寄存器

输入数据寄存器 IDR

低16位有效,接收外部引脚输入的高低电平;

当设置成输出模式的时候,ODR的数据可以从IDR中监控到。

输入模式中,可以通过CRL寄存器,设置成上拉/下拉输入模式。具体是上拉还是下拉,是通过BSRR寄存器软件控制。

TTL肖特基触发器:起到一个门作用,低于1.2V是0,高于2.0V是1。

GPIO的初始化顺序

  1. 选定具体的GPIO
  2. 配置GPIO的工作模式(CRL和CRH寄存器)
  3. 控制GPIO输出高低电平(ODR,BRR和BSRR)

示例:寄存器实现三色等闪烁

头文件:
// 用来存放STM32寄存器映射的代码
//外设 perirhral

# define PERI_BASE        ((unsigned int)0x40000000)
# define APB1_PERI_BASE    PERI_BASE
# define APB2_PERI_BASE   (PERI_BASE + 0X10000)
# define AHB_PERI_BASE    (PERI_BASE + 0X20000)

# define RCC_BASE          (AHB_PERI_BASE + 0X1000)
# define GPIOB_BASE        (APB2_PERI_BASE + 0X0C00)

# define RCC_APB2_ENR      *(unsigned int *)(RCC_BASE + 0x18)
# define GPIOB_CRL         *(unsigned int *)(GPIOB_BASE + 0X00)
# define GPIOB_CRH         *(unsigned int *)(GPIOB_BASE + 0x04)
# define GPIOB_ODR         *(unsigned int *)(GPIOB_BASE + 0x0C)
实现:
#include"stm32f10x.h"

//使用寄存器的写法,三色灯闪烁
void Delay(unsigned int count);
int main(void)
{
	//定好三条总线的基地址(AHB总线的基地址为了方便人为定义为0x40020000)
	//配置RCC为GPIOB使能
	RCC_APB2_ENR |= (1<<3);
	//配置IO口为输出,控制CRL寄存器 Green
	GPIOB_CRL &= ~((0x0f)<<(4*0));//严谨起见置1前先清零,因为是4位数字表状态
	GPIOB_CRL |= ((1)<<(4*0));
	//配置IO口为输出,控制CRL寄存器 Blue
	GPIOB_CRL &= ~((0x0f)<<(4*1));//严谨起见置1前先清零,因为是4位数字表状态
	GPIOB_CRL |= ((1)<<(4*1));
	//配置IO口为输出,控制CRL寄存器 Red
	GPIOB_CRL &= ~((0x0f)<<(4*5));//严谨起见置1前先清零,因为是4位数字表状态
	GPIOB_CRL |= ((1)<<(4*5));	
	while(1)
{
	//控制ODR寄存器
	GPIOB_ODR &= ~(1<<0);
	//延迟一段时间
	Delay(300000);
	GPIOB_ODR |= (1<<0);
	GPIOB_ODR &= ~(1<<1);	
	//延迟一段时间
	Delay(300000);
	GPIOB_ODR |= (1<<1);
	GPIOB_ODR &= ~(1<<5);
	//延迟一段时间
	Delay(300000);
	GPIOB_ODR |= (1<<5);

}
}
void Delay(unsigned int count)
{
	for(; count !=0 ; count --);
}
void SystemInit(void)
{
	//函数体为空,不实现,目的是为了骗过编译器不报错
}