新建工程(寄存器版)
新建工程——选择芯片型号——不用软件包
从下面路径选择相应的启动文件 拷贝并添加
添加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包含在引脚中,属于引脚的一类
如何查找每个GPIO的功能
数据手册 —— Pinouts and pin description —— Table 5
GPIO 功能框图
引脚部分电路,两个二极管进行保护
1. 电机启动的时候,会有很大的反向电动势和反向电流,I/O引脚如果直接接电机,保护二极管起不了作用,会直接烧坏。
2. 如果开发板要接电机,要隔离,要有M298这种类似的电机驱动模块。
输出驱动器 CRL寄存器控制 控制推挽、开漏或关闭
推挽(用的最多)
推:输出高电平,对外输出(灌电流); 挽:输出低电平,电流向内流(拉电流)。
由于mos管内阻比较小,所以对内输出电流比较大(对TTL电流而言),可以达到25mA,所以可以点亮LED等
开漏
只能输出低电平,不能输出高电平
输出高电平的话需要外接一个上拉电阻,输出电平电压与外接电压一样
多用于I2C或SMBUS总线
输出数据寄存器
信号来源是 端口位设置/清除寄存器BSRR,如果操作GPIO可以直接设置ODR
复用功能
复用功能不通过ODR,来自片上外设。 如串口,数据来自 数据寄存器
输入数据寄存器 IDR
低16位有效,接收外部引脚输入的高低电平;
当设置成输出模式的时候,ODR的数据可以从IDR中监控到。
输入模式中,可以通过CRL寄存器,设置成上拉/下拉输入模式。具体是上拉还是下拉,是通过BSRR寄存器软件控制。
TTL肖特基触发器:起到一个门作用,低于1.2V是0,高于2.0V是1。
GPIO的初始化顺序
- 选定具体的GPIO
- 配置GPIO的工作模式(CRL和CRH寄存器)
- 控制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)
{
//函数体为空,不实现,目的是为了骗过编译器不报错
}