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寄存器中