STM32编程中枚举和结构体的结合
01、结构体定义
基本定义:结构体,通俗讲就像是打包封装,把一些有共同特征(比如同属于某一类事物的属性,往往是某种业务相关属性的聚合)的变量封装在内部,通过一定方法访问修改内部变量。
结构体的定义:
第一种:只有结构体定义
struct stuff{ char *name; //姓名int num; //学号
int age; //年龄
float score; //成绩
};
第二种:附加该结构体类型的“结构体变量”的初始化的结构体定义,如下代码也就是定义结构体时,直接定义一个变量
struct stuff{ char *name; //姓名int num; //学号
int age; //年龄
float score; //成绩
}xiaoming;
其实这就相当于先定义结构体,再用结构体定义一个结构体变量:
struct stuff{ char *name; //姓名int num; //学号
int age; //年龄
float score; //成绩
};
struct stuff xiaoming;
第三种:使用typedef关键字,可以将结构体变量定义时少写一个struct,比较省事。
typedef struct stuff{ char *name; //姓名int num; //学号
int age; //年龄
float score; //成绩
}stuff_s;
stuff_s xiaoming;
使用typedef还可以进一步简化,将结构体名也省略,这也是常用的方式
typedef struct{ char *name; //姓名int num; //学号
int age; //年龄
float score; //成绩
}stuff_s;
stuff_s xiaoming;
STM32的标准外设库有大量这样的应用,如下
typedef struct{
uint32_t GPIO_Pin;
GPIOMode_TypeDef GPIO_Mode;
GPIOSpeed_TypeDef GPIO_Speed;
GPIOOType_TypeDef GPIO_OType;
GPIOPuPd_TypeDef GPIO_PuPd;
}GPIO_InitTypeDef;
关于结构体指针定义问题,有很多的“骚操作”的写法,我一般按照下面定义指针
stuff_s *cuerrent_student;
02、结构体初始化
在大部分应用中,一般都是定义结构体后,在代码中进行初始化,如下所示
typedef struct{ char *name; //姓名int num; //学号
int age; //年龄
float score; //成绩
}stuff_s;
stuff_s xiaoming;
void xiaoming_inf_init()
{
xiaoming.name = "xiaoming";
xiaoming.num = 1;
xiaoming.age = 18.0;
xiaoming.score = 100;
}
当然也有可以定义时就进行数据初始化的
typedef struct{ char *name; //姓名int num; //学号
int age; //年龄
float score; //成绩
}stuff_s;
stuff_s xiaoming={"xiaoming",1,18.0,100};
C99和C11为结构提供了指定初始化器(designatedinitializer)。其初始化器使用点运算符和成员名。
关于C99和C11的知识可以看我之前的文章《C语言的发展》,在IAR和Keil中记得勾选C99的选项。
例如,只初始化xiaoming结构中的name成员,可以这样做:
stuff_s xiaoming={
.name
= "xiaoming"};
也可以按照任意顺序使用指定初始化器:
stuff_s xiaoming={
.age
= 18.0,.name
= "xiaoming"};
这样的赋值方式,在linux方式中很常见,以platform驱动框架为例:
staticstruct platform_driver leds_platform_driver = {.driver
= {.name
= "imx6ul-led",.of_match_table
= leds_of_match,},
.probe
= leds_probe,.remove
= leds_remove,};
03、访问结构体成员
结构体成员的访问需要借助结构体成员运算符(.),如下
stuff_s xiaoming,xiaohong;void student_inf_init(){
xiaoming.name
= "xiaoming";xiaoming.num
= 1;xiaoming.age
= 18.0;xiaoming.score
= 100;xiaohong.name
= "xiaohong";xiaohong.num
= xiaoming.num+1;}
使用指针时,使用(->)符号访问结构体成员
stuff_s xiaoming,xiaohong;stuff_s
*cuerrent_student;void student_inf_init(){
xiaoming.name
= "xiaoming";xiaoming.num
= 1;xiaoming.age
= 18.0;xiaoming.score
= 100;cuerrent_student
= &xiaohong;cuerrent_student
->name = "xiaohong";cuerrent_student
->num = xiaoming.num+1;}
04、枚举与结构体的结合
简单介绍下枚举:有些数据的取值往往是有限的,只能是非常少量的整数,并且最好为每个值都取一个名字,以方便在后续代码中使用,比如一个星期只有七天,一年只有十二个月,一个班每周有六门课程等。
当然,你可以用宏定义
#define Mon 1#define Tues 2
#define Wed 3
#define Thurs 4
#define Fri 5
#define Sat 6
#define Sun 7
如果用了枚举则如下
enum week{Mon,
Tues,
Wed,
Thurs,
Fri,
Sat,
Sun
};
枚举是一种类型,通过它可以定义枚举变量:
enum week a, b, c;
那么枚举和结构体一起用会产生什么效果呢?假设我们要协议一个语音芯片的驱动,需要表示语音芯片的状态
typedef enum//语音芯片状态{
VOICE_INIT_OK = 0x4A, //语音芯片上电初始化成功后,自动回传命令
VOICE_RECEIVE_OK = 0x41, //语音芯片收到正确的命令帧
VOICE_ORDER_ERROR= 0x45, //语音收到错误的命令帧
VOICE_BUSY = 0x4E, //语音忙(正在合成状态)
VOICE_FREE = 0x4F//语音空闲
} VOICE_STATUS;
typedef struct {
VOICE_STATUS status ; //!< 语音芯片状态
Ouint32 delayTicks; //!< 播放时间
Ouint32 playtimes; //!< 播放次数
} voicechip_Para_S;
voicechip_Para_S voicechip_Para;
那么改变语音芯片状态时,我们可以按照下面这样写
voicechip_Para.status = VOICE_RECEIVE_OK;
判断语音芯片状态时,我们可以按照下面写
if((voicechip_Para.status == VOICE_FREE)
当然,你用宏定义是可以的,代码也很整洁。这里希望你能理解文章最开始的那句话:结构体是某种业务相关属性的聚合。
05、骚操作
关于结构体有很多骚操作,如果全部总结下来,这篇文章就会很臃肿,例如结构体嵌套的骚操作,可以一边定义结构体B,一边就使用上:
struct A{ struct B{ int c;}b;
struct B sb;}a;
对于这样的情况,我一般主张能看懂就行,自己写代码时就少点这样的骚操作
struct B{ int c;}b;
struct A{ struct B sb;}a;
点击查看专题:C语言进阶
以上是 STM32编程中枚举和结构体的结合 的全部内容, 来源链接: utcz.com/z/520135.html