寄存器,是集成電路中非常重要的一種存儲(chǔ)單元,通常由觸發(fā)器組成。在集成電路設(shè)計(jì)中,寄存器可分為電路內(nèi)部使用的寄存器和充當(dāng)內(nèi)外部接口的寄存器這兩類。內(nèi)部寄存器不能被外部電路或軟件訪問,只是為內(nèi)部電路的實(shí)現(xiàn)存儲(chǔ)功能或滿足電路的時(shí)序要求。而接口寄存器可以同時(shí)被內(nèi)部電路和外部電路或軟件訪問,CPU中的寄存器就是其中一種,作為軟硬件的接口,為廣泛的通用編程用戶所熟知。本文主要詳解寄存器操作方法以及對(duì)寄存器操作的通用方法總結(jié),具體的跟隨小編來了解一下。
一、寄存器操作
1、#define方法
1)寄存器地址的定義:
#define UART_BASE_ADRS (0x10000000) /* 串口的基地址 */
#define UART_RHR *(volatile unsigned char *)(UART_BASE_ADRS + 0) /* 數(shù)據(jù)接受寄存器 */
#define UART_THR *(volatile unsigned char *)(UART_BASE_ADRS + 0) /* 數(shù)據(jù)發(fā)送寄存器 */
2)寄存器讀寫操作:
UART_THR = ch; /* 發(fā)送數(shù)據(jù) */
ch = UART_RHR; /* 接收數(shù)據(jù) */
也可采用定義帶參數(shù)宏實(shí)現(xiàn)
#define WRITE_REG(addr, ch) *(volatile unsigned char *)(addr) = ch
#define READ_REG(addr, ch) ch = *(volatile unsigned char *)(addr)
3)對(duì)寄存器相應(yīng)位的操作方法:
定義寄存器
#define UART_LCR *(volatile unsigned char *)(UART_BASE_ADRS + 3) /* 線控制寄存器 */
定義寄存器相應(yīng)位的值
#define CHAR_LEN_5 0x00
#define CHAR_LEN_6 0x01
#define CHAR_LEN_7 0x02
#define CHAR_LEN_8 0x03 /* 8 data bit */
#define LCR_STB 0x04 /* Stop bit control */
#define ONE_STOP 0x00 /* One stop bit! */
#define LCR_PEN 0x08 /* Parity Enable */
#define PARITY_NONE 0x00
#define LCR_EPS 0x10 /* Even Parity Select */
#define LCR_SP 0x20 /* Force Parity */
#define LCR_SBRK 0x40 /* Start Break */
#define LCR_DLAB 0x80 /* Divisor Latch Access Bit */
定義寄存器相應(yīng)位的值另一種方法
#define CHAR_LEN_5 0〈〈0
#define CHAR_LEN_6 1〈〈0
#define CHAR_LEN_7 1〈〈1
#define CHAR_LEN_8 (1〈〈0)|(1〈〈1) /* 8 data bit */
#define LCR_STB 1〈〈2 /* Stop bit control */
#define ONE_STOP 0〈〈2 /* One stop bit! */
#define LCR_PEN 1〈〈3 /* Parity Enable */
#define PARITY_NONE 0〈〈3
#define LCR_EPS 1〈〈4 /* Even Parity Select */
#define LCR_SP 1〈〈5 /* Force Parity */
#define LCR_SBRK 1〈〈6 /* Start Break */
#define LCR_DLAB 1〈〈7 /* Divisor Latch Access Bit */
對(duì)寄存器操作只需對(duì)相應(yīng)位或賦值
UART_LCR = CHAR_LEN_8 | ONE_STOP | PARITY_NONE; /* 設(shè)置 8位數(shù)據(jù)位,1位停止位,無校驗(yàn)位 */
4)對(duì)寄存器某一位置位與清零
對(duì)某一寄存器第7位置位
XX_CRTL |= 1〈〈7;
XX_CRTL &= ~(1〈〈7);
UART_LCR |= LCR_DLAB; /* 時(shí)鐘分頻器鎖存使能 */
UART_LCR &= ~(LCR_DLAB); /* 禁止時(shí)鐘分頻器鎖存 */
5 判斷寄存器某一位是否置位或?yàn)?的方法
#define UART_LSR *(volatile unsigned char *)(UART_BASE_ADRS + 5) /* 線狀態(tài)寄存器 */
#define LSR_DR 1〈〈0 /* Data Ready */
當(dāng)UART_LSR的第0位為1時(shí)結(jié)束循環(huán)
while (!(UART_LSR & LSR_DR)) /* 等待數(shù)據(jù)接收完 */
2、共用體結(jié)構(gòu)體位域的應(yīng)用實(shí)例
【例】設(shè)count 是一個(gè)16 位的無符號(hào)整型計(jì)數(shù)器,最大計(jì)數(shù)為十六進(jìn)制0xffff,要求將這個(gè)計(jì)數(shù)值以十六進(jìn)制半字節(jié)的形式分解出來。
對(duì)于上述實(shí)例通常采用移位的方法求解,而采用共用體結(jié)構(gòu)體位域的方法不需要通過移位運(yùn)算。以下,對(duì)CCS 在頭文件中大量使用的共用體結(jié)構(gòu)體位域進(jìn)行注解。
先定義一個(gè)共用體結(jié)構(gòu)體位域:
…
Uint16 cont,g,s,b,q; //16 位無符號(hào)整型變量定義
cont=0xfedc; //對(duì)cont 賦值
…
union //共用體類型定義
{ Uint16 i; //定義i 為16 位無符號(hào)整型變量
struct //結(jié)構(gòu)體類型定義
{
Uint16 low:4; //最低4 位在前。從最低4 位開始,取每4 位構(gòu)成半字節(jié)
Uint16 mid0:4;
Uint16 mid1:4;
Uint16 high:4; //最高4 位在后
}HalfByte; //HalfByte 為具有所定義的結(jié)構(gòu)體類型的變量
}Count; //Count為具有所定義的共用體類型的變量
union 定義一個(gè)共用體類型,它包含兩個(gè)成員:一個(gè)是16 位無符號(hào)整型變量i,另一個(gè)是包含4 個(gè)半字節(jié)變量(low,mid0,mid1,high)的結(jié)構(gòu)體類型。它們占用同一個(gè)內(nèi)存單元,通過對(duì)i(Count.i)進(jìn)行賦值,可以完成對(duì)結(jié)構(gòu)體4 個(gè)變量的賦值。
上面的程序,在定義共用體類型和結(jié)構(gòu)體類型的同時(shí),直接完成了這兩個(gè)類型變量的定義,而未定義共用體和結(jié)構(gòu)體類型名。即HalfByte 是一個(gè)具有所定義的結(jié)構(gòu)體類型的變量,Count 是一個(gè)具有所定義的共用體類型的變量。理解了共用體與結(jié)構(gòu)體之間的關(guān)系,下面的賦值指令就清楚了。
Count.i = cont; //對(duì)共用體類型成員i 進(jìn)行賦值
g = Count.HalfByte.low; //將cont 的0~3 位賦值給g,g=0x000c
s = Count.HalfByte.mid0; //將cont 的4~7 位賦值給s,s=0x000d
b = Count.HalfByte.mid1; //將cont 的8~11 位賦值給b,b=0x000e
q = Count.HalfByte.high; //將cont 的12~15 位賦值給q,q=0x000f
通過共用體結(jié)構(gòu)體定義,當(dāng)對(duì)共用體類型成員i 進(jìn)行賦值時(shí),由于結(jié)構(gòu)體類型變量HalfByte 與i 占用同一個(gè)內(nèi)存單元,因此,也就完成了對(duì)HalfByte 的各成員的賦值。
C 語言的共用體結(jié)構(gòu)體位域定義,可以完成對(duì)寄存器位域的訪問。至于被訪問的位域在內(nèi)存中的具體位置則由編譯器安排,編程者可以不必關(guān)注。
下面是一個(gè)訪問寄存器位域的例子,供讀者參考。
先建立一個(gè)共用體結(jié)構(gòu)體位域定義,將某個(gè)寄存器的16 位,從最低位到最高位分別
定義為Bit1,Bit2,…,Bit16。
union //共用體類型定義
{ Uint16 all; //定義all 為16 位無符號(hào)整型變量
struct //結(jié)構(gòu)體類型定義
{
Uint16 Bit1:1; //0 位Bit1 取寄存器最低位0 位,以下順序取1 位直到最高位
Uint16 Bit2:1; //1
Uint16 Bit3:1; //2
Uint16 Bit4:1; //3
Uint16 Bit5:1; //4
Uint16 Bit6:1; //5
Uint16 Bit7:1; //6
Uint16 Bit8:1; //7
Uint16 Bit9:1; //8
Uint16 Bit10:1; //9
Uint16 Bit11:1; //10
Uint16 Bit12:1; //11
Uint16 Bit13:1; //12
Uint16 Bit14:1; //13
Uint16 Bit15:1; //14
Uint16 Bit16:1; //15
}bit; //bit為具有所定義的結(jié)構(gòu)體類型的變量
}CtrlBit; //CtrlBit 為具有所定義的共用體類型的變量
有了上面的定義之后,要訪問某一個(gè)位或某些位就很容易了。比如要置Bit4,Bit8,Bit12 及Bit16 為1,可用兩種方法進(jìn)行:
方法一:
CtrlBit.bit.Bit4 = 1;
CtrlBit.bit.Bit8 = 1;
CtrlBit.bit.Bit12 = 1;
CtrlBit.bit.Bit16 = 1;
二、對(duì)寄存器操作的通用方法總結(jié)
對(duì)寄存器的操作有時(shí)候要考慮對(duì)其不同的位進(jìn)行先后順序不同的設(shè)置,但是對(duì)寄存器操作的方法是固定的。
首先要明白邏輯運(yùn)算符(!,&&,||)和位運(yùn)算符(〈〈,〉〉,~,|,^,&)的區(qū)別:
對(duì)寄存器的操作使用的是位運(yùn)算符,
邏輯運(yùn)算符一般用于在程序中判斷邏輯中使用。
例如 定義一個(gè)8位的寄存器(0xf0是寄存器的地址): #define REG 0xF0
1)對(duì)單個(gè)的位進(jìn)行賦值
(1)將寄存器REG的第5位置“1”: REG |= (1 〈〈 5);
(2)將寄存器REG的第5位清“0”: REG &= ~(1 〈〈 5);
(3)將寄存器REG的第3和第5位置“1”:REG |= (1 〈〈 5) | (1 〈〈 3);
(4)將寄存器REG的第3和第5位清“0”:REG &= ~( (1 〈〈 5) | (1 〈〈 3) );
該段總結(jié)如下:
將某位置1,移位后使用位運(yùn)算“|” ;
將某位清0,移位取反后,使用位運(yùn)算“&”
2)直接賦值
(1)將寄存器REG的1、2、3、5、7位置“1”
REG = 0x5E; (即給寄存器REG1賦值為1010 1110,這種方法多在初始化中使用)
(2)分別將寄存器REG的1、3、5、7位置“1”;0、2位清“0”
u8 temp;
temp = REG;
temp |= (1 〈〈 1); //將第1位置“1”
temp |= (1 〈〈 3);
temp |= (1 〈〈 5);
temp |= (1 〈〈 7);
temp &= ~(1 〈〈 0) ; //將第0位清“0”,等價(jià)于temp &= ~0x01
temp &= ~(1 〈〈 2); //將第2位清“0”
REG = temp;
-
寄存器
+關(guān)注
關(guān)注
31文章
5363瀏覽量
121164
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
寄存器是什么?怎么操作寄存器點(diǎn)亮LED燈?
![<b class='flag-5'>寄存器</b>是什么?怎么<b class='flag-5'>操作</b><b class='flag-5'>寄存器</b>點(diǎn)亮LED燈?](https://file1.elecfans.com/web2/M00/8D/6E/wKgaomS6SMiADtQfAACtrdEXQEk745.jpg)
寄存器操作
對(duì)寄存器操作方法的經(jīng)驗(yàn)和其總結(jié)
![對(duì)<b class='flag-5'>寄存器</b><b class='flag-5'>操作方法</b>的經(jīng)驗(yàn)和其<b class='flag-5'>總結(jié)</b>](https://file1.elecfans.com//web2/M00/A7/17/wKgZomUMQlaATTC_AAA476wjYVs992.png)
寄存器變量
使用寄存器的邏輯操作指令是什么?
STM32單片機(jī)修改寄存器的位操作方法(全網(wǎng)最全)
![STM32單片機(jī)修改<b class='flag-5'>寄存器</b>的位<b class='flag-5'>操作方法</b>(全網(wǎng)最全)](https://file.elecfans.com/web1/M00/D9/4E/pIYBAF_1ac2Ac0EEAABDkS1IP1s689.png)
C語言操作寄存器的常見手法
如何在shell中操作寄存器
個(gè)人對(duì)STM32 SysTick的總結(jié)(寄存器操作)
![個(gè)人對(duì)STM32 SysTick的<b class='flag-5'>總結(jié)</b>(<b class='flag-5'>寄存器</b><b class='flag-5'>操作</b>)](https://file.elecfans.com/web2/M00/09/16/pYYBAGD0FvWAeWpFAAAb1Fux1oA753.jpg)
評(píng)論