学习了几个端口相关的工程后,把过程中的C语言相关的点记录下来。后续可以继续增加。
1/ typedef
typedef int size// size和int有一样的意义,这样size就可以去做类型申明了,比如size a,和int a,是一样的。
2/enum 枚举
枚举的意思是这个变量的变化值是有限的,就是在所列的枚举值列表里面。enum 枚举名{枚举值1,枚举值2,枚举值3,.....}
enum weekday{ sun,mon,tue,wed,thu,fri,sat }; /// enum weekday a,b,c; /// enum weekday{ sun,mon,tue,wed,thu,fri,sat }a,b,c; /// enum { sun,mon,tue,wed,thu,fri,sat }a,b,c; 这几种申明都是可以的。
a=sum, b=wed //赋值
另外枚举类型的元素是由默认值的。如果没有特殊说明,第一个sum=0,mon=1,tue=2。如果sun定义成10,后面就是 11,12了。
枚举和结构体是不一样的。结构体中的元素,都是属于这个结构体的某一部分。而枚举的意思就是,这个变量的赋值,从赋值表里面挑取一个。
3/ typedef 和enum,比如GPIO速率选择的赋值。
typedef enum { GPIO_Low_Speed = 0x00, /*!< Low speed */ GPIO_Medium_Speed = 0x01, /*!< Medium speed */ GPIO_Fast_Speed = 0x02, /*!< Fast speed */ GPIO_High_Speed = 0x03 /*!< High speed */ }GPIOSpeed_TypeDef; GPIOSpeed_TypeDef GPIO_Speed; //GPIO_Speed是一个枚举型变量
//效果和如下是一样的/////////////////////////
enum
{
GPIO_Low_Speed = 0x00, /*!< Low speed */
GPIO_Medium_Speed = 0x01, /*!< Medium speed */
GPIO_Fast_Speed = 0x02, /*!< Fast speed */
GPIO_High_Speed = 0x03 /*!< High speed */
}GPIO_Speed; //GPIO_Speed是一个枚举型变量
4/ typedef struct
typedef struct { uint32_t GPIO_Pin; /*!< Specifies the GPIO pins to be configured. This parameter can be any value of @ref GPIO_pins_define */ GPIOMode_TypeDef GPIO_Mode; /*!< Specifies the operating mode for the selected pins. This parameter can be a value of @ref GPIOMode_TypeDef */ GPIOSpeed_TypeDef GPIO_Speed; /*!< Specifies the speed for the selected pins. This parameter can be a value of @ref GPIOSpeed_TypeDef */ GPIOOType_TypeDef GPIO_OType; /*!< Specifies the operating output type for the selected pins. This parameter can be a value of @ref GPIOOType_TypeDef */ GPIOPuPd_TypeDef GPIO_PuPd; /*!< Specifies the operating Pull-up/Pull down for the selected pins. This parameter can be a value of @ref GPIOPuPd_TypeDef */ }GPIO_InitTypeDef; GPIO_InitTypeDef GPIO_InitStructure; //GPIO_InitStructure 是一个结构体变量
5/ 向函数传入结构体的指针。以下是一个标准的将结构体指正作为参数传入函数的做法。
struct funds{ //定义一个结构体 char aaa; double bbb; char ccc; double ddd; }; double sum(struct funds *money) //函数使用一个指向funds结构的指针money作为其唯一的参数 { do something // 函数体 } struct funds stan = { ...} // 赋值 sum(&stan) // 传入参数,这样指针money就指向了结构stan
嵌入式中的常用做法如下:
// typedef 以及结构体申明1,结构体元素删掉了一部分 typedef struct { __IO uint32_t LCKR; /*!< GPIO port configuration lock register, Address offset: 0x1C */ __IO uint32_t AFR[2]; /*!< GPIO alternate function registers, Address offset: 0x20-0x24 */ } GPIO_TypeDef; //typedef以及结构体申明2,结构体元素删除了一部分 typedef struct { uint32_t GPIO_Pin; /*!< Specifies the GPIO pins to be configured. This parameter can be any value of @ref GPIO_pins_define */ GPIOMode_TypeDef GPIO_Mode; /*!< Specifies the operating mode for the selected pins.ameter can be a value of @ref GPIOMode_TypeDef */ }GPIO_InitTypeDef;
//函数体
void GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct)
{
}
//结构体赋值以及函数调用 #define GPIOF ((GPIO_TypeDef *) GPIOF_BASE) //GPIOF_BASE是寄存器基地址
//联想一下struct guy *him 这个时候him是个指针,可以指向任何guy类型的指针
//由此可见GPIOF(就是GPIOF_BASE)原本是一个寄存器地址,被强制转换成GPIO_TypeDef类型的指针,而且地址已经确定了
//现在GPIOF是一个指向GPIO_TypeDef类型的指针,而且地址已经确定了,把GPIOF传入到函数中,对其元素的操作,可以去地址偏移上去理解,这样就完成了对寄存器的操作.
//比如GPIOx->MODER就是MODER这个寄存器的地址。
//所以在GPIO_TypeDef中,寄存器的位宽以及寄存器的顺序,都是一定的,不能随便换的。
GPIO_InitTypeDef GPIO_InitStructure; //定义一个结构体变量
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;//给结构体元素赋值
GPIO_Init(GPIOF, &GPIO_InitStructure); //函数调用,传入结构体地址
这样就完成了寄存器的访问和赋值。
6/结构体数组
因为在结构体定义中,已经对元素的顺序有定义,所以可以直接进行这样的赋值,方便快捷。最后调用初始化函数,把所有管脚的初始化都搞定了。
const GPIO_InitTypeDef GpioPortAMode[]= { /*Pin Mode Pull Speed Alternate*/ {GPIO_PIN_0, GPIO_MODE_AF_PP, GPIO_NOPULL, GPIO_SPEED_HIGH, GPIO_AF7_USART2 }, /* UART2_CTS*/ {GPIO_PIN_1, GPIO_MODE_AF_PP, GPIO_NOPULL, GPIO_SPEED_HIGH, GPIO_AF7_USART2 }, /* UART2_RTS*/ {GPIO_PIN_2, GPIO_MODE_AF_PP, GPIO_NOPULL, GPIO_SPEED_HIGH, GPIO_AF7_USART2 }, /* UART2_TX */ {GPIO_PIN_3, GPIO_MODE_AF_PP, GPIO_NOPULL, GPIO_SPEED_HIGH, GPIO_AF7_USART2 }, /* UART2_RX */ };