2. 基于STM32F10x.3.5.0库的流水灯程序http://blog.csdn.net/zc1107473010/article/details/45095543
1.LED的管脚在GPIOA ~GPIOD中处于何种位置,从而确定要使能和配置的GPIO模块。
这里可以通过查看原理图获得,如我的开发板就是PD2,PD3,PD4,PD7
注意:采用库函数方式,下面这些地址以及寄存器功能初期只需要了解就行,但如果采用寄存器控制,就需要查询STM32中文/英文参考手册8.2,了解寄存器每位所代表意思,通过直接地址操作配置和控制。
#definePERIPH_BASE ((u32)0x40000000)
#defineAPB2PERIPH_BASE (PERIPH_BASE + 0x10000)
#defineGPIOA_BASE (APB2PERIPH_BASE + 0x0800)
#defineGPIOA ((GPIO_TypeDef*) GPIOA_BASE)
以上用来定义GPIOx在外设定义中的地址。
//GPIO相关功能寄存器结构体
typedef struct
{
vu32CRL; //端口配置寄存器低位
vu32CRH; //端口配置寄存器高位
vu32IDR; //端口输入数据寄存器
vu32ODR; //端口输出数据寄存器
vu32BSRR; //端口位置位/复位寄存器
vu32BRR; //端口位复位寄存器
vu32LCKR; //端口配置锁定寄存器
}GPIO_TypeDef; //声明GPIO标准功能寄存器
//GPIO复用功能寄存器结构体
typedef struct
{
vu32EVCR; //事件控制寄存器
vu32MAPR; //复用重映射和调试I/O配置寄存器
vu32EXTICR[4]; //外部中断线号0~15配置寄存器
} AFIO_TypeDef; //声明GPIO复用功能寄存器
通过查询了解,如配置PD7位为推挽输出,最大频率50MHZ,且管脚置1,
寄存器配置如下:
GPIOD->CRL &= ~(0x11 << 28);
GPIOD->BRR |= (0x01 << 7);
<LED端口的初始化>
2.使能需要的GPIO端口的外设时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD, ENABLE);
其实在这之前还要配置系统时钟,以及端口所在总线区域也是在该芯片设计时已经固定的,这里知道GPIOD位于APB2总线即可,具体后面会在系统时钟章节继续深入讲解。
小知识:
外设模块时钟使能一定在外设配置函数之前,这是因为修改对应端口的寄存器是通过触发器设置,触发器脉冲来自于外设时钟,因此要先根据总线时钟使能外设时钟,否则配置是无效的。
4.GPIO配置函数GPIO_Init(GPI0x, GPIO_IntTypeDef *GPIO_IntStruct)
typedef struct
{
u16 GPIO_Pin; //选中需要的GPI管脚
GPIOSPeed_Typedef GPIO_SPeed; //设定工作输出最大频率
GPIOSMODE_Typedef GPIO_MODE; //设定管脚工作方式
}GPIO_IntTypeDef;
速率有三种,工作方式有8种, 如下定义即可完成管脚的配置:
GPIO_IntTypeDef *GPIO_IntStructure;
GPIO_IntStructure.GPIO_Pin = GPIO_Pin_2 | GPIO_Pin_3
| GPIO_Pin_4 | GPIO_Pin_7;
GPIO_IntStructure.GPIO_SPeed =GPIO_SPeed_50MHz; //最大工作频率50MHZ
GPIO_IntStructure.GPIO_MODE =GPIO_Mode_Out_PP; //设定选中管脚为推挽输出
GPIO_Init(GPIOD , &GPIO_IntStructure);
<对配置好的GPIO口进行操作>
5.流水灯逻辑
这里主要用到两个函数
GPIO_SetBits(GPI0x, u16 GPIO_Pin); /*对应GPIO端口置1*/
GPIO_ResetBits(GPI0x,u16 GPIO_Pin); /*对应GPIO端口置0*/
这两个函数很好理解,这里就不多说了。那么就说下流水灯的逻辑。
LED1亮-〉延时->LED1灭-〉LED2亮-〉延时->LED2灭......如此循环就可以实现流水灯。
看到这是不是对流水灯的设计一目了然了呢,其实和传统的如51单片机中实现流水灯的逻辑几乎没什么区别,唯一的区别就是多了端口的配置,这是因为STM32芯片的管脚有8种不同的功能,当我们使用这些管脚,嵌入式芯片并不能直接判断管脚用途,而当我们告诉它之后,就和以前写51程序一样简单了。类似的程序可以写按键控制点亮对应led灯,控制蜂鸣器发声,这里我就不在说明,并没有太大区别。
小知识:
GPIO的8种输入输出方式
GPIO_Mode_AIN 模拟输入
GPIO_Mode_IN_FLOATING 浮空输入
GPIO_Mode_IPD 下拉输入
GPIO_Mode_IPU 上拉输入
GPIO_Mode_Out_OD 开漏输出
GPIO_Mode_Out_PP 推挽输出
GPIO_Mode_AF_OD 复用开漏输出
GPIO_Mode_AF_PP 复用推挽输出
这8种工作方式的区别
模拟输入 用于模拟量的输入,或者低功耗下省电。
下拉输入 GPIO端口内默认下拉电阻电路导通。初始为低电平,外部高电平动作。
上拉输入 GPIO端口内默认上拉电阻电路导通,初始为高电平,外部低电平动作。
浮空输入 GPIO端口内上下MOSFET均不导通,高阻态,输入状态仅由端口决定。
开漏输出 GPIO端口输出为0时内部下拉电阻电路接地,输出1时端口相当于悬空,即默认只能输出0,如果外部需要输出1,需要外接上拉电阻电路。
推挽输出 GPIO端口输出为0时内部下拉电阻电路接地,输出1时内部接上拉电阻电路,不需要外接上拉电阻电路即可输出0和1。
复用推挽输出 百度看到的超经典回答,因为不在是普通的I/O口所以复用,因为不需要外接上拉电阻所以推挽。例如串口的TX就为发送数据端口,即复用推挽输出。
复用开漏输出 具体解释同上,具体管脚复用功能配置要求可参考STM32中文参考手册8.1.11