由于stm32有很多外设,为降低功耗,每个外设都对应着一个时钟。在芯片刚刚上电时,这些时钟都是被关闭的。如果想要外设工作,必须把相应的时钟打开。
即当GPIO口复用USART进行通讯时,必须要先使能GPIO的时钟,然后再使能具体外设的时钟(USART的时钟)!!!
1. stm32单片机的I/O端口配置步骤:
(1)GPIOx端口定义
(2)GPIO_Pin_x管脚定义
(3)GPIO_InitTypeDef初始化端口参数定义
(4)GPIO_Init初始化端口定义
每个GPIOx端口:共有7个设置寄存器
(1)两个32位的配置寄存器(GPIOx_CRL, GPIOx_CRH)
(GPIOx_CRL)(x=A....G): GPIOx configuration register low, GPIOx端口低配置寄存器,用于配置GPIOx端口的第0位~第7位。
(GPIOx_CRH)(x=A....G): GPIOx configuration register high, GPIOx端口高配置寄存器,用于配置 GPIOx端口的第8位~第16位。
(2)两个32位的数据寄存器(GPIOx_IDR, GPIOx_ODR)
(GPIOx_IDR)(x=A....G): GPIOx input data register, GPIOx输入数据寄存器,读出对应I/O口输入的状态值。
(GPIOx_ODR)(x=A....G): GPIOx output data register, GPIOx输出数据寄存器,读出对应I/O口输出的状态值。
(3)一个32位的置位/复位寄存器(GPIOx_BSRR)
(GPIOx_BSRR)(x=A...G): GPIOx bit set/reset register 用于设置端口的电平
(4)一个16位的复位寄存器(GPIOx_BRR):清除端口x的某位值
(5)一个32位的锁定寄存器(GPIOx_LCKR): (GPIOx_LCKR)(x=A...G): GPIOx configuration lock register, 用于寄存器锁定端口位的配置。
3. 在固件库函数文件中,用结构体GPIO_TypeDef定义GPIOx端口:
typedef struct { uint32_t CRL; uint32_t CRH; uint32_t IDR; uint32_t ODR; uint32_t BSRR; uint32_t BRR; uint32_t LCKR; }GPIO_TypeDef; //用结构体GPIO_TypeDef定义GPIOx端口,(即定义GPIOx端口的7个设置寄存器)
4. 编程时,GPIOx端口的具体配置是从GPIOA/GPIOB/GPIOC/GPIOD/GPIOE寄存器开始。
首先,在固件库中用结构体GPIO_TypeDef定义GPIOx端口,(即定义GPIOx端口的7个设置寄存器):
5. GPIO_Init初始化端口定义
功能:根据GPIO_InitTypeDef中指定的参数,初始化外设GPIOx端口
函数名 | GPIO_Init |
函数原型 | void GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct) |
功能 | 根据GPIO_InitStruct中指定的参数初始化外设GPIOx寄存器 |
输入参数1 | GPIOx: x可以是A,B,C,D,E,来选择GPIO外设 |
输入参数2 | GPIO_InitStruct: 指向结构体GPIO_InitTypeDef的指针,包含外设GPIO的配置信息 |
输出参数 | 无 |
返回值 | 无 |
先决条件 | 无 |
被调用函数 | 无 |
例如,GPIO_InitTypeDef GPIO_InitStructure; //定义结构体变量GPIO_InitStructure用于初始化GPIOx端口参数;GPIO_Init(GPIOx, &GPIO_InitStructure); //初始化GPIOx端口。
6. NRZ码
NRZ码是单极性不归零码,是最基本的数字基带编码。
编码规则:用高电平表示基带中的“1”, 低电平表示基带中的“0”;
7. stm32串口复用功能使用
(1)配置时钟,由于使用串口是在复用IO口,需要打开串口时钟和相应的IO口时钟。
(2)配置IO口,串口相应的IO口需要配置,输出口配置成复用推挽输出,输出口速度根据需要配置,输入口配 置为浮空输入。
(3)配置串口,主要是包括波特率、数据长度、停止位、奇偶校验、硬件流控制、接收发送模式。
(4)打开串口
串口配置程序 配置PA9, PA10为USART1的发送和接收口 void Config_Usart1(void) { GPIO_InitTypeDef GPIO_InitStructure; /*定义GPIO初始化结构体变量*/ USART_InitTypeDef USART_InitStructure; /*定义USART初始化结构体变量*/ /*配置USART1时钟,同时打开引脚时钟和USART1时钟*/ RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1|RCC_APB2Periph_GPIOA, ENABLE); /*配置USART1的TX(PA9)端口为推挽输出*/ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure); /*配置USART1的RX(PA10)端口为浮空输入*/ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_Init(GPIOA, &GPIO_InitStructure); /*USART1模式配置发送和接收, 波特率115200bps, 无校验位,不适用硬件流控制*/ USART_InitStructure.USART_BaudRate = 115200; USART_InitStructure.USART_WordLength = USART_WordLength_9b; USART_InitStructure.USART_StopBits = USART_StopBits_1; USART_InitStructure.USART_Parity = USART_Parity_Even; USART_InitStructure.USART_HardwareFlowControl = USART_Mode_Rx|USART_Mode_Tx; /*初始化USART1,打开USART1*/ USART1_Init(USART1, &USART_InitStructure); USART_Cmd(USART1,ENABLE); }
8. GPIO口作为一般输入输出口使用时
使用固件库点亮LED灯
int main(void) { GPIO_InitTypeDef GPIO_InitStructure; /*定义GPIO_InitTypeDef结构体*/ RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE); /*开启GPIO端口时钟*/ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; /*选择要控制的GPIO引脚*/ GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; /*选择引脚模式为通用推挽输出*/ GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; /*设置引脚速率为50MHz*/ GPIO_Init(GPIOA, &GPIO_InitStructure); GPIO_ResetBits(GPIOA,GPIO_Pin_0); while(1) { GPIO_ResetBits(GPIOA,GPIO_Pin_0); /*使引脚输出低电平,点亮LED灯*/ Delay(0xffff); GPIO_SetBits(GPIOA,GPIO_Pin_0); /*使引脚输出高电平,熄灭LED灯*/ Delay(0xffff); } }