STM32F103寄存器方式点亮LED流水灯

一、地址映射和寄存器映射

1.1 总线基地址

总线名称总线基地址相对外设基地址的偏移
APB10x4000 00000x0
APB20x4001 00000x0001 0000
AHB0x4001 80000x0001 8000

1.2 外设基地址

外设名称外设基地址相对 APB2 总线的地址偏移
GPIOA0x4001 08000x0000 0800
GPIOB0x4001 0C000x0001 0000
GPIOC0x4001 10000x0001 8000
GPIOD0x4001 14000x0000 1400
GPIOE0x4001 18000x0000 1800
GPIOF0x4001 1C000x0000 1C00
GPIOG0x4001 20000x0000 2000

1.3 外设寄存器地址

在这里插入图片描述在这里插入图片描述在这里插入图片描述
在这里插入图片描述stm32最小板仅有ABC三个引脚系列。0-7位为CRL,8-15位为CRH,相对基址的偏移即从基址开始多少十六进制后是此寄存器地址的开始,不同的寄存器有不同的地址,需要去访问该地址,就需要查表。

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述时钟寄存器在APB2线
在这里插入图片描述因此后续代码都是0x00000002对应的是0010
在这里插入图片描述高位同理。

二、搭建电路

2.1 接线

(1)将串口USB转TTL线与stm32核心板连接如图所示

在这里插入图片描述
(2)BOOT0 与 BOOT1 配置启动方式
在这里插入图片描述
在这里插入图片描述
(3) 程序下载
在这里插入图片描述
(4)实际连线图
在这里插入图片描述

2.2 用C语言寄存器实现流水灯

(1) main.c

#define RCC_AP2ENR	*((unsigned volatile int*)0x40021018)
	//----------------GPIOA配置寄存器 ------------------------
#define GPIOA_CRH	*((unsigned volatile int*)0x40010804)
#define	GPIOA_ORD	*((unsigned volatile int*)0x4001080C)
//----------------GPIOB配置寄存器 ------------------------
#define GPIOB_CRL	*((unsigned volatile int*)0x40010C00)
#define	GPIOB_ORD	*((unsigned volatile int*)0x40010C0C)
//----------------GPIOC配置寄存器 ------------------------
#define GPIOC_CRH	*((unsigned volatile int*)0x40011004)
#define	GPIOC_ORD	*((unsigned volatile int*)0x4001100C)
//-------------------简单的延时函数-----------------------
void  Delay_ms( volatile  unsigned  int  t)
{
     unsigned  int  i;
     while(t--)
         for (i=0;i<800;i++);
}
//------------------------主函数--------------------------
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_CRH&=0xFFF0FFFF;		//设置位 清零	
	GPIOA_CRH|=0x00020000;		//PA12推挽输出
	GPIOA_ORD|=1<<12;			//设置初始灯为亮
	
	GPIOB_CRL&=0xFFFFFF0F;		//设置位 清零	
	GPIOB_CRL|=0x00000020;		//PB1推挽输出
	GPIOB_ORD|=1<<1;			//设置初始灯为灭
	
	GPIOC_CRH&=0xF0FFFFFF;		//设置位 清零
	GPIOC_CRH|=0x02000000;   	//PC14推挽输出
	GPIOC_ORD|=1<<14;			//设置初始灯为灭	
	while(j)
	{	
		GPIOA_ORD=0x1<<12;		//PA12高电平	
		Delay_ms(3000000);
		GPIOA_ORD=0x0<<12;		//PA12低电平
		Delay_ms(3000000);
		
		GPIOB_ORD=0x1<<1;		//PB1高电平	
		Delay_ms(3000000);
		GPIOB_ORD=0x0<<1;		//PB1低电平
		Delay_ms(3000000);
		
		GPIOC_ORD=0x1<<14;		//PC14高电平	
		Delay_ms(3000000);
		GPIOC_ORD=0x0<<14;		//PC14低电平
		Delay_ms(3000000);
	}
}

使用高电平点亮低电平熄灭

(2)接入设备
在这里插入图片描述(3)编译生成hex文件

在这里插入图片描述
(4)用mcuisp烧入stm32如·2.1(3)
在这里插入图片描述

2.3 汇编语言实现流水灯

(1)汇编代码

RCC_APB2ENR EQU 0x40021018
 
GPIOA_CRH EQU   0x40010804
GPIOA_ODR EQU   0x4001080C
                                    
GPIOB_CRL EQU   0x40010C00    ;寄存器映射
GPIOB_ODR EQU   0x40010C0C	
	
GPIOC_CRH EQU   0x40011004
GPIOC_ODR EQU   0x4001100C	
	
	
Stack_Size      EQU     0x00000400
 
                AREA    STACK, NOINIT, READWRITE, ALIGN=3
					;NOINIT: = NO Init,不初始化。READWRITE : 可读,可写。ALIGN =3 : 2^3 对齐,即8字节对齐。
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 
		
                
MainLoop		BL LED2_Init
                BL LED2_ON
                BL Delay             ;LED2灯闪烁
                BL LED2_OFF
                BL Delay
				
				BL LED1_Init				
				BL LED1_ON
                BL Delay             ;LED1灯闪烁
                BL LED1_OFF
                BL Delay
				
                BL LED3_Init				
				BL LED3_ON
                BL Delay            ;LED3灯闪烁
                BL LED3_OFF
                BL Delay
				
                B MainLoop
				
             
LED1_Init
                PUSH {R0,R1, LR}        ;R0,R1,LR中的值放入堆栈
                
                LDR R0,=RCC_APB2ENR      ;LDR是把地址装载到寄存器中(比如R0)。
                ORR R0,R0,#0x08         ;开启端口GPIOB的时钟,ORR 按位或操作,01000将R0的第二位置1,其他位不变		
                LDR R1,=RCC_APB2ENR
                STR R0,[R1]             ;STR是把值存储到寄存器所指的地址中,将r0里存储的值给rcc寄存器
				;上面一部分汇编代码是控制时钟的
                
                
                LDR R0,=GPIOB_CRL
                ORR R0,R0,#0X00000020   ;GPIOB_Pin_1配置为通用推挽输出;开启的是pb1,所以是2,为0010,是推挽输出模式,最大速度为2mhz
                LDR R1,=GPIOB_CRL
                STR R0,[R1]
                
                LDR R0,=GPIOB_ODR   
                BIC R0,R0,#0X00000002      ;BIC 先把立即数取反,再按位与
                LDR R1,=GPIOB_ODR          ;GPIO_Pin_1输出为0;由r1控制ord寄存器
                STR R0,[R1]                 ;将ord寄存器的值变为r0的值
             
                POP {R0,R1,PC}             ;将栈中之前存的R0,R1,LR的值返还给R0,R1,PC
 
 
             
LED1_OFF
                PUSH {R0,R1, LR}    
                
                LDR R0,=GPIOB_ODR
                BIC R0,R0,#0X00000002    ;因为是pb1所以对应二进制0010;GPIO_Pin_1输出为0,LED1熄灭
			    LDR R1,=GPIOB_ODR
                STR R0,[R1]
             
                POP {R0,R1,PC}
             
LED1_ON
                PUSH {R0,R1, LR}    
                
                 LDR R0,=GPIOB_ODR
                ORR R0,R0,#0X00000002    ;GPIO_Pin_1输出为1,LED1亮
                 LDR R1,=GPIOB_ODR
                STR R0,[R1]
                POP {R0,R1,PC}           
 
 
				
 
LED2_Init
                PUSH {R0,R1, LR};R0,R1,LR中的值放入堆栈
                
                LDR R0,=RCC_APB2ENR
                ORR R0,R0,#0x04		   ;打开GPIOA的时钟
                LDR R1,=RCC_APB2ENR
                STR R0,[R1]                
                
                LDR R0,=GPIOA_CRH
                ORR R0,R0,#0X00020000   ;GPIOA_Pin_12配置为通用推挽输出
                LDR R1,=GPIOA_CRH
                STR R0,[R1]
                
                LDR R0,=GPIOA_ODR
                BIC R0,R0,#0X00001000   
                LDR R1,=GPIOA_ODR            ;GPIOA_Pin_12输出为0
                STR R0,[R1]
             
                POP {R0,R1,PC}
				
LED2_OFF
                PUSH {R0,R1, LR}   
                
               LDR R0,=GPIOA_ODR
               BIC R0,R0,#0X00001000        ;GPIOA_Pin_12输出为0,LED2熄灭
			    LDR R1,=GPIOA_ODR
                STR R0,[R1]
             
                POP {R0,R1,PC}
             
LED2_ON
                PUSH {R0,R1, LR}    
                
                LDR R0,=GPIOA_ODR
                ORR R0,R0,#0X00001000     ;GPIOA_Pin_12输出为1,LED2亮
				 LDR R1,=GPIOA_ODR
                STR R0,[R1]
				
				 POP {R0,R1,PC}
				 
 
LED3_Init
                PUSH {R0,R1, LR}
                
                LDR R0,=RCC_APB2ENR
                ORR R0,R0,#0x10		    ;打开GPIOC的时钟
                LDR R1,=RCC_APB2ENR
                STR R0,[R1]                
                
                LDR R0,=GPIOC_CRH
                ORR R0,R0,#0X02000000   ;GPIOC_Pin_14配置为通用推挽输出
                LDR R1,=GPIOC_CRH
                STR R0,[R1]
                
                LDR R0,=GPIOC_ODR
                BIC R0,R0,#0X00004000   ;GPIOC_Pin_14输出为0
                LDR R1,=GPIOC_ODR
                STR R0,[R1]
             
                POP {R0,R1,PC}
             
LED3_OFF
                PUSH {R0,R1, LR}    
                
                LDR R0,=GPIOC_ODR
                BIC R0,R0,#0X00004000  ;GPIOC_Pin_14输出为0,LED3熄灭
			    LDR R1,=GPIOC_ODR
                STR R0,[R1]
             
                POP {R0,R1,PC}
             
LED3_ON
                PUSH {R0,R1, LR}    
                
                 LDR R0,=GPIOC_ODR
                ORR R0,R0,#0X00004000   ;GPIOC_Pin_14输出为1,LED3亮
                 LDR R1,=GPIOC_ODR
                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,#300
                BCC DelayLoop0
                
                MOVS R0,#0
                ADDS R1,R1,#1
                CMP R1,#300
                BCC DelayLoop0
 
                MOVS R0,#0
                MOVS R1,#0
                ADDS R2,R2,#1
                CMP R2,#15
                BCC DelayLoop0
                
                POP {R0,R1,PC}    
 
                END

(2)添加工程文件
在这里插入图片描述(3)进行编译生成hex文件

在这里插入图片描述
(4)烧录程序
在这里插入图片描述(5)结果
在这里插入图片描述

三、总结

通过查阅资料与请教,慢慢的理解了stm32的工作原理,以及串行口的转换关系,基本掌握了软硬件结合的实验,实验过程与原理清晰容易理解的。

参考文献
STM32寄存器的简介、地址查找,与直接操作寄存器
STM32从地址到寄存器
STM32F103寄存器方式点亮LED流水灯

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值