系列文章目录
文章目录
1. GPIO模式
GPIO是微控制器中最基本也是最灵活的功能之一,其可以被配置为输入或输出模式,以及许多其他特殊功能模式。通过配置GPIO的端口配置寄存器,端口可以配置成以下8种模式:
模式名称 | 类型 | 描述 |
---|---|---|
浮空输入 | 浮空输入 | 引脚没有内部或外部上拉或下拉,其电平未定义,通常不建议使用 |
上拉输入 | 上拉输入 | 引脚内部上拉至VDD,外部信号低于VDD时,检测到低电平 |
下拉输入 | 下拉输入 | 引脚内部下拉至VSS,外部信号高于VSS时,检测到高电平 |
模拟输入 | 模拟输入 | GPIO未锁定,引脚直接连接到内部ADC |
开漏输出 | 开漏输出 | 引脚以开漏模式工作,高电平时为高阻态,低电平时连接到VSS |
推挽输出 | 推挽输出 | 引脚以推挽模式工作,高电平时连接到VDD,低电平时连接到VSS |
复用开漏输出 | 复用开漏输出 | 用于复用功能的开漏输出,高电平时为高阻态,低电平时连接到VSS |
复用推挽输出 | 复用推挽输出 | 用于复用功能的推挽输出,高电平时连接到VDD,低电平时连接到VSS |
模式分类:
- 输入模式(Input):引脚被配置为输入,用来读取外部信号的状态。
- 输出模式(Output):引脚被配置为输出,可以驱动外部设备或显示设备状态。
类型分类:
- 推挽输出(Push-pull):可以在两种状态之间切换,要么连接到VDD(高电平),要么连接到VSS(低电平)。
- 开漏输出(Open-drain):只能连接到VSS(低电平),而高电平状态需要外部拉高。
GPIO配置说明
- 浮空输入(Floating input):引脚没有内部或外部的上拉或下拉电阻,状态由外部电路决定。
- 上拉输入(Pull-up input):引脚内部连接有上拉电阻,如果外部电路没有连接,它将读取为高电平。
- 下拉输入(Pull-down input):引脚内部连接有下拉电阻,如果外部电路没有连接,它将读取为低电平。
- 模拟输入(Analog input):GPIO以模拟方式工作,可以直接连接到内部ADC(模拟到数字转换器)。
- 开漏输出(Open-drain output):引脚在激活时连接到VSS,非激活时不连接(悬空)。常用于需要外部拉高的应用场合。
- 推挽输出(Push-pull output):引脚可以输出高电平(连接到VDD)或低电平(连接到VSS)。
- 复用开漏输出(Alternate function open-drain output):开漏输出,但是引脚被配置为特殊功能,例如I2C通信。
- 复用推挽输出(Alternate function push-pull output):推挽输出,但是引脚被配置为特殊功能,例如PWM输出。
2. GPIO输出
操作STM32的GPIO一共有三个步骤:
- 使用RCC开启GPIO的时钟
- 使用GPIO_Init函数初始化GPIO
- 使用输出或者输入函数控制GPIO
2.1 RCC
首先打开一个新建好的工程文件,如果不知道怎么建立工程文件,可以看下面这篇文章:
之后在Library中找到rcc.h文件(这里全程使用vscode去操作,如果不知道怎么实现Keil和VSCode协同开发STM32程序,可以查看下面这篇教程:
在rcc.h文件中拖到最下面,这里一般都是所有库函数的声明,这里最常用的就是这三个函数:
void RCC_AHBPeriphClockCmd:外设时钟控制
接着选择函数名,右键并选择转到定义(这里需要先进行一次编译,否则可能无法跳转) ,之后会来到.c文件的函数定义,下面解释一下这个函数:
// 函数定义:控制特定AHB外设的时钟。 // RCC_AHBPeriph:要配置的AHB外设。 // NewState:指定外设时钟的新状态,ENABLE(使能) 或 DISABLE(失能)。 void RCC_AHBPeriphClockCmd(uint32_t RCC_AHBPeriph, FunctionalState NewState) { // 确保输入参数RCC_AHBPeriph是预定义的有效外设。 assert_param(IS_RCC_AHB_PERIPH(RCC_AHBPeriph)); // 确保输入的NewState是有效的功能状态(ENABLE 或 DISABLE)。 assert_param(IS_FUNCTIONAL_STATE(NewState)); // 如果NewState不是DISABLE(即是ENABLE),执行以下代码。 if (NewState != DISABLE) { // 通过逻辑或运算将对应的位设置为1,来使能(开启)外设的时钟。 RCC->AHBENR |= RCC_AHBPeriph; } // 如果NewState是DISABLE,执行以下代码。 else { // 通过逻辑与运算与对应位的否定值运算,将对应的位设置为0,来禁能(关闭)外设的时钟。 RCC->AHBENR &= ~RCC_AHBPeriph; } }
2.2 GPIO
下面看一下GPIO.h的文件,在Library中找到GPIO.h文件,也是拖到最后,这里可以看到常用的函数。
void GPIO_DeInit(GPIO_TypeDef* GPIOx); void GPIO_AFIODeInit(void); void GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct); void GPIO_StructInit(GPIO_InitTypeDef* GPIO_InitStruct); 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); 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);
void GPIO_DeInit(GPIO_TypeDef* GPIOx);
功能:将指定GPIO端口的所有配置重置为默认值。
参数:GPIOx:要重置的GPIO端口,例如GPIOA、GPIOB等。
说明:这个函数通常用于在重新配置(复位)GPIO端口之前清除端口的当前配置。
void GPIO_AFIODeInit(void);
功能:将AFIO(Alternate Function IO)模块的所有配置重置(复位)为默认值。
说明:这个函数通常用于清除所有GPIO端口的复用功能配置。
void GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct);
功能:用结构体的参数初始化指定GPIO端口的引脚。
参数:
- GPIOx:要初始化的GPIO端口,例如GPIOA、GPIOB等。
- GPIO_InitStruct:包含了初始化配置的结构体指针,如引脚模式、输出类型、输出速度等。
说明:这个函数用于配置GPIO引脚的各种属性,例如输入/输出模式、输出类型、输出速度等。
void GPIO_StructInit(GPIO_InitTypeDef* GPIO_InitStruct);
功能:将给定的GPIO_InitTypeDef结构体初始化为默认值。
参数:GPIO_InitStruct:要初始化的GPIO_InitTypeDef结构体指针。
说明:这个函数用于在配置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端口指定引脚的输入状态。
参数:
- GPIOx:要读取的GPIO端口,例如GPIOA、GPIOB等。
- GPIO_Pin:要读取的引脚,可以是单个引脚或多个引脚的按位或组合。
返回值:引脚的输入状态,0/1。或者GPIO端口的输入状态,每个引脚的状态对应一个位。
void GPIO_SetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
功能:将指定GPIO端口指定引脚的输出状态设置为高电平。
参数:
- GPIOx:要设置的GPIO端口,例如GPIOA、GPIOB等。
- GPIO_Pin:要设置的引脚,可以是单个引脚或多个引脚的按位或组合。
void GPIO_ResetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
功能:将指定GPIO端口指定引脚的输出状态设置为低电平。
参数:
- GPIOx:要重置的GPIO端口,例如GPIOA、GPIOB等。
- GPIO_Pin:要重置的引脚,可以是单个引脚或多个引脚的按位或组合。
void GPIO_WriteBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, BitAction BitVal);
功能:将指定GPIO端口指定引脚的输出状态设置为指定的电平。
参数:
- GPIOx:要写入的GPIO端口,例如GPIOA、GPIOB等。
- GPIO_Pin:要写入的引脚,可以是单个引脚或多个引脚的按位或组合。
- BitVal:要设置的电平,可以是Bit_RESET(低电平)或Bit_SET(高电平)。
void GPIO_Write(GPIO_TypeDef* GPIOx, uint16_t PortVal);
功能:设置指定GPIO端口的输出状态。
参数:
- GPIOx:要写入的GPIO端口,例如GPIOA、GPIOB等。
- PortVal:要设置的输出值,每个引脚的状态对应一个位,0表示低电平,1表示高电平。
3. 代码示例
这里使用最基础的led灯来解释代码功能
3.1 RCC时钟
在main.c文件中,首先调用RCC中的APB2外设时钟控制函数,首先和刚才一样,在RCC.h找到函数名, RCC_APB2PeriphClockCmd, 复制到main中,接着右键函数转到定义,根据注释中的提示,因为点亮的是PA0的LED,所以选择 RCC_APB2Periph_GPIOA,将其放到第一个参数,第二个参数选择ENABLE, 这样时钟就开启了。
3.2 GPIO初始化
接着调用GPIO的初始化函数,在GPIO.h中找到 GPIO_Init 函数,跳转到定义,和rcc类似根据注释中的提示,第一个参数选择GPIOA, 第二个参数是一个结构体
先把结构体复制到GPIO_Init上面,起名为:GPIO_InitStructure, 这个结构体相当于一个局部变量,然后将结构体的成员都列出来,如下所示:
GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_Pin = ; GPIO_InitStructure.GPIO_Mode = ; GPIO_InitStructure.GPIO_Speed = ; GPIO_Init()
接下来就是如何根据标准库文件来配置函数,以GPIO_Mode为例, 接下来会详细到每一个操作,之后这些操作会省略。
- 首先右键 GPIO_Mode转到定义
- 根据提示,我们选择GPIOMode_TypeDef,接着按ctrl+f 搜索,在下面找到定义方式,这里有GPIO的八种工作模式。
- GPIO_Mode_AIN (0x0):模拟输入模式(Analog Input Mode)
- GPIO_Mode_IN_FLOATING (0x04):浮空输入模式(Floating Input Mode)
- GPIO_Mode_IPD (0x28):输入下拉模式(Input Pull-Down Mode)
- GPIO_Mode_IPU (0x48):输入上拉模式(Input Pull-Up Mode)
- GPIO_Mode_Out_OD (0x14):开漏输出模式(Open-Drain Output Mode)
- GPIO_Mode_Out_PP (0x10):推挽输出模式(Push-Pull Output Mode)
- GPIO_Mode_AF_OD (0x1C):复用开漏输出模式(Alternate Function Open-Drain Mode)
- GPIO_Mode_AF_PP (0x18):复用推挽
因为这里是为了实现LED功能,所以使用GPIO_Mode_Out_PP,将其复制到GPIO_Mode后面。
接着是GPIO_Pin,同样的操作,转到定义,这里很简单,选择GPIO_Pin_0即可。
- 如果要使用多个A引脚,例如多个led灯,直接在后面加上即可,每个定义之间用 | 隔开。
最后是GPIO_Speed,转到定义以后,按ctrl+f 搜索,如图所示下一个就是函数说明,这里选择GPIO_Speed_50MHz,将其复制到GPIO_Speed后面。
最后,将完成配置的结构体的变量名:GPIO_InitStructure,复制到GPIO_Init中即可完成GPIO的初始化配置。
此时,main.c中的代码如下:
#include "stm32f10x.h" // Device header int main(void) { RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure); while (1) { } }
3.3 GPIO输出函数
完成GPIO的初始化之后,就可以使用GPIO的输出函数了,四个输出函数为(前面已经解释):
void GPIO_SetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin); //将指定GPIO端口指定引脚的输出状态设置为高电平。 void GPIO_ResetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin); //将指定GPIO端口指定引脚的输出状态设置为低电平。 void GPIO_WriteBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, BitAction BitVal); //将指定GPIO端口指定引脚的输出状态设置为指定的电平。 void GPIO_Write(GPIO_TypeDef* GPIOx, uint16_t PortVal); //设置指定GPIO端口的输出状态。
GPIO_ResetBits
我们选择低电平输出,所以使用 GPIO_ResetBits,和前面的操作一样,可以转到定义查看注释说明,因为led灯使用A0引脚,所以代码为:
GPIO_ResetBits(GPIOA, GPIO_Pin_0);
此时下载程序到单片机中就可以看到LED灯已经被点亮。(注意这里采用的时led长脚连接负极,短接连接引脚,代表低电平点亮)
GPIO_SetBits
如果换成 GPIO_SetBits,可以发现LED熄灭,因为此时输出为高电平。
GPIO_WriteBit
第三种输出函数:GPIO_WriteBit,这个函数是指定输出类型,比如前面的配置不同改变,多了一个BitAction参数,转到定义,可以发现注释教程中说明了两个方式Bit_RESET和Bit_SET
Bit_RESET: 清除端口值(置低电平)
Bit_SET: 设置端口值(置高电平)
GPIO_WriteBit(GPIOA, GPIO_Pin_0, Bit_SET); 此时led点亮。。GPIO_WriteBit(GPIOA, GPIO_Pin_0, Bit_SET); 此时led熄灭。
目前main.c中的代码如下:
#include "stm32f10x.h" // Device header int main(void) { RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure); GPIO_WriteBit(GPIOA, GPIO_Pin_0, Bit_SET); while (1) { } }
这里的GPIO_WriteBit用于LED点亮时,可能会发现一个问题,Bit_SET可以置为高电平,此时LED熄灭,那如果想用基本的0和1来代表高低电平,直接将Bit_SET改为1会出现警告,所以还需要加上强制类型转换,把1和0类型转为BitAction的枚举类型:
GPIO_WriteBit(GPIOA, GPIO_Pin_0, (BitAction)1);
这就是GPIO输出函数的配置,之后就是你想实现的功能,这些功能就是在后面的while中去实现,并且根据不同的模块和功能添加不同的库,例如实现led连续闪烁,除了修改main.c中的主程序,还需要在工程文件在加入delay.c 和 delay.h 文件。但操作都类似,在.h文件中找到需要使用的标准库函数,转到定义在.c文件中找到函数定义和注释说明。
GPIO_WriteBit
这个函数可以设置指定GPIO端口的输出状态。例如对于多个led的控制。
首先还是转到定义,从注释中可以看到,第一个参数依然是GPIOA, 第二个参数是指定写到输出数据寄存器的值,下面可以看到第二个参数是直接写道GPIO和ODR寄存器里的。
所以可以直接写0x001(十六进制),对应二进制为0000 0000 0000 0001。这16个二进制分别对应PA0 - PA15 一共16个端口,最低位(右边)对应PA0。
此时如果加入延迟函数,就可以实现最基本的led灯流水线
#include "stm32f10x.h" // Device header int main(void) { RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_All; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure); while (1) { GPIO_Write(GPIOA, 0x0001); // Set PA0 Delay_ms(1000); GPIO_Write(GPIOA, 0x0002); // Set PA1 Delay_ms(1000); GPIO_Write(GPIOA, 0x0004); // Set PA2 Delay_ms(1000); } }
如果设置为低电平触发,可以在参数前加上 ~ ,意思是取反。
3.4 推挽输出和开漏输出
对于推挽输出和开漏输出的驱动问题,还是用刚才led的例子,目前我们使用的是GPIO_Mode_Out_PP (0x10):推挽输出模式。此时将led短脚连接负极,长接连接引脚,代表高电平点亮,这时可以发现程序依然可用,说明在推挽模式下,高低电平都有驱动能力。
如果把端口的模式改为 GPIO_Mode_Out_OD (0x14):开漏输出模式
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;
此时led还是保持高电平点亮,但程序不起作用,只有当led引脚切换以后,改为低电平点亮时,程序才可以正常运行,这说明开漏输出模式的高电平不具有驱动能力。
所以,推挽输出高低电平都有驱动能力,开漏输出高电平相当于高阻态,没有驱动能力,只有低电平有驱动能力。
4. GPIO输入
4.1 输入模式
GPIO输入的配置和GPIO输出类似,不同的数结构体中 GPIO_InitStructure.GPIO_Mode 不同,这里要使用下面的四种输入模式,例如按键输入使用上拉输入模式(GPIO_Mode_IPU)
GPIO_Mode_AIN (0x0):模拟输入模式(Analog Input Mode)
- 在这种模式下,GPIO引脚被配置为读取模拟信号,意味着它可以直接与微控制器内部的模拟-数字转换器(ADC)相连。
- GPIO引脚不会被数字输入缓冲器干扰,这样可以保证模拟信号的准确性和质量。
- 通常用于传感器信号读取,如温度、压力或湿度传感器。
GPIO_Mode_IN_FLOATING (0x04):浮空输入模式(Floating Input Mode)
- GPIO引脚配置为数字输入,没有激活内部上拉或下拉电阻,其电平状态取决于外部电路。
- 如果外部没有提供确定的电平,引脚的状态是未定义的,可能会浮动,因此称为“浮空”。
- 这种模式适合于外部电路总是会驱动GPIO到一个确定状态,或者外部已经提供了必要的上拉或下拉设置。
GPIO_Mode_IPD (0x28):输入下拉模式(Input Pull-Down Mode)
- PIO引脚配置为数字输入,并且内部激活了下拉电阻,这会将引脚默认拉至低电平(接地)。
- 如果外部没有提供信号,引脚将读取为低电平状态;如果外部提供了高电平信号,则会被检测到。
- 这种模式适用于按钮或开关,其中未激活状态需要确保为低电平。
GPIO_Mode_IPU (0x48):输入上拉模式(Input Pull-Up Mode)
- GPIO引脚配置为数字输入,并且内部激活了上拉电阻,这会将引脚默认拉至高电平(接VDD或正电源)。
- 如果外部没有提供信号,引脚将读取为高电平状态;如果外部提供了低电平信号,则会被检测到。
- 这同样适用于按钮或开关,但在这种情况下,未激活状态需要确保为高电平。
4.2 数据读取函数
还有GPIO数据读取的函数:例如读取按键输入就要用到 GPIO_ReadInputDataBit
uint8_t GPIO_ReadInputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
- 功能:此函数用于读取STM32的GPIO端口上的单个输入引脚的状态。这对于检测如按钮按下、限位开关触发等简单的二进制输入非常有用。
- 参数:
GPIOx
:指向你想要读取的GPIO端口的指针。STM32微控制器有多个GPIO端口,例如GPIOA、GPIOB等,每个都对应不同的物理引脚组。GPIO_Pin
:具体的GPIO引脚编号,它是一个16位的值,每一位代表一个特定的引脚。例如,如果你想读取第0位,就会使用GPIO_Pin_0
。
- 返回值:返回值是一个8位的无符号整数。如果指定的引脚处于高电平状态,则返回非零值;如果处于低电平,则返回零。
uint16_t GPIO_ReadInputData(GPIO_TypeDef* GPIOx);
- 功能:这个函数读取整个GPIO端口的当前输入数据。这在你需要同时检查一个端口上的多个引脚状态时非常有用。
- 参数:
- GPIOx:与GPIO_ReadInputDataBit函数中的GPIOx相同,指向要读取的GPIO端口的指针。
- 返回值:返回值是一个16位的无符号整数。每个比特位代表该端口上对应引脚的输入状态,位值为1表示该引脚处于高电平,位值为0表示处于低电平。
uint8_t GPIO_ReadOutputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
- 功能:此函数用于读取STM32的GPIO端口上的单个输出引脚的状态。这在你需要确认引脚的当前输出状态,例如,确保一个LED是否被程序正确控制时非常有用。
- 参数:
- GPIOx:与GPIO_ReadInputDataBit函数中的GPIOx相同,指向你想要读取的GPIO端口的指针。
- GPIO_Pin:与GPIO_ReadInputDataBit函数中的GPIO_Pin相同,表示特定的GPIO引脚编号。
- 返回值:返回值是一个8位的无符号整数。如果指定的引脚正在输出高电平,则返回非零值;如果正在输出低电平,则返回零。
uint16_t GPIO_ReadOutputData(GPIO_TypeDef* GPIOx);
- 功能:这个函数读取整个GPIO端口的当前输出数据。当你需要审核或调试一个端口上多个引脚的输出配置时,这个函数非常有用。
- 参数:
- GPIOx:与GPIO_ReadInputData函数中的GPIOx相同,指向要读取的GPIO端口的指针。
- 返回值:返回值是一个16位的无符号整数。与
GPIO_ReadInputData
类似,每个比特位代表该端口上对应引脚的输出状态,位值为1表示该引脚正在输出高电平,位值为0表示正在输出低电平。
5. C语言语法
STM32基于C语言开发,对于这部分,需要有一些C语言的基础知识,例如下面的数据类型,如果对这方面不太了解,可以看下面的C语言系列讲解。
数据类型 | 位数 | 表示范围 | stdint定义 | ST定义 |
---|---|---|---|---|
char | 8 | -128 ~ 127 | int8_t | s8 |
unsigned char | 8 | 0 ~ 255 | uint8_t | u8 |
short | 16 | -32768 ~ 32767 | int16_t | s16 |
unsigned short | 16 | 0 ~ 65535 | uint16_t | u16 |
int | 32 | -2147483648 ~ 2147483647 | int32_t | s32 |
unsigned int | 32 | 0 ~ 4294967295 | uint32_t | u32 |
long | 32 | -2147483648 ~ 2147483647 | int32_t | s32 |
unsigned long | 32 | 0 ~ 4294967295 | uint32_t | u32 |
long long | 64 | -(2^64)/2 ~ (2^64)/2-1 | int64_t | |
unsigned long long | 64 | 0 ~ (2^64)-1 | uint64_t | |
float | 32 | -3.4e38 ~ 3.4e38 | ||
double | 64 | -1.7e308 ~ 1.7e308 |
接下来对几个关键的语法进行简单说明:
宏定义 #define
用途:用一个字符串代替一个数字,便于理解,防止出错;提取程序中经常出现的参数,便于快速修改。
定义宏定义:
#define test 123
引用宏定义:
int a = test; //等效于int a = 123;
typedef
用途:将一个比较长的变量类型名换个名字,便于使用,只能用于变量名。
定义typedef:
typedef unsigned char uint8_t;
引用typedef:
uint8_t a; //等效于unsigned char a;
结构体 struct
用途:数据打包,不同类型变量的集合
定义结构体变量:因为结构体变量类型较长,所以通常用typedef更改变量类型名
struct{char x; int y; float z;} StructName;
引用结构体成员:
StructName.x = 'T'; StructName.y = 123; StructName.z = 55.55; //或者 pStructName->x = 'T'; //pStructName为结构体的地址 pStructName->y = 123; pStructName->z = 55.55;
枚举 enum
用途:定义一个取值受限制的整型变量,用于限制变量取值范围;宏定义的集合.
定义枚举变量:因为枚举变量类型较长,所以通常用typedef更改变量类型名
enum{FALSE = 0, TRUE = 1} EnumName;
引用枚举成员:
EnumName = FALSE; EnumName = TRUE;
这里知识简单说明,如果想要深入学习,可以看下面的C语言系列讲解。