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是等同的作用。