三态门
前面我们说到外设芯片的数据总线在没有被选中时其处于高阻态,当被选中时,其电平可能是高(1)或是低(0)。如此一来,我们说外设的数据总线其芯片管脚是属于三态门的,即存在高电平、低电平和高阻态,三个状态。
静态全局变量
将全局变量的作用域缩减到了仅当前源文件可见,其它文件不可见;静态全局变量的优势是增强了程序的安全性和健壮性。
电平的有效性
前面我们了解了什么是片选信号,也讲到了三态门,需要指出的是片选信号通常不是三态门,其只存在两个状态,即高电平或是低电平。前面我们也说了,片选信号是用来“开门”的,而片选信号又有高和低电平,那到底是高电平表示“开门”呢?还是低电平?
对于这一问题,我们称如果一个电平对于一个片选信号表示“开门”那么它就是这一信号的有效电平。比如,对于一个片选信号,如果低电平表示“开门”,那么我们说这个片选信号是低电平有效的。虽然,在这里我们用片选信号来解释电平的有效性,但是很多信号都存在有效性的问题,比如,后面我们将要谈的读信号和写信号都存在有效性问题。
static修饰函数
让函数仅在本文件可见, 其它文件无法对其进行调用,例如在example1.c文件里面进行了如下定义:
static void gt_fun(void)
{
...
}
那么gt_fun这个函数就只能在example1.c中被调用,在example2.c中就无法调用这个函数。而如果不使用static来修饰这个函数,那么只需要在example2.c中使用extern关键字写下语句extern void gt_fun(void);即可调用gt_fun这个函数。
extern关键词
在C语言中, extern关键字用于指明函数或变量定义在其它文件中,提示编译器遇到此函数或者变量的时候到其它模块去寻找其定义,这样被extern声明的函数或变量就可以被本模块或其它模块使用。因而, extern关键字修饰的函数或者变量是一个声明而不是定义,例如:
/* example.c */
uint16_t a = 0;
uint16_t max(uint16_t i, uint16_t j) {
return ((i>j)?i:j);
}
而在main.c中,如果没有include example.c,但又想使用example.c中定义的变量,则使用extern关键词:
/* main.c */
#include <stdio.h>
extern uint16_t a;
extern uint16_t max(uint16_t i, uint16_t j);
void main(void) {
printf("a=%d\r\n", a);
printf("Max number between 5 and 9: %d\r\n", max(5, 9));
}
extern关键字还有一个重要的作用,就是如果在C++程序中要引用C语言的文件,则需要用以下格式:
#ifdef __cplusplus
extern "C"{
#endif
......
#ifdef __cplusplus
}
#endif
这段代码的含义是,如果当前是C++环境( _cplusplus是C++编译器中定义的宏),要编译花括号{}里面的内容需要使用C语言的文件格式进行编译,而extern “C”就是向编译器指明这个功能的语句。
volatile关键词
volatile原意是“易变的”,在嵌入式环境中用volatile关键字声明的变量,在每次对其值进行引用的时候都会从原始地址取值。由于该值“易变”的特性所以,针对其的任何赋值或者获取值操作都会被执行(而不会被优化)。由于这个特性,所以该关键字在嵌入式编译环境中经常用来消除编译器的优化,可以分为以下三种情景:
修饰硬件寄存器;
修饰中断服务函数中的非自动变量;
在有操作系统的工程中修饰被多个应用修改的变量;
在有操作系统(比如RTOS、 UCOS-II、 Linux等)的程序中,如果有多个任务对同一个变量进行赋值或取值,那么这一类变量也应使用volatile来修饰保证其可见性。所谓可见即:当前任务修改了这一变量的值,同一时刻,其它任务此变量的值也发生了变化。