一、寄存器简介
寄存器,根据百度百科介绍,寄存器是中央处理器内的组成部分。寄存器是有限存贮容量的高速存贮部件,它们可用来暂存指令、数据和地址。
通俗的讲,寄存器就是存放东西的。存放的东西不过是由我们客观上的东西变为了指令、数据或地址。
GPIO
简介
GPIO(General-Purpose IO ports),也就是通用输入输出口。一个GPIO端口至少需要两个寄存器,一个做控制用的“通用IO端口控制寄存器”,还有一个是存放数据的“通用I/O端口数据寄存器”。数据寄存器的每一位是和GPIO的硬件引脚对应的,而数据的传递方向是通过控制寄存器设置的,通过控制寄存器可以设置每一位引脚的数据流向。

GPIO的工作模式
1、浮空输入GPIO_IN_FLOATING ——浮空输入,可以做KEY识别,RX1 2、带上拉输入GPIO_IPU——IO内部上拉电阻输入
3、带下拉输入GPIO_IPD—— IO内部下拉电阻输入
4、模拟输入GPIO_AIN ——应用ADC模拟输入,或者低功耗下省电
5、开漏输出GPIO_OUT_OD ——IO输出0接GND,IO输出1,悬空,需要外接上拉电阻,才能实现输出高电平。当输出为1时,IO口的状态由上拉电阻拉高电平,但由于是开漏输出模式,这样IO口也就可以由外部电路改变为低电平或不变。可以读IO输入电平变化,实现C51的IO双向功能
6、推挽输出GPIO_OUT_PP ——IO输出0-接GND, IO输出1 -接VCC,读输入值是未知的
7、复用功能的推挽输出GPIO_AF_PP ——片内外设功能(I2C的SCL,SDA)
8、复用功能的开漏输出GPIO_AF_OD——片内外设功能(TX1,MOSI,MISO.SCK.SS)
二、汇编语言点亮LED灯
LED0 EQU 0x42218194
RCC_APB2ENR EQU 0x40021018
;GPIOA_CRH EQU 0x40010804
GPIOB_CRL EQU 0x40010C00
Stack_Size EQU 0x00000400
AREA STACK, NOINIT, READWRITE, ALIGN=3
Stack_Mem SPACE Stack_Size
__initial_sp
AREA RESET, DATA, READONLY
__Vectors DCD __initial_sp
DCD Reset_Handler
AREA |.text|, CODE, READONLY
THUMB
REQUIRE8
PRESERVE8
ENTRY
Reset_Handler
BL LED_Init
MainLoop BL LED_ON
BL Delay
BL LED_OFF
BL Delay
B MainLoop
LED_Init
PUSH {R0,R1, LR}
LDR R0,=RCC_APB2ENR
ORR R0,R0,#0x08
LDR R1,=RCC_APB2ENR
STR R0,[R1]
LDR R0,=GPIOB_CRL
BIC R0,R0,#0XFF0FFFFF
LDR R1,=GPIOB_CRL
STR R0,[R1]
LDR R0,=GPIOB_CRL
ORR R0,R0,#0X00300000
LDR R1,=GPIOB_CRL
STR R0,[R1]
MOV R0,#1
LDR R1,=LED0
STR R0,[R1]
POP {R0,R1,PC}
LED_ON
PUSH {R0,R1, LR}
MOV R0,#0
LDR R1,=LED0
STR R0,[R1]
POP {R0,R1,PC}
LED_OFF
PUSH {R0,R1, LR}
MOV R0,#1
LDR R1,=LED0
STR R0,[R1]
POP {R0,R1,PC}
Delay
PUSH {R0,R1, LR}
MOVS R0,#0
MOVS R1,#0
MOVS R2,#0
DelayLoop0
ADDS R0,R0,#1
CMP R0,#330
BCC DelayLoop0
MOVS R0,#0
ADDS R1,R1,#1
CMP R1,#330
BCC DelayLoop0
MOVS R0,#0
MOVS R1,#0
ADDS R2,R2,#1
CMP R2,#15
BCC DelayLoop0
POP {R0,R1,PC}
END
三、C语言点亮LED灯
延时函数Delay.h
void Delay()
{
unsigned int i;
while(t--)
for (i=0;i<10000000;i++);
}
点灯函数Light.h
//A灯
void A_LED(){
GPIOA_ORD=0x0<<5; //PA5低电平
GPIOB_ORD=0x1<<6; //PB6高电平
GPIOC_ORD=0x1<<7; //PC7高电平
}
//B灯
void B_LED(){
GPIOA_ORD=0x1<<5; //PA5高电平
GPIOB_ORD=0x0<<6; //PB6低电平
GPIOC_ORD=0x1<<7; //PC7高电平
}
//C灯
void C_LED(){
GPIOA_ORD=0x1<<5; //PA5高电平
GPIOB_ORD=0x1<<6; //PB6高电平
GPIOC_ORD=0x0<<7; //PC7低电平
}
主函数
#include"Delay.h"
#include"Light.h"
#define RCC_AP2ENR *((unsigned volatile int*)0x40021018)//APB2使能时钟寄存器
#define GPIOA_CRL *((unsigned volatile int*)0x40010800)//配置GPIOA寄存器
#define GPIOA_ORD *((unsigned volatile int*)0x4001080C)
#define GPIOB_CRH *((unsigned volatile int*)0x40010C04)//配置GPIOB寄存器
#define GPIOB_ORD *((unsigned volatile int*)0x40010C0C)
#define GPIOC_CRH *((unsigned volatile int*)0x40011004)//GPIOC配置寄存器
#define GPIOC_ORD *((unsigned volatile int*)0x4001100C)
//主函数
int main()
{
int j=100;
RCC_AP2ENR|=1<<2; //APB2-GPIOA外设时钟使能
RCC_AP2ENR|=1<<3; //APB2-GPIOB外设时钟使能
RCC_AP2ENR|=1<<4; //APB2-GPIOC外设时钟使能
//这两行代码可以合为 RCC_APB2ENR|=1<<3|1<<4;
GPIOA_CRL&=0x0FFFFFFF; //设置位 清零
GPIOA_CRL|=0x20000000; //PA7推挽输出
GPIOA_ORD|=1<<5; //设置PA5初始灯为灭
GPIOB_CRH&=0xFFFFFF0F; //设置位 清零
GPIOB_CRH|=0x00000020; //PB6推挽输出
GPIOB_ORD|=1<<6; //设置初始灯为灭
GPIOC_CRH&=0x0FFFFFFF; //设置位 清零
GPIOC_CRH|=0x30000000; //PC7推挽输出
GPIOC_ORD|=0x1<<7; //设置初始灯为灭
while(j)
{
A_LED();
Delay();
B_LED();
Delay();
C_LED();
Delay();
}
}
编译构建后生成.HEX文件,创建工程及后续操作可参考笔者以前的博客
Keil5 MDK版的STM32工程创建
烧录程序
可以用Keil5直接烧录,也可用FlyMcu烧录。
- 打开程序,点击三个小圆点,导入生成的.HEX文件

- 读取器件信息

- 开始编程

四、构建实物
连线过程自行操作,由于编者搭线时未拍照,具体过程可上网查阅。
连线实物图

- 运行结果

五、小结
对于用STM32来开发一些简单功能的东西总体来说还是不难的,但是由于笔者是第一次用硬件左开发,对很多东西都不太理解,可以说是边做边学吧。我现在更加相信 “世上无难事,只要肯攀登” 了。
这篇博客介绍了如何通过STM32F103的寄存器操作来点亮LED流水灯,涵盖了寄存器基础知识、GPIO工作模式,以及使用汇编和C语言的具体实现步骤,包括延时函数和主函数的编写,并提到了程序的编译、烧录和实物构建的过程。
5378

被折叠的 条评论
为什么被折叠?



