目录
位操作
6种位操作运算符
- 位操作
- 数值操作
位操作即按位进行运算操作
GPIO->CRL &= 0xFFFFFF0F
上面这句代码的意思是将GPIO的CRL寄存器的对应位清0
看到&=操作,就要马上想到这是一个清0操作,那么具体是将哪些位清0呢?再去看后面的十六进制数中的那些位是为0的
GPIOA->CRL |= 0x00000040
上面这句话的意思是将GPIO的CRL寄存器的对应位置1
看到|=操作,就要马上想到这是一个置1操作,那么具体是将哪些位置1呢?再去看看后面的十六进制数中那些位是为1的
这些位操作运算符在固件库里面用得特别多,就是那些stm32f10x_xx.c文件
包括取反运算符,在定时器固件库里用得特别多
define宏定义关键词
define是C语言的预处理命令,用于宏定义,可以提高代码可读性
#define 标识符 字符串
例如
#define SYSCLK_FREQ_72MHz 72000000
凡是程序中出现了SYSCLK_FREQ_72MHz的地方,都会被替换为72000000
ifdef条件编译
当满足条件时对一组语句进行编译,而当条件不满足时对另一组语句进行编译
#ifdef 标识符
程序段1
#else
程序段2
#endif
ifndef也是同样的道理
打开Keil,魔术棒,C/C++选项,里面的Preprocessor Symbols就是预处理符号,里面的Define的内容可以被整个工程识别
extern变量声明
extern修饰变量或函数,表示变量或函数的定义是在别的文件中,提示编译器遇到此变量或函数时在别的文件中寻找其定义
注意:extern的变量声明可以有很多次,但是定义只能出现一次
首先是定义,我们定义一个名为id的变量:
在main.c文件中
u8 id; // 此处为定义,有且只有一次
main{
id = 1;
printf("%d",id); // id = 1
test();
printf("%d",id); // id = 2
}
在test.c文件中
extern u8 id; // 注意,这里是使用extern关键字在声明
void test(void){
id = 2;
}
注意,这里是使用extern关键字在声明
这样就可以在test.c文件中操作这个变量
typedef类型
结构体
使用结构体的本质是利用面向对象的思想对描述事物
Struct 结构体名{
成员列表1;
成员变量2;
...
}变量名列表;
在结构体声明的时候可以定义变量,也可以在声明之后定义,定义的方法为:
Struct 结构体名字 结构体变量列表;
结构体的优势:
1. 将无序的不同类型的变量放在一起,让程序更加有序可读
2. 提高程序的扩展性
例如,对于结构体的定义如下所示
GPIO_TypeDef结构体
/**
* @brief General Purpose I/O
*/
typedef struct
{
__IO uint32_t CRL;
__IO uint32_t CRH;
__IO uint32_t IDR;
__IO uint32_t ODR;
__IO uint32_t BSRR;
__IO uint32_t BRR;
__IO uint32_t LCKR;
} GPIO_TypeDef;
GPIO_InitTypeDef结构体
/**
* @brief GPIO Init structure definition
*/
typedef struct
{
uint16_t GPIO_Pin; /*!< Specifies the GPIO pins to be configured.
This parameter can be any value of @ref GPIO_pins_define */
GPIOSpeed_TypeDef GPIO_Speed; /*!< Specifies the speed for the selected pins.
This parameter can be a value of @ref GPIOSpeed_TypeDef */
GPIOMode_TypeDef GPIO_Mode; /*!< Specifies the operating mode for the selected pins.
This parameter can be a value of @ref GPIOMode_TypeDef */
}GPIO_InitTypeDef;
以结构体作为入口参数传入
void GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct)
这里第二个入口参数用于描述IO口的模式特性,例如模式,速度,上下拉等
若不用结构体作为入口参数,那么此时我们就需要非常多的入口参数,例如int xx , int xx
此时若要再增加参数,则所有的函数的定义和所有的声明都要修改,无数个调用这个函数的地方都要修改,此时这个代码的扩展性就非常差
这方面就可以通过结构体来解决这个问题,我们只需要去改变结构体的成员变量即可,声明就不需要做任何修改
我们去增加结构体的成员变量,对于原程序是没有任何影响的
这也是为什么库函数都是使用结构体或结构体指针作为函数入口参数的原因
static关键字
static声明的局部变量,存储在静态存储区,在函数调用结束后,不会被释放,具有记忆功能
static修饰的函数一般在内部使用