编程步骤:

•   首先要开GPIO端口时钟(RCC AHB1 外设时钟使能寄存器 (RCC_AHB1ENR))
•   要先确定引脚号
•   要确定是输入还是输出
•   如果是输出,那么是推挽还是开漏输出 OTYPER
•   确定是上拉还是下拉
•   那么输出速度是多少呢?

配置IO(LED):

void GPIO_LED_Config(void)
{ 
    GPIO_InitTypeDef GPIO_InitStruct;

    //打开LED_GPIO的时钟
    RCC_AHB1PeriphClockCmd(LED_R_GPIO_CLK,ENABLE);
    //选定LED_GPIO,就是具体的引脚
    GPIO_InitStruct.GPIO_Pin=LED_R_GPIO_PIN;
    //配置输出
    GPIO_InitStruct.GPIO_Mode=GPIO_Mode_OUT;
    //配置推挽输出
       GPIO_InitStruct.GPIO_OType=GPIO_OType_PP;
    //配置上拉
    GPIO_InitStruct.GPIO_PuPd=GPIO_PuPd_UP;
    //配置输出速度
    GPIO_InitStruct.GPIO_Speed=GPIO_Fast_Speed;
    //初始化LED_GPIO口
    GPIO_Init(LED_R_GPIO_PORT,&GPIO_InitStruct);
}

可避免文件在多个文件中重复定义

#ifndef _BSP_KEY_H
#define _BSP_KEY_H
//代码编写部分
#endif /*_BSP_KEY_H*/

配置IO(按键检测):

void  Key_GPIO_Config(void)
{
    GPIO_InitTypeDef GPIO_InitStruct;

    //打开KEY_GPIO的时钟
    RCC_AHB1PeriphClockCmd(KEY1_GPIO_CLK,ENABLE);

    //选定KEY_GPIO,就是具体的引脚
    GPIO_InitStruct.GPIO_Pin=KEY1_GPIO_PIN;

    //配置输入模式
    GPIO_InitStruct.GPIO_Mode=GPIO_Mode_IN;

    //配置下拉
    GPIO_InitStruct.GPIO_PuPd=GPIO_PuPd_DOWN;

  //初始化GPIO口
    GPIO_Init(KEY1_GPIO_PORT,&GPIO_InitStruct);
}

位带操作:(AHB2和AHB3不能实现位带操作(不在范围内))

SRAM和片上外设均有1MB的位带区,位带区里面的每一个位都可以通过位带别名区的地址来访问。位带区一位,对
    应位带别名区的四个字节。

SRAM位带区地址        0X2000 0000~0X200F 0000
SRAM位带别名区地址    0X2000 0000~0X23FF FFFF

外设位带区与外设位带别名区的地址转换:

AliasAddr=0X4200 0000+(A-0X4000 0000)*8*4+n*4
SRAM位带区和SRAM位带别名区的地址转换:
AliasAddr=0X2200 0000+(A-0X2000 0000)*8*4+n*4

A:表示我们要操作的那个位所在的寄存器的地址
n:位号
要点:位带区的一个位在位带别名区会被膨胀成四字节

外设与SRAM位带区与位带别名区的地址转换:

统一地址:((addr&0XF000 0000)+0x0200 0000+((addr&0x000F FFFF)<<5)+(bitnum<<2))
addr:要操作的位所在寄存器的地址
bitnum:位号

启动文件作用:

1-   初始化堆栈指针SP(SP=_initial_sp)
2-   初始化PC指针,指向复位程序(初始化PC 指针=Reset_Handler)
3-   初始化中断向量表
4-   配置系统时钟(SystemInit()函数配置时钟)
5-   调用C 库函数_main 初始化用户堆栈,从而最终调用main 函数去到C 的世界(第一个启动的是__main函数)

向量表:

1.     向量表实际是一个32位的整型数组,一个元素对应一个异常(ESR),数组元素存的就是ESR的入口地址。
2.     向量表在复位后从FLASH的0地址(存储器重映射)开始。

Stack栈:

用于局部(全局)变量、函数调用、函数形参的开销

Heap堆:

堆用于动态内存的分配,malloc函数