※LED灯初始化
一、Led_Init
void LED_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOC,ENABLE);
GPIO_InitStructure.GPIO_Pin =GPIO_Pin_13;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOC, &GPIO_InitStructure);
}
1. GPIO_InitTypeDef GPIO_InitStructure;
typedef struct
{
uint16_t GPIO_Pin;
GPIOSpeed_TypeDef GPIO_Speed;
GPIOMode_TypeDef GPIO_Mode;
}GPIO_InitTypeDef;
对结构体使用typedef来定义一个新的数据类型名字GPIO_InitTypeDef,然后使用这个新的数据类型GPIO_InitTypeDef来直接定义结构变量 GPIO_InitStructure; 该结构体的作用 提供单片机引脚,引脚速度(MHz),输入输出模式的选择
(1)GPIOSpeed_TypeDef GPIO_Speed; 输出 最大频率选择
typedef enum
{
GPIO_Speed_10MHz = 1,
GPIO_Speed_2MHz,
GPIO_Speed_50MHz
}GPIOSpeed_TypeDef;
#define IS_GPIO_SPEED(SPEED) (((SPEED) == GPIO_Speed_10MHz) || ((SPEED) == GPIO_Speed_2MHz) || \
((SPEED) == GPIO_Speed_50MHz))
对枚举使用typedef来定义一个新的数据类型名字GPIOSpeed_TypeDef,然后使用这个新的数据类型GPIOSpeed_TypeDef来直接定义结构变量 GPIO_Speed;
(2)GPIOMode_TypeDef GPIO_Mode; 配置模式枚举
typedef enum
{ GPIO_Mode_AIN = 0x0,
GPIO_Mode_IN_FLOATING = 0x04,
GPIO_Mode_IPD = 0x28,
GPIO_Mode_IPU = 0x48,
GPIO_Mode_Out_OD = 0x14,
GPIO_Mode_Out_PP = 0x10,
GPIO_Mode_AF_OD = 0x1C,
GPIO_Mode_AF_PP = 0x18
}GPIOMode_TypeDef;
#define IS_GPIO_MODE(MODE) (((MODE) == GPIO_Mode_AIN) || ((MODE) == GPIO_Mode_IN_FLOATING) || \
((MODE) == GPIO_Mode_IPD) || ((MODE) == GPIO_Mode_IPU) || \
((MODE) == GPIO_Mode_Out_OD) || ((MODE) == GPIO_Mode_Out_PP) || \
((MODE) == GPIO_Mode_AF_OD) || ((MODE) == GPIO_Mode_AF_PP))
对枚举使用typedef来定义一个新的数据类型名字GPIOSpeed_TypeDef,然后使用这个新的数据类型GPIOSpeed_TypeDef来直接定义结构变量 GPIO_Speed;
二、RCC_APB2PeriphClockCmd
关于这个APB2的外设时钟启用或者禁用的函数,本人学习深度有限,不做过多分析,直接上图。但是通过固件库手册可以看出输入参数1是选择不同外设,输入参数2是选择为你选择的外设进行时钟的配置(启用或者禁用)。而且可以通过"|"进行多个外设的选择,然后使能比如初始化函数的第二条函数
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOC,ENABLE);
三、引脚配置
通过GPIO_InitTypeDef GPIO_InitStructure; 这条语句定义了结构体GPIO_InitStructure之后,对该结构体内部的定义 (I/O的选择,IO口的工作方式以及IO口速度) 进行配置
GPIO_InitStructure.GPIO_Pin =GPIO_Pin_13;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
四、GPIO_Init(GPIOC, &GPIO_InitStructure);
最后一条语句:GPIO_Init(GPIOC, &GPIO_InitStructure); 通过固件库手册可以看出,GPIOC作为输入参数1是我们选中的外设,而 输入参数**&GPIO_InitStructure**通过取地址符让传给我们的指针形参。具体函数的实现方式,有大佬可以在评论区进行补充,但是就算不知道函数是如何实现初始化功能的,也不影响我们的使用。 #※ LED点灯程序(以点亮PC13这个LED为例子) 从STM32F103C8T6的原理图可以看到,LED(D2)已经有3.3V的高电平,为了点亮LED(D2)灯我们应该让PC13给一个低电平。
※LED的点亮程序
一、方法一:GPIO_WriteBit
该函数可以对每一位引脚的数据进行设置或者清除,对于LED灯来说就是对其控制引脚输入高电平或者低电平。 那么我们通过
GPIO_WriteBit(GPIOC,GPIO_Pin_13,Bit_RESET);
就可以把LED点亮了;
二、方法二:GPIO_SetBits&GPIO_ResetBits
通过数据手册可以知道这两个函数是将GPIO_WriteBit的拆分。 GPIO_SetBits只用来设置高电平,且可以控制一个外设的多个引脚。 GPIO_ResetBits只用来清除高电平或者设置低电平,且可以控制一个外设的多个引脚。 那么我们通过
GPIO_SetBits(GPIOC,GPIO_Pin_13);
是可以点亮LED灯的;
三、方法三:GPIO_Write
该函数的输入参数1是我们熟悉的GPIO外设的选择。我们知道GPIO是有16个引脚,对应其端口数据寄存器的16位,那么GPIO_Pin_13也就是端口寄存器的第13位,低电平选中的话对应的16进制也就是**~0x2000** 那么通过
GPIO_Write(GPIOC,~0x2000);
是可以点亮LED灯的;
四、方法四:P_out(n);
**“_”**这里代表我们要操作的那一组外设,"n"代表这个外设的哪一个引脚。
#define PAout(n) BIT_ADDR(GPIOA_ODR_Addr,n)
#define PAin(n) BIT_ADDR(GPIOA_IDR_Addr,n)
#define PBout(n) BIT_ADDR(GPIOB_ODR_Addr,n)
#define PBin(n) BIT_ADDR(GPIOB_IDR_Addr,n)
#define PCout(n) BIT_ADDR(GPIOC_ODR_Addr,n)
#define PCin(n) BIT_ADDR(GPIOC_IDR_Addr,n)
#define PDout(n) BIT_ADDR(GPIOD_ODR_Addr,n)
#define PDin(n) BIT_ADDR(GPIOD_IDR_Addr,n)
#define PEout(n) BIT_ADDR(GPIOE_ODR_Addr,n)
#define PEin(n) BIT_ADDR(GPIOE_IDR_Addr,n)
#define PFout(n) BIT_ADDR(GPIOF_ODR_Addr,n)
#define PFin(n) BIT_ADDR(GPIOF_IDR_Addr,n)
#define PGout(n) BIT_ADDR(GPIOG_ODR_Addr,n)
#define PGin(n) BIT_ADDR(GPIOG_IDR_Addr,n)
那么我们通过
PCout(13) = 0;
也是可以点亮LED的;
五、LED的闪烁
如何实现LED的闪烁呢?这里我们需要延时函数的参与,那么上面4中方法与延时函数的结合很容易就可以把LED闪烁的功能实现。这里介绍一下另个函数也可以实现LED的闪烁功能。 GPIO_ReadOutputDataBit的功能的可以返回引脚的电平高低。 那么我们通过GPIO_WriteBit函数就可以实现闪烁功能。
GPIO_WriteBit(GPIOC,GPIO_Pin_13,1-(GPIO_ReadOutputDataBit(GPIOC,GPIO_Pin_13)));
delay_ms(500);
这里delay函数大家可以自己百度啦,就不多在赘述。
|