LED初始化的汇编代码简析

文章详细描述了在STM32平台中如何使用GPIO控制LED灯,包括开启GPIO外设时钟、设置GPIO引脚模式、速度和初始化操作,以及使用RCC_APB2PeriphClockCmd函数来控制GPIO的启用和禁用。
摘要由CSDN通过智能技术生成
void LED_GPIO_Config(void)
{		
		/*定义一个GPIO_InitTypeDef类型的结构体*/
		GPIO_InitTypeDef GPIO_InitStructure;

		/*开启LED相关的GPIO外设时钟*/
		RCC_APB2PeriphClockCmd( LED1_GPIO_CLK | LED2_GPIO_CLK | LED3_GPIO_CLK, ENABLE);
		/*选择要控制的GPIO引脚*/
		GPIO_InitStructure.GPIO_Pin = LED1_GPIO_PIN;	

		/*设置引脚模式为通用推挽输出*/
		GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;   

		/*设置引脚速率为50MHz */   
		GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; 

		/*调用库函数,初始化GPIO*/
		GPIO_Init(LED1_GPIO_PORT, &GPIO_InitStructure);	
		
		/*选择要控制的GPIO引脚*/
		GPIO_InitStructure.GPIO_Pin = LED2_GPIO_PIN;

		/*调用库函数,初始化GPIO*/
		GPIO_Init(LED2_GPIO_PORT, &GPIO_InitStructure);
		
		/*选择要控制的GPIO引脚*/
		GPIO_InitStructure.GPIO_Pin = LED3_GPIO_PIN;

		/*调用库函数,初始化GPIOF*/
		GPIO_Init(LED3_GPIO_PORT, &GPIO_InitStructure);

		/* 关闭所有led灯	*/
		GPIO_SetBits(LED1_GPIO_PORT, LED1_GPIO_PIN);
		
		/* 关闭所有led灯	*/
		GPIO_SetBits(LED2_GPIO_PORT, LED2_GPIO_PIN);	 
    
    /* 关闭所有led灯	*/
		GPIO_SetBits(LED3_GPIO_PORT, LED3_GPIO_PIN);
}
void RCC_APB2PeriphClockCmd(uint32_t RCC_APB2Periph, FunctionalState NewState)
{
  /* Check the parameters */
  assert_param(IS_RCC_APB2_PERIPH(RCC_APB2Periph));
  assert_param(IS_FUNCTIONAL_STATE(NewState));
  if (NewState != DISABLE)
  {
    RCC->APB2ENR |= RCC_APB2Periph;
  }
  else
  {
    RCC->APB2ENR &= ~RCC_APB2Periph;
  }
}

 

 LED_GPIO_Config
        0x080002c4:    b508        ..      PUSH     {r3,lr}
        0x080002c6:    2101        .!      MOVS     r1,#1
        0x080002c8:    2008        .       MOVS     r0,#8
        0x080002ca:    f000f82f    ../.    BL       RCC_APB2PeriphClockCmd ; 0x800032c
        0x080002ce:    2020                MOVS     r0,#0x20
        0x080002d0:    f8ad0000    ....    STRH     r0,[sp,#0]
        0x080002d4:    2010        .       MOVS     r0,#0x10
        0x080002d6:    f88d0003    ....    STRB     r0,[sp,#3]
        0x080002da:    2003        .       MOVS     r0,#3
        0x080002dc:    f88d0002    ....    STRB     r0,[sp,#2]
        0x080002e0:    4669        iF      MOV      r1,sp
        0x080002e2:    480f        .H      LDR      r0,[pc,#60] ; [0x8000320] = 0x40010c00
        0x080002e4:    f7ffff5e    ..^.    BL       GPIO_Init ; 0x80001a4
        0x080002e8:    2001        .       MOVS     r0,#1
        0x080002ea:    f8ad0000    ....    STRH     r0,[sp,#0]
        0x080002ee:    4669        iF      MOV      r1,sp
        0x080002f0:    480b        .H      LDR      r0,[pc,#44] ; [0x8000320] = 0x40010c00
        0x080002f2:    f7ffff57    ..W.    BL       GPIO_Init ; 0x80001a4
        0x080002f6:    2002        .       MOVS     r0,#2
        0x080002f8:    f8ad0000    ....    STRH     r0,[sp,#0]
        0x080002fc:    4669        iF      MOV      r1,sp
        0x080002fe:    4808        .H      LDR      r0,[pc,#32] ; [0x8000320] = 0x40010c00
        0x08000300:    f7ffff50    ..P.    BL       GPIO_Init ; 0x80001a4
        0x08000304:    2120         !      MOVS     r1,#0x20
        0x08000306:    4806        .H      LDR      r0,[pc,#24] ; [0x8000320] = 0x40010c00
        0x08000308:    f7ffffd7    ....    BL       GPIO_SetBits ; 0x80002ba
        0x0800030c:    2101        .!      MOVS     r1,#1
        0x0800030e:    4804        .H      LDR      r0,[pc,#16] ; [0x8000320] = 0x40010c00
        0x08000310:    f7ffffd3    ....    BL       GPIO_SetBits ; 0x80002ba
        0x08000314:    2102        .!      MOVS     r1,#2
        0x08000316:    4802        .H      LDR      r0,[pc,#8] ; [0x8000320] = 0x40010c00
        0x08000318:    f7ffffcf    ....    BL       GPIO_SetBits ; 0x80002ba
        0x0800031c:    bd08        ..      POP      {r3,pc}

 

RCC_APB2PeriphClockCmd
        0x0800032c:    b129        ).      CBZ      r1,0x800033a ; RCC_APB2PeriphClockCmd + 14
        0x0800032e:    4a06        .J      LDR      r2,[pc,#24] ; [0x8000348] = 0x40021000
        0x08000330:    6992        .i      LDR      r2,[r2,#0x18]
        0x08000332:    4302        .C      ORRS     r2,r2,r0		
        0x08000334:    4b04        .K      LDR      r3,[pc,#16] ; [0x8000348] = 0x40021000
        0x08000336:    619a        .a      STR      r2,[r3,#0x18]
        0x08000338:    e004        ..      B        0x8000344 ; RCC_APB2PeriphClockCmd + 24
        0x0800033a:    4a03        .J      LDR      r2,[pc,#12] ; [0x8000348] = 0x40021000
        0x0800033c:    6992        .i      LDR      r2,[r2,#0x18]
        0x0800033e:    4382        .C      BICS     r2,r2,r0
        0x08000340:    4b01        .K      LDR      r3,[pc,#4] ; [0x8000348] = 0x40021000
        0x08000342:    619a        .a      STR      r2,[r3,#0x18]
        0x08000344:    4770        pG      BX       lr
    $d
        0x08000346:    0000        ..      DCW    0
        0x08000348:    40021000    ...@    DCD    1073876992
    [1]    0x0800032c:    b129        ).      CBZ      r1,0x800033a ; RCC_APB2PeriphClockCmd + 14 //比较R1寄存器的值与0是否相等
    [2]    0x0800032e:    4a06        .J      LDR      r2,[pc,#24] ; [0x8000348] = 0x40021000	//将RCC寄存器的基地址给到R2寄存器
    [3]    0x08000330:    6992        .i      LDR      r2,[r2,#0x18]	//将RCC->APB2ENR寄存器的值给到R2寄存器
    [4]    0x08000332:    4302        .C      ORRS     r2,r2,r0		//将R2寄存器的值与R0寄存器的值做按位或运算后给到R2
    [5]    0x08000334:    4b04        .K      LDR      r3,[pc,#16] ; [0x8000348] = 0x40021000	//将RCC寄存器的值给到R3寄存器
    [6]    0x08000336:    619a        .a      STR      r2,[r3,#0x18]	//将R2寄存器的值,写入到RCC->APB2ENR寄存器中
	
	
	[1]		if (NewState != DISABLE)	因为此时R1寄存器存储的是NewState也就是函数的第二个参数的值
	[2]		RCC->APB2ENR |= RCC_APB2Periph; 首先要获取RCC寄存器的地址也就是
												#define RCC                 ((RCC_TypeDef *) RCC_BASE)
												#define RCC_BASE              (AHBPERIPH_BASE + 0x1000)
												#define AHBPERIPH_BASE        (PERIPH_BASE + 0x20000)
												#define PERIPH_BASE           ((uint32_t)0x40000000)
												0x40021000
											LDR      r2,[pc,#24] 就是将pc+24地址处的内容给到R2寄存器
											此时pc不是0x0800032e,而是指向下一条指令也就是0x08000330
											因此R2的值才是0x8000348地址处的值0x40021000,也就是RCC的值
	[3]		这句话的目的是为了得到RCC->APB2ENR的值,RCC的类型是一个结构体类型,APB2ENR寄存器是偏移24(0x18)
			个字节得到的
	[4] 	最后用R2(RCC->APB2ENR)的值与R0的值做按位或运算,而R0保存的是函数的第一个参数的值,这里第一个
			参数的值在LED_GPIO_Config函数中的RCC_APB2PeriphClockCmd( LED1_GPIO_CLK | LED2_GPIO_CLK | LED3_GPIO_CLK, ENABLE);
			这个函数中赋值了,LED1_GPIO_CLK | LED2_GPIO_CLK | LED3_GPIO_CLK得到的是0x00000008,在做完这个运算后,还要将值给到
			R2寄存器保存,因为这个运算后的值最后要写到RCC->APB2ENR寄存器中,[5][6]句就是做这个事情
	[5]		这里将当前指针寄存器的值加16个字节偏移,再次指到保存RCC寄存器基地址的那个内存处,还是为了得到0x4002100这个
			RCC寄存器的基地址
	[6]		第[5]句得到的RCC地址是为了把R2保存的按位或的值保存在RCC->APB2ENR寄存器中

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值