日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

LM3S1138驱动函数SysCtlPeripheralEnable解析

發(fā)布時間:2025/3/15 编程问答 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 LM3S1138驱动函数SysCtlPeripheralEnable解析 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
標簽:? 函數(shù)? 解析? 驅(qū)動? 2010-06-10 14:46

1、??????? 引言

LM3S1138的使用過程中,如果要使用外設(shè),如本文所述的GPIO_A端口時,就得先使能此外設(shè)在RCGCx寄存器中的對應(yīng)位。至于為什么使用外設(shè)時要打開其相應(yīng)的RCGCx寄存器中的對應(yīng)位,此處先不講,我也先不懂。

LM3S系列芯片因為自帶了豐富的驅(qū)動庫程序,所以編程變得方便了很多。但對于我一個入門級選手來說,我得先懂得其驅(qū)動庫程序的組織結(jié)構(gòu),爾后才能把Luminary的驅(qū)動庫為我所用。我有一個簡單的愿望就是,我使用Luminary的驅(qū)動庫的水平,能達到這個庫仿佛是我寫的一樣。本文正是在此愿望水平還很強烈時草草擬出的。

本文內(nèi)容,很單一,只是說明一個我在使用LM3S1138芯片時,為了把PA1引腳設(shè)置為通用的IO引腳,且能對其進行軟件上的置位與復(fù)位所作的前期準備工作中的一部分。這一部分工作的核心就是把RCGC2寄存器中的GPIOA位置1,這個核心也就是本文的全部內(nèi)容了。

2、??????? 正文

我們先給出LM3S1138中的RCGC2寄存器結(jié)構(gòu),如圖1所示。

?

?

1 RCGC2寄存器的結(jié)構(gòu)圖

看到這個圖之后,我們知道自己所做的工作即是把RCGC2中的0GPIOA位置1。事實是,我們不管用什么程序結(jié)構(gòu),都是為了達到這個目的。最直接的,最熟練的方式是采用C語言的賦值語句:

?

RCGC2 |= 0x00000001;

?

接下來,我們順著Luminary的驅(qū)動庫程序的流程,來看一下,上述目的是怎么個實現(xiàn)過程。首現(xiàn)我們先將Luminary驅(qū)動庫程序?qū)?/span>RCGC2中的GPIOA位置1的程序流程圖羅列出來,如圖2所示。

2 RCGC2GPIOA位置1的程序結(jié)構(gòu)圖

2所示的程序流程圖中的函數(shù)原型:

?

extern void SysCtlPeripheralEnable(unsigned long ulPeripheral);

?

Sysctl.h中聲明,在Sysctl.c中定義,其作用是置位對應(yīng)外設(shè)在RCGC2中的控制位,使能此外設(shè)。

程序流程圖是簡單的,程序的執(zhí)行過程是復(fù)雜的,當然復(fù)雜是因為我的初學(xué),不懂的太多。接下來,我們要探討的是SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA)這個函數(shù)的執(zhí)行細節(jié)。為了夠細節(jié),我們直接將Luminary的源碼羅列在下面,以達到給篇幅注水的目的。

?

//*****************************************************************************

//

//! Enables a peripheral.

//!

//! /param ulPeripheral is the peripheral to enable.

//!

//! Peripherals are enabled with this function.? At power-up, all peripherals

//! are disabled; they must be enabled in order to operate or respond to

//! register reads/writes.

//!

//! The /e ulPeripheral parameter must be only one of the following values:

//! /b SYSCTL_PERIPH_ADC, /b SYSCTL_PERIPH_CAN0, /b SYSCTL_PERIPH_CAN1,

//! /b SYSCTL_PERIPH_CAN2, /b SYSCTL_PERIPH_COMP0, /b SYSCTL_PERIPH_COMP1,

//! /b SYSCTL_PERIPH_COMP2, /b SYSCTL_PERIPH_ETH, /b SYSCTL_PERIPH_GPIOA,

//! /b SYSCTL_PERIPH_GPIOB, /b SYSCTL_PERIPH_GPIOC, /b SYSCTL_PERIPH_GPIOD,

//! /b SYSCTL_PERIPH_GPIOE, /b SYSCTL_PERIPH_GPIOF, /b SYSCTL_PERIPH_GPIOG,

//! /bSYSCTL_PERIPH_GPIOH, /bSYSCTL_PERIPH_HIBERNATE, /b SYSCTL_PERIPH_I2C0,

//! /b SYSCTL_PERIPH_I2C1, /b SYSCTL_PERIPH_PWM, /b SYSCTL_PERIPH_QEI0,

//! /b SYSCTL_PERIPH_QEI1, /b SYSCTL_PERIPH_SSI0, /b SYSCTL_PERIPH_SSI1,

//! /b SYSCTL_PERIPH_TIMER0, /b SYSCTL_PERIPH_TIMER1, /b SYSCTL_PERIPH_TIMER2,

//! /b SYSCTL_PERIPH_TIMER3, /b SYSCTL_PERIPH_UART0, /b SYSCTL_PERIPH_UART1,

//! /b SYSCTL_PERIPH_UART2, /b SYSCTL_PERIPH_UDMA, /b SYSCTL_PERIPH_USB0, or

//! /b SYSCTL_PERIPH_WDOG.

//!

//! /note It takes five clock cycles after the write to enable a peripheral

//! before the the peripheral is actually enabled.? During this time, attempts

//! to access the peripheral will result in a bus fault.? Care should be taken

//! to ensure that the peripheral is not accessed during this brief time

//! period.

//!

//! /return None.

//

//*****************************************************************************

void

SysCtlPeripheralEnable(unsigned long ulPeripheral)

{

??? //

??? // Check the arguments.

??? //

??? ASSERT(SysCtlPeripheralValid(ulPeripheral));

?

??? //

? ??// Enable this peripheral.

??? //

??? HWREG(g_pulRCGCRegs[SYSCTL_PERIPH_INDEX(ulPeripheral)]) |=

??????? SYSCTL_PERIPH_MASK(ulPeripheral);

}

?

?

這個函數(shù)基本上就做了兩件事情,一件是采用斷言:

?

ASSERT(SysCtlPeripheralValid(ulPeripheral));

?

檢查形參的合法性,若形參不合法,ASSERT(條件)里面的邏輯值為假。程序在編譯階段是要報錯的。斷言的使用,目前不是很熟悉,不多講了。

斷言對形參進行判斷之后,參數(shù)合法,接著,就指著這個參數(shù)來進行一系列的寄存器操作了。其操作語句為:

?

??? //

??? // Enable this peripheral.

??? //

??? HWREG(g_pulRCGCRegs[SYSCTL_PERIPH_INDEX(ulPeripheral)]) |=

??????? SYSCTL_PERIPH_MASK(ulPeripheral);

?

關(guān)于這條語句的注釋是,這條語句用專業(yè)的驅(qū)動庫把一條簡單的

?

RCGC2 |= 0x00000001;

?

賦值語句進行了一點點小小的復(fù)雜化。下面,我們就把這個語句,給拆明白了,如果我能把這條語給講明白了,那真得覺得算是我的一點點小小的造化。首先,我們就

?

??? HWREG(g_pulRCGCRegs[SYSCTL_PERIPH_INDEX(ulPeripheral)]) |=

??????? SYSCTL_PERIPH_MASK(ulPeripheral);

?

這條賦值語句的左邊是如何解析出RCCG2來進行說明,然后,我們就這條賦值語句的右邊是如何解析出0x00000001來再進行說明。這條賦值語句的左邊是:

?

HWREG(g_pulRCGCRegs[SYSCTL_PERIPH_INDEX(ulPeripheral)])

?

HWREG它是一個帶參數(shù)的宏,它的參數(shù)是一個數(shù)組名為g_pulRCGCRegs的元素,這個元素在數(shù)組中的序號是SYSCTL_PERIPH_INDEX(ulPeripheral),我查過,SYSCTL_SYSCTL_PERIPH_INDEXSysctl.c中有定義,是一個帶參數(shù)的宏。完整的定義是:

?

//*****************************************************************************

//

// This macro extracts the array index out of the peripheral number.

//

//*****************************************************************************

#define SYSCTL_PERIPH_INDEX(a)? (((a) >> 28) & 0xf)

?

?

HWREG(g_pulRCGCRegs[SYSCTL_PERIPH_INDEX(ulPeripheral)])

?

其中ulPeripheral 這個形參所對應(yīng)的實參是:SYSCTL_PERIPH_GPIOA。對上述左邊的表達式,比較看好的執(zhí)行結(jié)果是:

RCGC2

?

我們順著HWREG(g_pulRCGCRegs[SYSCTL_PERIPH_INDEX(ulPeripheral)])的執(zhí)行過程進行解析。

1)? 給出ulPeripheral所對應(yīng)的實參為:

SYSCTL_PERIPH_GPIOA

這個實參是個代表32位二進制數(shù)的宏,在Sysctl.h定義,

?

#define SYSCTL_PERIPH_GPIOA???? 0x20000001? // GPIO A

?

2) 執(zhí)行SYSCTL_PERIPH_INDEX(ulPeripheral)

也就是執(zhí)行

(((a) >> 28) & 0xf)

代入實參SYSCTL_PERIPH_GPIOA(0x20000001)之后的情況是:

(((SYSCTL_PERIPH_GPIOA) >> 28) & 0xf)

(((0x20000001) >> 28) & 0xf)

這個值我們心算一下,可以得出,等于十進制數(shù)2

?

3) 執(zhí)行g_pulRCGCRegs[SYSCTL_PERIPH_INDEX(ulPeripheral)],也就是執(zhí)行

?

g_pulRCGCRegs[2]

?

g_pulRCGCRegs[]是一個數(shù)組,在Sysctl.c中定義,其具體的定義形式為:

//*****************************************************************************

//

// An array that maps the "peripheral set" number (which is stored in the upper

// nibble of the SYSCTL_PERIPH_* defines) to the SYSCTL_RCGC? register that

// controls the run-mode enable for that peripheral.

//

//*****************************************************************************

static const unsigned long g_pulRCGCRegs[] =

{

??? SYSCTL_RCGC0,

??? SYSCTL_RCGC1,

??? SYSCTL_RCGC2

};

?

可以看到g_pulRCGCRegs[2]對應(yīng)的元素即是:

?

SYSCTL_RCGC2

?

這也是個宏,在Hw_sysctl.h中定義,其具體的定義形式為:

?

#define SYSCTL_SCGC2??????????? 0x400FE118? // Sleep-mode clock gating reg 2

?

這對應(yīng)的數(shù)值0x400FE118,即對應(yīng)著RCGC2對應(yīng)的地址,如圖1所示的寄存器結(jié)構(gòu)的左上腳的說明部分,如圖3所示。

?

3 RCGC2的地址說明

4) 執(zhí)行HWREG(0x400FE118),這一句語翻譯成標準的C語言之后,應(yīng)該是:

?

*((volatile unsigned long *)0x400FE108)

?

HWREG()這個宏在Hw_types.h文件中有定義,具本定義為:

?

#define HWREG(x)??? (*((volatile unsigned long *)(x)))

?

TI網(wǎng)站上,你可以下載一個spmu019c.pdf,在第7頁與第9頁,也會告訴你,在Luminary完整的驅(qū)動庫文件(名為:SW-LM3S-5961.exe,這個是今年5月份的時候的叫法)中,你解壓完之后的/inc目錄下,你可以找到lm3s1138.h這個頭文件,這頭文件是為直接寄存器訪問的編程而制做的頭文件,在這個頭文件中,你也可以找到如下的宏定義。

?

#define SYSCTL_RCGC2_R????????? (*((volatile unsigned long *)0x400FE108))????????????????????

?

表達式*((volatile unsigned long *)0x400FE108)的作用是:

先用(volatile unsigned long *)0x400FE108強制轉(zhuǎn)換,將0x400FE108變成一個地址,然后再用*((volatile unsigned long *)0x400FE108)將這個地址,變成實實在在的一個沒有名稱的變量,你可以往里賦值了。

?

寫到這里,請大家清醒的意識到,我們只是干完了

?

??? HWREG(g_pulRCGCRegs[SYSCTL_PERIPH_INDEX(ulPeripheral)]) |=

??????? SYSCTL_PERIPH_MASK(ulPeripheral);

?

這條語句的左半部分,這條賦值語句的右邊是:

?

SYSCTL_PERIPH_MASK(ulPeripheral)

?

它是一個帶參數(shù)的宏,它的參數(shù)是ulPeripheral,對應(yīng)的實參是SYSCTL_PERIPH_GPIOA

這個帶參數(shù)的宏SYSCTL_PERIPH_MASK()Sysctl.c中有定義,完整的定義是:

?

//*****************************************************************************

//

// This macro constructs the peripheral bit mask from the peripheral number.

//

//*****************************************************************************

#define SYSCTL_PERIPH_MASK(a)?? (((a) & 0xffff) << (((a) & 0x001f0000) >> 16))

?

實參ulPeripheral,前面已經(jīng)講過是個代表32位二進制數(shù)的宏,在Sysctl.h定義,

?

#define SYSCTL_PERIPH_GPIOA???? 0x20000001? // GPIO A

?

SYSCTL_PERIPH_MASK(ulPeripheral)

?

中的ulPeripheral 這個形參所對應(yīng)的實參是:SYSCTL_PERIPH_GPIOA,這條語句比較看好的執(zhí)行結(jié)果是:

0x00000001

我們順著SYSCTL_PERIPH_MASK(ulPeripheral)的執(zhí)行過程進行解析。

?

1)????? 給出ulPeripheral所對應(yīng)的實參為:

SYSCTL_PERIPH_GPIOA

這個實參是個代表32位二進制數(shù)的宏,在Sysctl.h定義,

?

#define SYSCTL_PERIPH_GPIOA???? 0x20000001? // GPIO A

?

2) ?SYSCTL_PERIPH_MASK (ulPeripheral),也就是執(zhí)行

?

(((a) & 0xffff) << (((a) & 0x001f0000) >> 16))

代入實參SYSCTL_PERIPH_GPIOA(0x20000001)之后的情況是:

(((SYSCTL_PERIPH_GPIOA) & 0xffff) << (((SYSCTL_PERIPH_GPIOA) & 0x001f0000) >> 16))

(((0x20000001) & 0xffff) << (((0x20000001) & 0x001f0000) >> 16))

0x00000001 << (0>> 16)

0x00000001 << 0

0x00000001

?

好了,你可以把這個1賦給RCGC2了,結(jié)合式子的左右部分得出的完整的語句是:

?

*((volatile unsigned long *)0x400FE108) |= 0x00000001;

?

1所示的寄存器RCGC20GPIOA,被成功的置1了。

?

3、??????? 總結(jié)

夏天很熱,上述文字寫得也不冷靜,許多暖昧不清的地方可能還沒被我意識到,許多應(yīng)該加以說明的地方,我可能草草了事。像每個引用的文件,其作用,沒有被說明;像優(yōu)秀的變量命名方式?jīng)]有被表揚;究其原因,我覺得是我入門的太淺,不能對文中所述的內(nèi)容,做以全局的把握和說明。

?

?

總結(jié)

以上是生活随笔為你收集整理的LM3S1138驱动函数SysCtlPeripheralEnable解析的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。