ODR 是一个端口输出数据寄存器,也只用了低 16 位。该寄存器为可读写,从该寄存器读出来的数据可以用于判断当前 IO 口的输出状态。而向该寄存器写数据,则可以控制某个 IO 口的输出电平。该寄存器的各位描述如图 6.1.3 所示:
端口输出数据寄存器(GPIOx_ODR)
ODR15
ODR14
ODR13
ODR12
ODR11
ODR10
ODR9
ODR8
ODR7
ODR6
ODR5
ODR4
ODR3
ODR2
ODR1
ODR0
位31:16
保留,始终读为0。
位15:0
ODRy[15:0]:端口输出数据(y = 0…15) (Port output data)
这些位可读可写并只能以字(16位)的形式操作。
注:对GPIOx_BSRR(x = A…E),可以分别地对各个ODR位进行独立的设置/清除。
c语言实用位操作
&:按位与 ~:取反 |:按位或 <>:右移
清零操作:&运算实现清零--------GPIOA->ODR&=0XFF0F;//将4-7位清零
置一操作:|运算实现置一---------GPIOA->ODR|=0X0040;//将第6位置一
实用移位操作可以提高代码可读性----GPIOA->ODR|=1<<5;//第五位置一
宏定义define讲解:
1:不带参数的宏定义 格式:#define 标示符 字符串
作用:在编译预处理时,将源程序中所有的标示符换成字符串
例如:
#define PI 3.148 //PI即为3.148
#define uchar unsigned char //在定义数据类型时,uchar 等效于 unsigned char
注意:编译与处理时,不做语法检查,只是简单的字符替换,只有在编译时才对已经展开宏名(比如已经将源程序中的PI替换成3.148)的源程序进行语法检查
宏定义时可以引用已经定义的宏名:
#define PI 3.148
#define X 2.0
#define ALL PI*X
2:带参数的宏定义 一般格式:#define 标示符(参数表) 字符串
作用:在编译预处理时,将源程序中所有标示符替换成字符串,并且将字符串中的参数用实际用的参数替换
例如:#define s(a,b) (a*b)/2
若程序中使用了s(3,4),在编译预处理时,将替换为(3*4)/2
extern:
C语言中extern可以置于变量和函数之前,用以表示变量或则函数定义在别的文件中,提示编译器遇到此变量和函数时在其他模块寻找定义。
注意:extern声明变量可以多次,但是定义只有一次
变量存储类型:
auto型:在动态存储区中 register型:在寄存器中 satic型和extern型;在静态存储器中
局部变量默认存储类型:auto 全局变量默认存储类型:extern
auto和register型只用于定义局部变量
static型即可定义局部变量(值将被保留,而且只第一次进入此函数时初始化该变量,也就是只操作一次),也可定义全局变量,定义全局变量时它的有效范围
为它所在的源文件,其他源文件不能使用
注意:auto类型分配在栈上, 属于动态存储类别, 占动态存储区空间, 函数调用结束后自动释放, 而static分配在静态存储区, 在程序整个运行期间都不释放
函数:
若函数存储类型为satic型,则为内部函数或静态函数,他表示由多个源文件组成的一个程序,该函数只能在其所在的文件中使用,在其他文件终不能使用
若函数的存储类型为extern型,则为外部函数,他表示该函数能被其他源文件调用。
函数默认存储类型:extern
结构体:
1,在程序中使用结构体,必须对结构体的组成进行描述,这个描述过程为结构体类型定义。
形式: struct person
{
long no;
char name[12];
};
在上面的例子中,struct为关键字,person为结构体名,no,name为成员。
注意:与其他变量不同,定义结构体类型,并不意味着系统将分配一段内存单元来存放各个数据成员,这只是定义类型而不是结构体变量。他告诉系统该结构有哪些成员构成,并把它们当做一个整体来处理。
2.结构体变量定义:一旦定义了结构体,就可以定义结构体变量,可以采用不同方式定义结构体变量。
A- struct person stu,worker;
上面定义了两个结构体变量(stu,worker),它们是结构体 struct person(此如同int一样,代表类型名) 的变量。
B-
struct person
{
long no;
char name[12];
}teacher,doctor;
上面定义了两个结构体变量(teacher,doctor)。
C-
struct
{
long no;
char name[12];
}teacher,doctor;
上面只是定义了teacher和doctor两个变量为结构体类型,但没有定义该结构体类型的名字,所以不能再用来定义其他变量,struct stu 是不合法的。
3,结构体变量初始化:
struct person
{
long no;
char name[12];
};
***********************************************************************************
A: struct person teacher ={"4300","LI MING"};
B:
struct person
{
long no;
char name[12];
} teacher ={"4300","LI MING"};
注意:不能直接对结构体变量赋予一组常量:teacher ={"4300","LI MING"};
4,结构体变量引用:
struct
{
long no;
char name[12];
}teacher,doctor,*w;(指针w指向结构体变量doctor)
A:doctor.no B:(*w).no C:doctor->no 是对结构体变量doctor的no成员的正确引用。
补充:
指针变量的定义:[存储类型] 数据类型 *指针变量名[=初值];
指针变量使用:
赋值:(1) int i,*p;
p=&i;
(2) int i,*p=&i;
将指针p指向变量i的地址。
引用:
(1)*p-------代表所指变量的值
(2)p--------代表所指变量的地址
typedef:类型别名
typedef用于为现有的类型创建一个新的名字,或称为类型别名。这样可以简化变量的定义,一般用在结构体上。
例如:
typedef struct
{
long no;
char name[12];
}GPIO_TYPEDEF;
typedef 为结构体定义了一个别名叫GPIO_TYPEDEF,这样就可以通过GPIO_TYPEDEF来定义结构体了。
例如;GPIO_TYPEDEF teacher,doctor;
这里GPIO_TYPEDEF与struct person是等同的作用。