一、观察结构图
基于以上的外设图我们明白操作LED灯需要用到RCC(时钟)与GPIO两个外设,因此我们需要对两个外设进行使能
二、
选择库函数
对于RCC外设函数来说,库函数琳琅满目,但是对于初学者来说,三个函数即可:
void RCC_AHBPeriphClockCmd(uint32_t RCC_AHBPeriph, FunctionalState NewState);
void RCC_APB2PeriphClockCmd(uint32_t RCC_APB2Periph, FunctionalState NewState);
void RCC_APB1PeriphClockCmd(uint32_t RCC_APB1Periph, FunctionalState NewState);
对于GPIO外设函数我们需要学习的较多,主要是以下几种:
void GPIO_DeInit(GPIO_TypeDef* GPIOx);//复位GPIO外设
void GPIO_AFIODeInit(void);//复位AFIO外设
void GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct);//GPIO外设初始化
void GPIO_StructInit(GPIO_InitTypeDef* GPIO_InitStruct);//将GPIO结构体变量赋一个默认值
uint8_t GPIO_ReadInputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
uint16_t GPIO_ReadInputData(GPIO_TypeDef* GPIOx);
uint8_t GPIO_ReadOutputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
uint16_t GPIO_ReadOutputData(GPIO_TypeDef* GPIOx);//以上四行代码是GPIO读取函数
void GPIO_SetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
void GPIO_ResetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
void GPIO_WriteBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, BitAction BitVal);
void GPIO_Write(GPIO_TypeDef* GPIOx, uint16_t PortVal);//以上代码是GPIO写入函数
三、分析原理图
由于我是使用了野火stm32霸道的板子,采用的是f103zet6的芯片,因此将原理图LED部分附下:
可以看到红灯接在PB5上,绿灯接在PB0上,蓝灯接在PB1上。
四、开始代码
1、由以上两幅图可以看出LED等挂载在GPIO口并连接在APB2总线上,因此我们先对APB2时钟进行使能,采用void RCC_APB2PeriphClockCmd(uint32_t RCC_APB2Periph, FunctionalState NewState)函数,通过观察发现该函数具有两个参数,分别填写具体的外设名与是否使能,并将其填入函数中如下(以点亮蓝灯为例):
void RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
2、对GPIO外设进行初始化
选用
void GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct);
分析参数可知需要填入具体的GPIOA~GPIOG之间的一个外设,我们这里选GPIOB,另一个参数是结构体较复杂一些这要求我们在使用这个结构体时,在使用的时候我们需要先引用这个结构体。
GPIO_InitTypeDef GPIO_InitStructure;
看到这样的一行代码可能有很多同学感到疑惑,现在我来解释一下结构体以及关键字typedef的用法。所谓typedef关键字的用法就是重命名,我们先打开头文件gpio.h,可以找到如下一段代码:
可以看到,整个结构体都被typedef更改名字成了GPIO_InitTypedef,因此在我们引用这个结构体的 时候只需用GPIO_InitTypedef加上一个结构体变量(这里我们定义为GPIO_InitStructure)。
这样引用就完成了。然后我们通过结构体变量名用.运算符将结构体成员引出来分别配置
#include "stm32f10x.h" // Device header
int main()
{
GPIO_InitTypeDef GPIO_InitStructure;//声明结构体并定义结构体变量
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;//配置成推挽输出模式
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_1;//由原理图配置PB1口
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;//速度一般设置成50MHZ即可
GPIO_Init(GPIOB, &GPIO_InitStructure);//对GPIO进行初始化
while(1)
{
}
}
上面就是对GPIO完整的初始化过程
然后我们就可以使用GPIO的输入输出函数了。
首先介绍void GPIO_ResetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);函数,它的功能是清除选定的数据端口位,即将指定的端口位置零
配置如下:
GPIO_ResetBits(GPIOB,GPIO_Pin_1);
完整代码如下
#include "stm32f10x.h" // Device header
int main()
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); //开启GPIOA的时钟
GPIO_InitTypeDef GPIO_InitStructure;//声明结构体并定义结构体变量
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;//配置成推挽输出模式
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_1;//由原理图配置PB1口
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;//速度一般设置成50MHZ即可
GPIO_Init(GPIOB, &GPIO_InitStructure);//对GPIO进行初始化
GPIO_ResetBits(GPIOB,GPIO_Pin_1);
while(1)
{
}
}
程序现象如下: