3.3.4 C语言知识补充

C语言数据类型:

注意:在51单片机中int是占16位的,但是在STM32中int是占32位的,如果要用16位的数据,要用short来表示

因为编程习惯以及各种原因,C语言和ST给左边的变量换了名字,换为了右边的名字,C语言提供了stdint这个头文件,使用了新的名字,新版本库函数使用stdint这一列的关键字命名即可

C语言宏定义:

关键字:#define

用途:用一个字符串代替一个数字,便于理解,防止出错;提取程序中经常出现的参数,便于快速修改

定义宏定义:#define ABC 12345

引用宏定义:int a = ABC;

C语言typedef:

关键字:typedef

用途:讲一个比较长的变量类型名换个名字,便于使用

定义typedef:typedef unsigned char unit8_t;

引用typedef:unit8_t a;等效于unsigned char a;

C语言结构体

关键字:struct

用途:数据打包,不同类型变量的集合

定义结构体变量:struct{char x;int y;float z;}StructName;因为结构体变量类型较长,所以通常用typedef更改变量类型名:typedef struct {char x……} StructName_t;因此GPIO当时定义结构体也是库函数中打包好了typedef的功能,在main.c中直接使用即可

引用结构体成员:

StructName.x = 'A';

StructName.y = 66;

或pStructName->x = ‘A’;pStructName为结构体的地址

C语言枚举

关键字:enum

用途:定义一个取值受限制的整型变量,用于限制变量的取值范围;枚举同时也是一个宏定义的集合

定义枚举变量:enum{FALSE = 0,TRUE = 1} EnumName;

因为枚举变量类型较长,所以通常用typedef更改变量类型名

引用枚举成员:EnumName = FALSE;

3.3.5 按键控制LED

接线图:

需要将按键驱动控制代码单独进行封装,新建一个文件夹-HardWare,用来存放硬件驱动

上图是添加了LED驱动的HardWare文件夹

LCD.c文件:

#include "stm32f10x.h"                  // Device header
​
void LED_Init(void)
{RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
    
    GPIO_InitTypeDef GPIO_InitStruct;
    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP; 
    GPIO_InitStruct.GPIO_Pin = GPIO_Pin_1|GPIO_Pin_2;
    GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
    
    GPIO_Init(GPIOA,&GPIO_InitStruct);
    
    GPIO_SetBits(GPIOA,GPIO_Pin_1|GPIO_Pin_2);
}
​
void LED1_On(void)
{
    GPIO_ResetBits(GPIOA,GPIO_Pin_1);
}
​
void LED1_Off(void)
{
    GPIO_SetBits(GPIOA,GPIO_Pin_1);
}
​
void LED2_On(void)
{
    GPIO_ResetBits(GPIOA,GPIO_Pin_2);
}
​
void LED2_Off(void)
{
    GPIO_SetBits(GPIOA,GPIO_Pin_2);
}
​

接下来完成按键读取的文件

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.h中的函数

GPIO_ReadInputDataBit:用于读取输入数据寄存器某一个端口的输入值,参数是指定端口,返回值是uint8_t,代表这个端口的高低电平

GPIO_ReadInputData:用于读取整个输入数据寄存器,返回值是一个十六位的数据

GPIO_ReadOutputDataBit:用来读取输出数据寄存器的某一个位,其并不是用来读取端口的输入数据,这个函数一般用于输出模式下,用来看一下自己输出的是什么

GPIO_ReadOutputData:用于读取整个输出寄存器

Key.c文件:

#include "stm32f10x.h"                  // Device header
#include "Delay.h"
​
void Key_Init(void)
{
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
    
    GPIO_InitTypeDef GPIO_InitStruct;
    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IPU; 
    GPIO_InitStruct.GPIO_Pin = GPIO_Pin_1|GPIO_Pin_11;
    GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
    
    GPIO_Init(GPIOB,&GPIO_InitStruct);
    
}
    
uint8_t Key_GetNum(void)
{
    uint8_t KeyNum = 0;
    
    if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_1) == 0)
    {
        Delay_ms(20);//消除按下抖动
        while(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_1) == 0);//判断松手的情况
        Delay_ms(20);//消除松开抖动
        KeyNum = 1;
    }
    
    if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_11) == 0)
    {
        Delay_ms(20);//消除按下抖动
        while(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_11) == 0);//判断松手的情况
        Delay_ms(20);//消除松开抖动
        KeyNum = 2;
    }
    
    return KeyNum;
}

同时需要用到LED反转函数,在LED.c中添加即可

void LED1_Turn(void)
{
    if(GPIO_ReadOutputDataBit(GPIOA,GPIO_Pin_1) == 0)
    {
        GPIO_SetBits(GPIOA,GPIO_Pin_1);
    }
    else
    {
        GPIO_ResetBits(GPIOA,GPIO_Pin_1);
    }
}
​
void LED2_Turn(void)
{
    if(GPIO_ReadOutputDataBit(GPIOA,GPIO_Pin_2) == 0)
    {
        GPIO_SetBits(GPIOA,GPIO_Pin_2);
    }
    else
    {
        GPIO_ResetBits(GPIOA,GPIO_Pin_2);
    }
}

完整按键控制小灯主函数代码如图所示:

#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "LED.h"
#include "Key.h"
​
uint8_t KeyNum;//存键码的返回值
​
int main()
{
    LED_Init();
    Key_Init();
    
    while(1)
    {
        KeyNum = Key_GetNum();
        if(KeyNum ==1)
        {
            LED1_Turn();
        }
        if(KeyNum ==2)
        {
            LED2_Turn();
        }
    }
}
Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐