STM32寄存器操作
寄存器的定义
寄存器是存放指令、数据、地址的地方。不同的寄存器有不同的地址。
1、指令寄存器:暂存当前正在执行的指令。指令寄存器的时钟信号是clk,在clk的上升沿触发。
2、数据寄存器:是计算机控制单元中的寄存器,寄存了将要写入到计算机主存储器(例如:RAM)的数据,或由计算机主存储器读取后的数据。
3、地址寄存器:用来保存当前CPU所访问的内存单元的地址。由于在内存和CPU之间存在着操作速度上的差别,所以必须使用地址寄存器来保持地址信息,直到内存的读/写操作完成为止 。
寄存器操作GPIO
可以把寄存器类比为,有特殊功能的地方,既然是个地方当然就有地址了,所以,可以把寄存器想象为特殊的地址。
STM32的IO口有8中配置方式:
输入:
浮空输入GPIO_IN_FLOATING ——浮空输入,可以做KEY识别,RX1
带上拉输入GPIO_IPU——IO内部上拉电阻输入
带下拉输入GPIO_IPD—— IO内部下拉电阻输入
模拟输入GPIO_AIN ——应用ADC模拟输入,或者低功耗下省电
输出:
开漏输出GPIO_OUT_OD ——IO输出0接GND,IO输出1,悬空,需要外接上拉电阻,才能实现输出高电平。
推挽输出GPIO_OUT_PP ——IO输出0-接GND, IO输出1 -接VCC,读输入值是未知的
复用功能的推挽输出GPIO_AF_PP ——片内外设功能(I2C的SCL,SDA)
复用功能的开漏输出GPIO_AF_OD——片内外设功能(TX1,MOSI,MISO.SCK.SS)
其中这次实验采用的推挽输出:可以输出高、低电平,连接数字器件;推挽结构一般是指两个三极管分别受两个互补信号的控制,总是在一个三极管导通的时候另一个截止。高低电平由IC的电源决定。
点灯
打开GPIO口的时钟
因为我是用的芯片是STM32F103C8T6,所以选择的是GPOA,GPIOB,GPIOC这三个端口。
首先,我们要通过查表来得到所使用的GPIO的地址和时钟的地址
#define RCC_APB2ENR (*(unsigned int *)0x40021018)
// 打开时钟
RCC_APB2ENR |= (1<<3); // 打开 GPIOB 时钟
RCC_APB2ENR |= (1<<4); // 打开 GPIOC 时钟
RCC_APB2ENR |= (1<<2); // 打开 GPIOA 时钟
初始化GPIO口(选择推挽输出)
刚开始我们已经知道GPIO端口有四中输入模式和四中输出模式,这里我们采用的是
推挽式输出,所以我们需要把GPIOA,GPIOB,GPIOC这三个端口设置为推挽式输出。
对于GPIOB的B0、GPIOC的C15、GPIOA的A0,设置如下:
#define GPIOB_CRL (*(unsigned int )0x40010C00)
#define GPIOC_CRH ((unsigned int )0x40011004)
#define GPIOA_CRL ((unsigned int *)0x40010800)
// 配置 GPIO 口为推挽输出
// GPIOB----最后四位为0001
GPIOB_CRL |= (1<<0); // 最后一位变1
GPIOB_CRL &= ~(0xE<<0); // 倒数2、3、4位变0
// GPIOC----前四位为0001
GPIOC_CRH |= (1<<28); // 第四位变1
GPIOC_CRH &= ~(0xE0000000); // 前三位变0
// GPIOA----最后四位为0001
GPIOA_CRL |= (1<<0); // 最后一位变1
GPIOA_CRL &= ~(0xE<<0); // 倒数2、3、4位变0
设置低电平
对于GPIOB的B0、GPIOC的C15、GPIOA的A0,设置如下:
#define GPIOB_ODR (*(unsigned int )0x40010C0C)
#define GPIOC_ODR ((unsigned int )0x4001100C)
#define GPIOA_ODR ((unsigned int *)0x4001080C)
GPIOB_ODR &= ~(1<<0); //最后一位变为0
GPIOC_ODR &= ~(1<<15); //倒数16位变为0
GPIOA_ODR &= ~(1<<0); //最后一位变为
实践操作
keil生成.hex
基本操作除了芯片选择为STM32F1038T6其他可参照[上一篇]进行创建项目(https://blog.youkuaiyun.com/qq_59531651/article/details/120475676)
创建main.c文件
代码:#define GPIOB_BASE 0x40010C00
#define GPIOC_BASE 0x40011000
#define GPIOA_BASE 0x40010800
#define RCC_APB2ENR (*(unsigned int *)0x40021018)
#define GPIOB_CRL (*(unsigned int )0x40010C00)
#define GPIOC_CRH ((unsigned int )0x40011004)
#define GPIOA_CRL ((unsigned int *)0x40010800)
#define GPIOB_ODR (*(unsigned int )0x40010C0C)
#define GPIOC_ODR ((unsigned int )0x4001100C)
#define GPIOA_ODR ((unsigned int *)0x4001080C)
void SystemInit(void);
void Delay_ms(volatile unsigned int);
void Delay_ms( volatile unsigned int t)
{
unsigned int i;
while(t–)
for (i=0;i<800;i++);
}
int main(){
开启时钟:
RCC_APB2ENR |= (1<<3);
RCC_APB2ENR |= (1<<4);
RCC_APB2ENR |= (1<<2);
设置推挽输出
GPIOB_CRL |= (1<<0);
GPIOB_CRL &= ~(0xE);
GPIOC_CRH |= (1<<28);
GPIOC_CRH &= ~(0xE0000000);
GPIOA_CRL |= (1<<0);
GPIOA_CRL &= ~(0xE);
初始化LED为高电位:
GPIOB_ODR |= (1<<0);
GPIOC_ODR |= (1<<15);
GPIOA_ODR |= (1<<0);
点灯,灭灯:
while(1){
GPIOB_ODR &= ~(1<<0);
Delay_ms(1000000);
GPIOB_ODR |= (1<<0);
Delay_ms(1000000);
GPIOC_ODR &= ~(1<<15);
Delay_ms(1000000);
GPIOC_ODR |= (1<<15);
GPIOA_ODR &= ~(1<<0);
Delay_ms(1000000);
GPIOA_ODR |= (1<<0);
Delay_ms(1000000);
}
}
void SystemInit(){
}
代码分析:
添加了延时函数
void Delay_ms( volatile unsigned int t)
{
unsigned int i;
while(t–)
for (i=0;i<800;i++);
}
添加了SystemInit函数:
void SystemInit(void);
int main(){
}
void SystemInit(){
}
将所需要的启动文件复制到项目目录下(f103c8t6启动文件为startup_stm32f10x_md.s
右击文件夹,选择Add Existing Files to Group Source Group 1
选择All FIles,选择刚刚添加的启动文件,Add,Add之后Close。添加之后如图所示。
打开魔术棒,勾选生成.HEX文件
进行编译成功生成.hex文件
电路连接
对于USB转TTL模块和stm32f103c8t6连接
GND — GND
3v3 — 3v3
TXD — A10
RXD — A9
芯片 烧录
1、下载安装STM32串口(flymcu)和串口调试助手
链接:https://pan.baidu.com/s/1E_Xm33R2jh3nVgoYpMh_Mw
提取码:1234
先打开sscom,再打开flymcu
Port选择新生成的com
选择上一步生成的.hex文件
将界面参数调试如下:
检查电路,插入电脑USB端口,点击开始编程,读取器件信息,按下芯片上的按钮。
总结
对寄存器和gpio的推挽输出有了了解,学会了烧录芯片的方法。