单片机基础:关键字的使用以及结构体指针

1.#define:

用法: #define     标识符        被标识符代表的字符串

        标识符为所定义的宏名        而字符串可以是常数、表达式、格式串等

作用:为c语言的预处理命令,用于宏定义,可以提高代码的可读性,在单片机中用于替换字节地址或定义标识符

eg:

#define    LED                P0
#define    ABC                123
#define    SYSCLK_FREQ_72MHz  72000000

2.typedef

用法:typedef        被替换的变量类型                标识符

作用:只能对变量类型换名字,会对变量类型进行检测,如果不是变量类型会报错。

eg:

typedef  unsigned char   uint8_t;
typedef  unsigned int    uint16_t;
typedef struct
{
    //结构体
}GPIO_TypeDef;
typedef enum
{
    //枚举
}Bit_Action;

 Typedef 为结构体定义一个别名 GPIO_TypeDef,以及给枚举定义别名Bit_Action;

3.#ifdef、#ifndef

主要用于头文件的编译中,当满足某条件时对一组语句进行编译,而当条件不满足时则编译另一组语句。

#define  PI    3.14

#ifdef  PI
    printf("PI被宏定义了");//程序段1
#else
    printf("PI未被宏定义");//程序段2
#endif

当标识符已经被定义过(一般是用#define 命令定义),则对程序段 1 进行编译,否则编译程序段 2。 其中#else 部分也可以没有。

4.extern

        用法:extern        变量或函数

        作用:C 语言中 extern 可以置于变量或者函数前,以表示变量或者函数的定义在别的文件中,提示编译器遇到此变量和函数时在其他模块中寻找其定义。

        在单片机编程模块化中可能会用到,比如:我在按键中定义了一个变量uint8_t KEY_num,如果想在main函数中使用这个变量,可以在main函数之前或者在key.h中写

extern uint8_t KEY_num;

5.static

         用法:static        int    num;  或者 static        int    num = 1;

        作用:调用函数结束后,将局部变量的值保护起来,下次再调用所在函数时,其值不会被初始化,即它所占用的存储单元不释放,在下一次调用该函数时,其局部变量的值仍然存在,也就是上一次函数调用结束时的值。。 static 关键字不仅可以用来修饰变量,还可以用来修饰函数。

6.const

         用法:const    变量并赋值

                   const      int    x = 10;

         作用:可以修饰一个变量,使这个值在初始化后就不会在改变(相当于声明为只读特性)。如果强行改变则会报错,主要防止变量被调用过程被错误的更改。

eg:

const int x = 10;

void printfString(const char* str)
{
    printf("String:str");
}

const int get_num(int x)
{
    return x = 2;
}

7.volatile

        作用:防止被优化。在嵌入式开发中非常重要,尤其是操作硬件或者多线程的场景。编译器在很多时候为了提升程序的运行效率,会删除一些没用的代码,以及直接从寄存器或则缓存中读取某些变量的值。因为从寄存器或者缓存中读取值其速度比内存快,若这个变量为共享数据,有可能会被中断等程序修改,那读到的数据和内存的数据可能不一致,接下来可能会导致一系列的问题。而加了这个关键字就是告诉编译器这个变量是不稳定的,不管编译器怎么优化每次得从内存中读取这个变量值。

        总结:当变量被volatile修饰时,编译器不会再用刀变量时直接从寄存器里面拿,而是直接去取内存地址里的值,通过这种方法取到的值一定是最新的,实际的值。

8.struct 结构体

Struct 结构体名{
成员列表;
}变量名列表;

        用法一:这里使用struct关键字定义了一个结构体变量Date, 这个日期包含了年、月、日几个成员,然后定义变量名Today,来给结构体成员赋值。当然可以不止定义这一个变量,比如:

struct Data Today,tomorrow;

struct Data
{
    uint16_t  Year;
    uint8_t  Mon;
    uint16_t Day;
};

int main()
{
    struct Data Today;
    Today.Year = 2024;
    Today.Mon  = 5;
    Today.Day  = 24;    
}

        用法二: 通过typedef 声明结构体Date为新的类型名来代替原有的类型名Dat(Dat可以省略)。然后在结构体定义时直接通过Date来定义就可以了(也可以用原有类型名Dat来定义:Dat Today;)。

        这种是使用最多的方法,这种方式定义结构体时语法比较简单,通过自定义的类型名我们也可以很直观的看出来这个结构体的作用。

typedef struct Dat
{
    uint8_t  Year;
    uint8_t  Mon;
    uint16_t Day;
}Data;

int main()
{
    Data Today;
    Today.Year = 2024;
    Today.Mon  = 5;
    Today.Day  = 24;  
    //Data Today = { 2024,5,24 } ; 
}

 其中被注释的语句是另一种赋值方法;

        结构体与数组区别:数组是相同数据类型的集合,而结构体则是不同数据类型的集合;就是由于数组不能有不同数据类型的集合,结构体就是在此基础上诞生的。

int a = { 1,2,3,4,5,6  };

typedef struct{
    int x;
    char y;
    float z;
}struct_name;//typedef给结构体重新取名为struct_name

 当然,结构体中也可以是数组,结构体,即结构体数组以及包含结构体的结构体。

结构体数组

        定义结构体数组一般形式是:

stuct        结构体名

{
        成员列表;
}数组名[数组长度];

 例如:

struct Person
{
    char name[20];//名字
    char gender[20];//性别
    float hight;//身高
};

struct Person people[3] = { {"A","boy",185}, {"B","boy",180}, {"C","girl",170} };

main()
{
    OLED_Init();

    while(1)
    {
        OLED_ShowNum(0,16,people[1].hight,16);
		OLED_Refresh();//更新显示
    }
}

 其中定义了一个结构体数组,分别存有姓名、性别以及身高;结构体的声明可以放在函数内或函数外;由于字符串是以字符结束的,而字符不显示,故一个“A”其实占两个字节,故数组name[ ]最小为2;

结构体指针

        通过指向结构体变量的指针变量输出结构体变量中成员的信息。

struct student
{
    char name[4];
    char age;
}*P;

//或者写成
struct student
{
    char name[4];
    char age;
};

student *p;

 如何使用指针访问结构体成员呢?

        方法一:        (*p).name = "ABC";

        方法二:        p->name = "ABC";

结构体的嵌套

比如定义一个结构体包含一个人名字和生日,生日又分年月日,故我们可以把生日定义为一个结构体实现结构体的嵌套。

struct birthday
{
	u8 month;
	u8 day;
};

typedef struct
{
    u8 name[3];//名字
    struct birthday bir;
} Person;

那么如何引用呢?

Person people;
people.bir.month = 12;

 9.enum  枚举

        具有有限个整型符号常量的集合,这些整型符号常量就称为枚举常量。

        定义方式:

enum 枚举类型名
{
    枚举常量名1,
    枚举常量名2,
    ...
};

枚举类型有什么用?

比如数字1,在别人看来就是数字1,也可能是星期一,也可能是一月等,会让人难以会意你真正的意思。故为了提高程序的可读性,引入非数值量(一些有意义的符号)是很有必要的。

例如在按键控制实验中:我们可以定义枚举用来代替0和1,之前可能需要判断某个引脚是否为0或1去判断按下与松开,如今直接判断是否等于DOWN或者NO_DOWN就可以了,是不是增强了代码的可读性呢?

enum
{
	NO_DOWN = 1,
	DOWN = 0
};

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值