描述文本。
STM32的引脚叫GPIO(General-purpose input/output,通用型输入输出),功能类似8051的P0—P3
其接脚可以供使用者由程控自由使用,有8种输入输出模式(或者参考这个)
这些模式的电流输入输出能力不同,还有的具有额外的功能(比如AD)转换,这个根据具体应用场景具体选择一个
void GPIO_Config(void) //GPIO初始配置 { GPIO_InitTypeDef GPIO_InitStructure;//定义结构体变量 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD, ENABLE); //使能GPIOD的时钟 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13; //指定引脚13 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //设置输出速率50MHz GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出模式 GPIO_Init(GPIOD, &GPIO_InitStructure); //初始化外设GPIOx寄存器 }
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD, ENABLE);
这句话比较长,我们首先来逐个的分解一下其中的含义
这句话的意思是开启外设时钟,具体原因参见此链接
为了节省资源,STM32所有的时钟都是默认关闭的,因此要使用某个外设时,需要打开对应的时钟
GPIO_SetBits(GPIOD, GPIO_Pin_13)
主程序如下
int main(void) { Stm32_Clock_Init(9); delay_init(72); LED_Init(); while(1) { LED0=0; LED1=1; delay_ms(300); LED0=1; LED1=0; delay_ms(300); } }
其中的LED初始化的程序如下
void LED_Init(void) { RCC->APB2ENR|=1<<3; //使能PORTB时钟 RCC->APB2ENR|=1<<6; //使能PORTE时钟 GPIOB->CRL&=0XFF0FFFFF; GPIOB->CRL|=0X00300000; //PB.5 推挽输出 GPIOB->ODR|=1<<5; //PB.5 输出高 GPIOE->CRL&=0XFF0FFFFF; GPIOE->CRL|=0X00300000; //PE.5推挽输出 GPIOE->ODR|=1<<5; //PE.5输出高 }
首先对前两句进行分析
RCC->APB2ENR|=1<<3; //使能PORTB时钟 RCC->APB2ENR|=1<<6; //使能PORTE时钟
第一句的意思是把RCC的APB2ENR寄存器的第3位(从0开始计位)变为1
APB2ENR寄存器的第2-8位分别对应着ABCDEFG端口
APB2ENR是APB2 enable register,APB2总线的使能寄存器,所有的通用接口都有APB2总线负责
具体的RCC结构的定义如下所示。
//stdint.h typedef unsigned int uint32_t; #define __IO volatile //stm32f10x.h #define PERIPH_BASE ((uint32_t)0x40000000) #define AHBPERIPH_BASE (PERIPH_BASE + 0x20000) #define RCC_BASE (AHBPERIPH_BASE + 0x1000) #define RCC ((RCC_TypeDef *) RCC_BASE) typedef struct { __IO uint32_t CR; __IO uint32_t CFGR; __IO uint32_t CIR; __IO uint32_t APB2RSTR; __IO uint32_t APB1RSTR; __IO uint32_t AHBENR; } RCC_TypeDef;
接下来是对GPIO通用输入输出接口的配置
GPIOB->CRL&=0XFF0FFFFF; GPIOB->CRL|=0X00300000; //PB.5 推挽输出 GPIOB->ODR|=1<<5; //PB.5 输出高前两句是对GPIOB的CRL寄存器进行配置,具体是把PB5的配置位变为 3
3的二进制是0010,后两位是端口模式MODE,10表示2Mhz输出模式;前两位是端口配置位CNF,00,表示通用推挽输出模式
后一句是对GPIOB的ODR寄存器进行配置,把代表PB5的第5位写位高电平
//test.c LED = 0; //led.h #define LED0 PBout(5) // DS0 //sys.h #define PBout(n) BIT_ADDR(GPIOB_ODR_Addr,n) //Êä³ö #define BIT_ADDR(addr, bitnum) MEM_ADDR(BITBAND(addr, bitnum)) #define MEM_ADDR(addr) *((volatile unsigned long *)(addr)) #define BITBAND(addr, bitnum) ((addr & 0xF0000000)+0x2000000+((addr &0xFFFFF)<<5)+(bitnum<<2)) #define GPIOB_ODR_Addr (GPIOB_BASE+12) //0x40010C0C //stm32f10x.h #define GPIOB_BASE (APB2PERIPH_BASE + 0x0C00) #define APB2PERIPH_BASE (PERIPH_BASE + 0x10000) #define PERIPH_BASE ((uint32_t)0x40000000)
程序里面有bitband的定义,这个名字直译就是比特段,https://wenku.baidu.com/view/16645b5702f69e3143323968011ca300a6c3f6db.html
文件夹的架构如下