一.GPIO
1.概念
General Purpose input output,也叫做通用输入输出端口,简称为GPIO
GPIO输入输出的0和1的二进制数据,物理上使用高低电平(ARM中高电平:3.3V 低电平:0v)
2.编写硬件驱动的流程(以LED为例)
(1)看原理图
通过搜索硬件在开发板的丝印,或者通过原理图的索引
看原理图要达到的目的:
1)要操作的硬件是如何工作的 ---- 对应的管脚高电平,LED灭;低电平,LED亮
2)明确要操作的硬件连接到了CPU的哪些管脚(原理图上名字相同的脚在实际电路是是连在一起)
连接到了CPU的PF9,PF10 ----- GPIO管脚
(2)查看硬件说明手册(略)
(3)查看CPU的芯片手册
ARM ----- Cortex M3与M4权威指南.pdf
ST ----- STM32F4xx中文参考手册.pdf
CPU的寄存器是我们操作芯片的媒介,要控制芯片的动作,都是通过寄存器来实现的,ARM芯片的寄存器通常都是32位
stm32f407的GPIO手册
八种功能:
根据以下配置表来配置管脚的功能:
寄存器的查看
1)获取要操作寄存器的地址
stm32寄存器的地址由基地址和偏移构成,偏移就在寄存器说明的位置,基地址在参考手册2.3节
寄存器地址 = 基地址+偏移
volatile int *mode = (int *)0x40021400+0; //先清0后置1(输出) *mode &= ~(0xf<<18);//将18-21为清0 *mode |= 0x5<<18;//将18-21为改为0101 |
volatile int *otype = (int *)0x40021400+0x4; //清0(推挽) *otype &= ~(0x3<<9); |
volatile int *ospeed = (int *)0x40021400+0x8; //先清0后置1(50MHz) *ospeed &= ~(0xf<<18);//将18-21为清0 *ospeed |= 0xa<<18;//将18-21为改为1010 |
volatile int *pupdr = (int *)0x40021400+0xc; //先清0(无上下拉) *pupdr &= ~(0xf<<18);//将18-21为清0 |
用于设置输出数据寄存器对应位的值,将输出数据寄存器对应位置1,就要将本寄存器的对应set位置1
将输出数据寄存器的对应位清0,就要将本寄存器的对应reset位置1
volatile int *bsrr = (int *)0x40021400+0x18; //PF9 输出高 *bsrr |= (0x1<<9); // PF9 输出低 *bsrr |= (0x1<<25); |
注:任何的硬件要正常工作,必须提供时钟
(4)编写硬件驱动代码
3.stm32库函数使用
st公司为了推广stm系列芯片的使用,将各种寄存器的操作封装成函数,将这些函数作为固件库提供给开发者,开发者在使用stm芯片开始时候,可以不需要去直接操作寄存器,通过调用提供的库函数就可以实现对应的功能。固件库有标准固件库,HAL库,LL库
固件库在安装好stm32的开发环境后就已经存在,直接调用即可
固件库的查询文档有一些,M4找不到电子版,M3有,参考stm32f1系列的固件库文档
(1)GPIO的库函数
1)GPIO_Init -------- 初始化函数
void GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct)
参数:
GPIOx - 初始化哪一组GPIO(GPIOF)
GPIO_InitStruct - 初始化结构
typedef struct GPIOMode_TypeDef GPIO_Mode; /*!< 模式 @ref GPIOMode_TypeDef */ GPIOSpeed_TypeDef GPIO_Speed; /*!< 输出速度 @ref GPIOSpeed_TypeDef */ GPIOOType_TypeDef GPIO_OType; /*!< 输出模式 @ref GPIOOType_TypeDef */ GPIOPuPd_TypeDef
GPIO_PuPd; /*!< 上下拉 @ref GPIOPuPd_TypeDef */ |
2)GPIO_SetBits/GPIO_Reset_Bits -------- 输出高/低电平函数
void GPIO_SetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)
void GPIO_ResetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)
参数:
GPIOx - 初始化哪一组GPIO(GPIOF)
GPIO_Pin - 哪个脚
(2)时钟使能库函数
void RCC_AHB1PeriphClockCmd(uint32_t RCC_AHB1Periph, FunctionalState NewState)
参数:
AHB1Periph - 哪个时钟(RCC_AHB1Periph_GPIOF)
NewState - 设置成什么状态(ENABLE/DISABLE)