第4章STM32開發(fā)基礎(chǔ)知識_第1頁
第4章STM32開發(fā)基礎(chǔ)知識_第2頁
第4章STM32開發(fā)基礎(chǔ)知識_第3頁
第4章STM32開發(fā)基礎(chǔ)知識_第4頁
第4章STM32開發(fā)基礎(chǔ)知識_第5頁
已閱讀5頁,還剩76頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)

文檔簡介

1、STM32 開發(fā)基礎(chǔ)知識開發(fā)基礎(chǔ)知識MDK 下下 C 語言基礎(chǔ)復(fù)習(xí)語言基礎(chǔ)復(fù)習(xí) STM32 系統(tǒng)架構(gòu)系統(tǒng)架構(gòu) STM32 時鐘系統(tǒng)時鐘系統(tǒng) 端口復(fù)用和重映射端口復(fù)用和重映射 STM32 NVIC 中斷管理中斷管理 MDK 中寄存器地址名稱映射分析中寄存器地址名稱映射分析 MDK 固件庫快速開發(fā)技巧固件庫快速開發(fā)技巧MDK 下下 C 語言基礎(chǔ)復(fù)習(xí)語言基礎(chǔ)復(fù)習(xí)位操作位操作位操作在單片機開發(fā)中的一些實用技巧位操作在單片機開發(fā)中的一些實用技巧不改變其他位的值的狀況下,對某幾個位進行設(shè)值。不改變其他位的值的狀況下,對某幾個位進行設(shè)值。 這個場景單片機開發(fā)中經(jīng)常使用,方法就是先對需要設(shè)置的位用這個場景單片

2、機開發(fā)中經(jīng)常使用,方法就是先對需要設(shè)置的位用&操作符進行清零操作,然后用操作符進行清零操作,然后用| 操作符設(shè)值。比如我要改變操作符設(shè)值。比如我要改變 GPIOA 的狀態(tài)的狀態(tài), 可以先對寄存器的值進行可以先對寄存器的值進行&清零操作清零操作GPIOA-CRL&=0XFFFFFF0F; /將第將第 4-7 位清位清 0然后再與需要設(shè)置的值進行然后再與需要設(shè)置的值進行| 或運算或運算GPIOA-CRL|=0X00000040; /設(shè)置相應(yīng)位的值,不改變其他位的值設(shè)置相應(yīng)位的值,不改變其他位的值移位操作提高代碼的可讀性移位操作提高代碼的可讀性移位操作在單片機開發(fā)中也非常重要

3、,下面讓我們看看固件庫移位操作在單片機開發(fā)中也非常重要,下面讓我們看看固件庫的的 GPIO 初始化的函數(shù)里面的一行代碼初始化的函數(shù)里面的一行代碼GPIOx-BSRR = (uint32_t)0 x01) BSRR =0 x0030;這樣的代碼就不好看也不好重用了。這樣的代碼就不好看也不好重用了。類似這樣的代碼很多類似這樣的代碼很多:GPIOA-ODR|=15; /PA.5 輸出高輸出高,不改變其他位不改變其他位這樣我們一目了然,這樣我們一目了然, 5 告訴我們是第告訴我們是第 5 位也就是第位也就是第 6 個端口,個端口, 1 告訴我們是設(shè)置為告訴我們是設(shè)置為 1 了。了。uint8_t /

4、uint16_t / uint32_t /uint64_t 是什么數(shù)據(jù)類型是什么數(shù)據(jù)類型這些數(shù)據(jù)類型是這些數(shù)據(jù)類型是 C99 中定義的,具體定義在:中定義的,具體定義在:/usr/include/stdint.h ISO C99: 7.18 Integer types 取反操作使用技巧取反操作使用技巧SR 寄存器的每一位都代表一個狀態(tài),某個時刻我們希望去設(shè)置寄存器的每一位都代表一個狀態(tài),某個時刻我們希望去設(shè)置某一位的值為某一位的值為 0,同時其他位都保留為,同時其他位都保留為 1,簡單的作法是直接給,簡單的作法是直接給寄存器設(shè)置一個值:寄存器設(shè)置一個值:TIMx-SR=0 xFFF7;這樣的作

5、法設(shè)置第這樣的作法設(shè)置第 3 位為位為 0,但是這樣的作法同樣不好看,并且,但是這樣的作法同樣不好看,并且可讀性很差??纯磶旌瘮?shù)代碼中怎樣使用的:可讀性很差??纯磶旌瘮?shù)代碼中怎樣使用的:TIMx-SR = (uint16_t)TIM_FLAG;而而 TIM_FLAG 是通過宏定義定義的值:是通過宏定義定義的值:#define TIM_FLAG_Update (uint16_t)0 x0001)#define TIM_FLAG_CC1 (uint16_t)0 x0002)看這個應(yīng)該很容易明白,可以直接從宏定義中看出看這個應(yīng)該很容易明白,可以直接從宏定義中看出 TIM_FLAG_Update 就是

6、設(shè)置的第就是設(shè)置的第 0 位了,可讀性非常強。位了,可讀性非常強。define 宏定義宏定義define 是是 C 語言中的預(yù)處理命令,它用于宏定義,可以提高源語言中的預(yù)處理命令,它用于宏定義,可以提高源代碼的可讀性,為編程提供方便。常見的格式:代碼的可讀性,為編程提供方便。常見的格式:#define 標(biāo)識符標(biāo)識符 字符串字符串“標(biāo)識符標(biāo)識符”為所定義的宏名。為所定義的宏名。“字符串字符串”可以是常數(shù)、表達式、可以是常數(shù)、表達式、格式串等。例如:格式串等。例如:#define SYSCLK_FREQ_72MHz 72000000定義標(biāo)識符定義標(biāo)識符 SYSCLK_FREQ_72MHz 的值為的

7、值為 72000000。ifdef條件編譯條件編譯單片機程序開發(fā)過程中,經(jīng)常會遇到一種情況,單片機程序開發(fā)過程中,經(jīng)常會遇到一種情況, 當(dāng)滿足某條件當(dāng)滿足某條件時對一組語句進行編譯,而時對一組語句進行編譯,而當(dāng)條件不滿足時則編譯另一組語句。當(dāng)條件不滿足時則編譯另一組語句。 條件編譯命令最常見的形條件編譯命令最常見的形式為:式為:#ifdef 標(biāo)識符標(biāo)識符程序段程序段 1#else程序段程序段 2#endif它的作用是:當(dāng)標(biāo)識符已經(jīng)被定義過它的作用是:當(dāng)標(biāo)識符已經(jīng)被定義過(一般是用一般是用#define 命令命令定義定義) ,則對程序段,則對程序段 1 進行編譯,進行編譯,否則編譯程序段否則編譯

8、程序段 2。 其中其中#else 部分也可以沒有,即:部分也可以沒有,即:#ifdef程序段程序段 1#endif這個條件編譯在這個條件編譯在 MDK 里面是用得很多的,在里面是用得很多的,在 stm32f10 x.h 這個頭文件中經(jīng)常會看到這樣的語句:這個頭文件中經(jīng)常會看到這樣的語句:#ifdef STM32F10X_HD大容量芯片需要的一些變量定義大容量芯片需要的一些變量定義#end而而 STM32F10X_HD 則是我們通過則是我們通過#define 來定義的。來定義的。extern 變量申明變量申明C 語言中語言中 extern 可以置于變量或者函數(shù)前,以表示變量或者函數(shù)可以置于變量或

9、者函數(shù)前,以表示變量或者函數(shù)的定義在別的文件中,提示編譯器遇到此變量和函數(shù)時在其他模的定義在別的文件中,提示編譯器遇到此變量和函數(shù)時在其他模塊中尋找其定義。塊中尋找其定義。 這里面要注意,對于這里面要注意,對于 extern 申明變量可以多申明變量可以多次,但定義只有一次。在我們的代碼中你會看到看到這樣的語句:次,但定義只有一次。在我們的代碼中你會看到看到這樣的語句:extern u16 USART_RX_STA;這個語句是申明這個語句是申明 USART_RX_STA 變量在其他文件中已經(jīng)定義了,變量在其他文件中已經(jīng)定義了,在這里要使用到。所以,你肯定可以找到在某個地方有變量定義在這里要使用到

10、。所以,你肯定可以找到在某個地方有變量定義的語句:的語句:u16 USART_RX_STA;的出現(xiàn)。下面通過一個例子說明一下使用方法。的出現(xiàn)。下面通過一個例子說明一下使用方法。引出引出IO口口在在 Main.c 定義的全局變量定義的全局變量 id, id 的初始化都是在的初始化都是在 Main.c 里面里面進行的。進行的。Main.c 文件文件u8 id;/定義只允許一次定義只允許一次main()id=1;printf(d%,id);/id=1test();printf(d%,id);/id=2但是我們希望在但是我們希望在 test.c 的的 changeId(void) 函數(shù)中使用變量函數(shù)中

11、使用變量 id, 這這個時候我們就需要在個時候我們就需要在 test.c里面去申明變量里面去申明變量 id 是外部定義的了,是外部定義的了,因為如果不申明,變量因為如果不申明,變量 id 的作用域是到不了的作用域是到不了 test.c 文件中。文件中。看下面看下面 test.c 中的代碼:中的代碼:extern u8 id;/申明變量申明變量 id 是在外部定義的,申明可以在是在外部定義的,申明可以在很很 多個文件中進行多個文件中進行void test(void) id=2;在在 test.c 中申明變量中申明變量 id 在外部定義,然后在在外部定義,然后在 test.c 中就可中就可以使用變

12、量以使用變量 id 了。了。對于對于 extern 申明函數(shù)在外部定義的應(yīng)用,這里我們就不多申明函數(shù)在外部定義的應(yīng)用,這里我們就不多講解了。講解了。typedef類型別名類型別名typedef 用于為現(xiàn)有類型創(chuàng)建一個新的名字,或稱為類型別名,用來用于為現(xiàn)有類型創(chuàng)建一個新的名字,或稱為類型別名,用來簡化變量的定義。簡化變量的定義。typedef 在在 MDK 用得最多的就是定義結(jié)構(gòu)體的類型別名和枚舉類型用得最多的就是定義結(jié)構(gòu)體的類型別名和枚舉類型了。了。struct _GPIO_IO uint32_t CRL;_IO uint32_t CRH;定義了一個結(jié)構(gòu)體定義了一個結(jié)構(gòu)體 GPIO,這樣我們

13、定義變量的方式為:,這樣我們定義變量的方式為:struct _GPIO GPIOA; /定義結(jié)構(gòu)體變量定義結(jié)構(gòu)體變量 GPIOA但是這樣很繁瑣,但是這樣很繁瑣, MDK 中有很多這樣的結(jié)構(gòu)體變量需要定義。這里中有很多這樣的結(jié)構(gòu)體變量需要定義。這里我們可以為結(jié)體定義一個別名我們可以為結(jié)體定義一個別名 GPIO_TypeDef,這樣我們就可以在其,這樣我們就可以在其他地方通過別名他地方通過別名 GPIO_TypeDef 來定義結(jié)構(gòu)體變量了。來定義結(jié)構(gòu)體變量了。方法如下:方法如下:typedef struct_IO uint32_t CRL;_IO uint32_t CRH; GPIO_TypeDe

14、f;Typedef 為結(jié)構(gòu)體定義一個別名為結(jié)構(gòu)體定義一個別名 GPIO_TypeDef,這樣我們可,這樣我們可以通過以通過 GPIO_TypeDef 來定義結(jié)構(gòu)體來定義結(jié)構(gòu)體變量:變量:GPIO_TypeDef _GPIOA,_GPIOB;這里的這里的 GPIO_TypeDef 就跟就跟 struct _GPIO 是等同的作用了。是等同的作用了。 這樣是不是方便很多?這樣是不是方便很多?結(jié)構(gòu)體結(jié)構(gòu)體經(jīng)常很多用戶提到,他們對結(jié)構(gòu)體使用不是很熟悉,但是經(jīng)常很多用戶提到,他們對結(jié)構(gòu)體使用不是很熟悉,但是 MDK 中太多地方使用結(jié)構(gòu)體以及結(jié)構(gòu)體指針,這讓他們一下中太多地方使用結(jié)構(gòu)體以及結(jié)構(gòu)體指針,這讓

15、他們一下子摸不著頭腦,學(xué)習(xí)子摸不著頭腦,學(xué)習(xí) STM32 的積極性大大降低,其實結(jié)構(gòu)體的積極性大大降低,其實結(jié)構(gòu)體并不是那么復(fù)雜,這里我們稍微提一下結(jié)構(gòu)體的一些知識,并不是那么復(fù)雜,這里我們稍微提一下結(jié)構(gòu)體的一些知識,還有一些知識我們會在下一節(jié)的還有一些知識我們會在下一節(jié)的“寄存器地址名稱映射分析寄存器地址名稱映射分析”中講到一些。中講到一些。聲明結(jié)構(gòu)體類型:聲明結(jié)構(gòu)體類型:Struct 結(jié)構(gòu)體名結(jié)構(gòu)體名 成員列表成員列表;變量名列表;變量名列表;例如:例如:Struct U_TYPE Int BaudRate Int WordLength;usart1,usart2;在結(jié)構(gòu)體申明的時候可以定

16、義變量,也可以申明之后定義,方在結(jié)構(gòu)體申明的時候可以定義變量,也可以申明之后定義,方法是:法是:Struct 結(jié)構(gòu)體名字結(jié)構(gòu)體名字 結(jié)構(gòu)體變量列表結(jié)構(gòu)體變量列表 ;例如:例如: struct U_TYPE usart1, usart2;結(jié)構(gòu)體成員變量的引用方法是:結(jié)構(gòu)體成員變量的引用方法是:結(jié)構(gòu)體變量名字結(jié)構(gòu)體變量名字.成員名成員名比如要引用比如要引用 usart1 的成員的成員 BaudRate,方法是:,方法是: usart1.BaudRate;結(jié)構(gòu)體指針變量定義也是一樣的,跟其他變量沒有啥區(qū)別。結(jié)構(gòu)體指針變量定義也是一樣的,跟其他變量沒有啥區(qū)別。例如:例如: struct U_TYPE

17、*usart3; /定義結(jié)構(gòu)體指針變量定義結(jié)構(gòu)體指針變量 usart1;結(jié)構(gòu)體指針成員變量引用方法是通過結(jié)構(gòu)體指針成員變量引用方法是通過“-”符號實現(xiàn),比如要符號實現(xiàn),比如要訪問訪問 usart3 結(jié)構(gòu)體指針指向的結(jié)結(jié)構(gòu)體指針指向的結(jié)構(gòu)體的成員變量構(gòu)體的成員變量 BaudRate, 方法是:方法是:Usart3-BaudRate;上面講解了結(jié)構(gòu)體和結(jié)構(gòu)體指針的一些知識,其他的什么初上面講解了結(jié)構(gòu)體和結(jié)構(gòu)體指針的一些知識,其他的什么初始化這里就不多講解了。始化這里就不多講解了。 講到這里,有人會問,結(jié)構(gòu)體到底講到這里,有人會問,結(jié)構(gòu)體到底有什么作用呢?為什么要使用結(jié)構(gòu)體呢?下面我們將簡單的有什么

18、作用呢?為什么要使用結(jié)構(gòu)體呢?下面我們將簡單的通過一個實例回答一下這個問題。通過一個實例回答一下這個問題。在我們單片機程序開發(fā)過程中,經(jīng)常會遇到要初始化一個外設(shè)在我們單片機程序開發(fā)過程中,經(jīng)常會遇到要初始化一個外設(shè)比如串口,它的初始化狀態(tài)是由幾個屬性來決定的,比如串口比如串口,它的初始化狀態(tài)是由幾個屬性來決定的,比如串口號,波特率,極性,以及模式。對于這種情況,在我們沒有學(xué)號,波特率,極性,以及模式。對于這種情況,在我們沒有學(xué)習(xí)結(jié)構(gòu)體的時候,我們一般的方法是:習(xí)結(jié)構(gòu)體的時候,我們一般的方法是:void USART_Init(u8 usartx,u32 u32 BaudRate,u8 parit

19、y,u8 mode);這種方式是有效的同時在一定場合是可取的。但是試想,如果這種方式是有效的同時在一定場合是可取的。但是試想,如果有一天,我們希望往這個函數(shù)里面再傳入一個參數(shù),那么勢必有一天,我們希望往這個函數(shù)里面再傳入一個參數(shù),那么勢必我們需要修改這個函數(shù)的定義,重新加入字長這個入口參數(shù)。我們需要修改這個函數(shù)的定義,重新加入字長這個入口參數(shù)。于是我們的定義被修改為:于是我們的定義被修改為:void USART_Init (u8 usartx,u32 BaudRate, u8 parity,u8 mode,u8 wordlength );但是如果我們這個函數(shù)的入口參數(shù)是隨著開發(fā)不斷的增多,那但

20、是如果我們這個函數(shù)的入口參數(shù)是隨著開發(fā)不斷的增多,那么是不是我們就要不斷的修改函數(shù)的定義呢?這是不是給我們么是不是我們就要不斷的修改函數(shù)的定義呢?這是不是給我們開發(fā)帶來很多的麻煩?那又怎樣解決這種情況呢?開發(fā)帶來很多的麻煩?那又怎樣解決這種情況呢?這樣如果我們使用到結(jié)構(gòu)體就能解決這個問題了。我們可以這樣如果我們使用到結(jié)構(gòu)體就能解決這個問題了。我們可以在不改變?nèi)肟趨?shù)的情況下,只需要改變結(jié)構(gòu)體的成員變量,在不改變?nèi)肟趨?shù)的情況下,只需要改變結(jié)構(gòu)體的成員變量,就可以達到上面改變?nèi)肟趨?shù)的目的。結(jié)構(gòu)體就是將多個變就可以達到上面改變?nèi)肟趨?shù)的目的。結(jié)構(gòu)體就是將多個變量組合為一個有機的整體。上面的函數(shù)量

21、組合為一個有機的整體。上面的函數(shù), BaudRate, wordlength, Parity, mode, wordlength 這些參數(shù),他們對于串這些參數(shù),他們對于串口而言,是一個有機整體,都是來設(shè)置串口參數(shù)的,所以我口而言,是一個有機整體,都是來設(shè)置串口參數(shù)的,所以我們可以將他們通過定義一個結(jié)構(gòu)體來組合在一個。們可以將他們通過定義一個結(jié)構(gòu)體來組合在一個。 MDK 中中是這樣定義的:是這樣定義的:typedef structuint32_t USART_BaudRate;uint16_t USART_WordLength;uint16_t USART_StopBits;uint16_t U

22、SART_Parity;uint16_t USART_Mode;uint16_t USART_HardwareFlowControl; USART_InitTypeDef;于是,我們在初始化串口的時候入口參數(shù)就可以是于是,我們在初始化串口的時候入口參數(shù)就可以是 USART_InitTypeDef 類型的變量或者指針變量了,類型的變量或者指針變量了, MDK 中是中是這樣做的:這樣做的:void USART_Init(USART_TypeDef* USARTx, USART_InitTypeDef* USART_InitStruct);這樣,任何時候,我們只需要修改結(jié)構(gòu)體成員變量,往這樣,任何時

23、候,我們只需要修改結(jié)構(gòu)體成員變量,往結(jié)構(gòu)體中間加入新的成員變量,而不需要修改函數(shù)定義就可以結(jié)構(gòu)體中間加入新的成員變量,而不需要修改函數(shù)定義就可以達到修改入口參數(shù)同樣的目的了。達到修改入口參數(shù)同樣的目的了。 這樣的好處是不用修改任何這樣的好處是不用修改任何函數(shù)定義就可以達到增加變量的目的。函數(shù)定義就可以達到增加變量的目的。在以后的開發(fā)過程中,如果你的變量定義過多,如果某在以后的開發(fā)過程中,如果你的變量定義過多,如果某幾個變量是用來描述某一個對象,你可以考慮將這些變量定義幾個變量是用來描述某一個對象,你可以考慮將這些變量定義在結(jié)構(gòu)體中,這樣也許可以提高你的代碼的可讀性。使用結(jié)構(gòu)在結(jié)構(gòu)體中,這樣也許

24、可以提高你的代碼的可讀性。使用結(jié)構(gòu)體組合參數(shù),可以提高代碼的可讀性,不會覺得變量定義混亂。體組合參數(shù),可以提高代碼的可讀性,不會覺得變量定義混亂。STM32 系統(tǒng)架構(gòu)系統(tǒng)架構(gòu)STM32 主系統(tǒng)主要由四個驅(qū)動單元和四個被動單元構(gòu)成。主系統(tǒng)主要由四個驅(qū)動單元和四個被動單元構(gòu)成。四個驅(qū)動單元是:四個驅(qū)動單元是:內(nèi)核內(nèi)核 DCode 總線總線;系統(tǒng)總線系統(tǒng)總線;通用通用 DMA1;通用通用 DMA2;四被動單元是:四被動單元是:AHB 到到 APB 的橋:連接所有的的橋:連接所有的 APB 設(shè)備;設(shè)備;內(nèi)部內(nèi)部 FlASH 閃存;閃存;內(nèi)部內(nèi)部 SRAM;FSMC; ICode 總線:該總線將總線:該

25、總線將 M3 內(nèi)核指令總線和閃存指令接口相內(nèi)核指令總線和閃存指令接口相連,指令的預(yù)取在該總線上面完成。連,指令的預(yù)取在該總線上面完成。 DCode 總線:該總線將總線:該總線將 M3 內(nèi)核的內(nèi)核的 DCode 總線與閃存存儲總線與閃存存儲器的數(shù)據(jù)接口相連接,常量加載和調(diào)試訪問在該總線上面完成。器的數(shù)據(jù)接口相連接,常量加載和調(diào)試訪問在該總線上面完成。 系統(tǒng)總線:該總線連接系統(tǒng)總線:該總線連接 M3 內(nèi)核的系統(tǒng)總線到總線矩陣,總內(nèi)核的系統(tǒng)總線到總線矩陣,總線矩陣協(xié)調(diào)內(nèi)核和線矩陣協(xié)調(diào)內(nèi)核和 DMA 間訪問。間訪問。 DMA 總線:該總線將總線:該總線將 DMA 的的 AHB 主控接口與總線矩陣相主控

26、接口與總線矩陣相連,總線矩陣協(xié)調(diào)連,總線矩陣協(xié)調(diào) CPU 的的DCode 和和 DMA 到到 SRAM,閃存和外閃存和外設(shè)的訪問。設(shè)的訪問。 總線矩陣:總線矩陣協(xié)調(diào)內(nèi)核系統(tǒng)總線和總線矩陣:總線矩陣協(xié)調(diào)內(nèi)核系統(tǒng)總線和 DMA 主控總線之主控總線之間的訪問仲裁,仲裁利用輪換算法。間的訪問仲裁,仲裁利用輪換算法。 AHB/APB 橋橋:這兩個橋在這兩個橋在 AHB 和和 2 個個 APB 總線間提供同總線間提供同步連接,步連接, APB1 操作速度限于操作速度限于36MHz, APB2 操作速度全速。操作速度全速。STM32 時鐘系統(tǒng)時鐘系統(tǒng)眾所周知,時鐘系統(tǒng)是眾所周知,時鐘系統(tǒng)是 CPU 的脈搏,

27、就像人的心跳一樣。所以的脈搏,就像人的心跳一樣。所以時鐘系統(tǒng)的重要性就不言而喻了。時鐘系統(tǒng)的重要性就不言而喻了。 STM32 的時鐘系統(tǒng)比較復(fù)雜,的時鐘系統(tǒng)比較復(fù)雜,不像簡單的不像簡單的 51 單片機一個系統(tǒng)時鐘就可以解決一切。于是有人單片機一個系統(tǒng)時鐘就可以解決一切。于是有人要問,采用一個系統(tǒng)時鐘不是很簡單嗎?為什么要問,采用一個系統(tǒng)時鐘不是很簡單嗎?為什么 STM32 要有多要有多個時鐘源呢?因為首先個時鐘源呢?因為首先STM32 本身非常復(fù)雜,外設(shè)非常的多,本身非常復(fù)雜,外設(shè)非常的多,但是并不是所有外設(shè)都需要系統(tǒng)時鐘這么高的頻率,比如看門但是并不是所有外設(shè)都需要系統(tǒng)時鐘這么高的頻率,比如

28、看門狗以及狗以及 RTC 只需要幾十只需要幾十 k 的時鐘即可。同一個電路,時鐘越快的時鐘即可。同一個電路,時鐘越快功耗越大,同時抗電磁干擾能力也會越弱,所以對于較為復(fù)雜功耗越大,同時抗電磁干擾能力也會越弱,所以對于較為復(fù)雜的的 MCU 一般都是采取多時鐘源的方法來解決這些問題。一般都是采取多時鐘源的方法來解決這些問題。在在 STM32 中,有五個時鐘源,為中,有五個時鐘源,為 HSI、 HSE、 LSI、 LSE、 PLL。從時鐘頻率來分可以分為高速時鐘源和低速時鐘源,在。從時鐘頻率來分可以分為高速時鐘源和低速時鐘源,在這這 5 個中個中 HIS, HSE 以及以及 PLL 是高速時鐘,是高

29、速時鐘, LSI 和和 LSE 是低是低速時鐘。從來源可分為外部時鐘源和內(nèi)部時鐘源,外部時鐘源速時鐘。從來源可分為外部時鐘源和內(nèi)部時鐘源,外部時鐘源就是從外部通過接晶振的方式獲取時鐘源,其中就是從外部通過接晶振的方式獲取時鐘源,其中 HSE 和和 LSE 是外部時鐘源。是外部時鐘源。、 HSI 是高速內(nèi)部時鐘,是高速內(nèi)部時鐘, RC 振蕩器,振蕩器, 頻率為頻率為 8MHz。、 HSE 是高速外部時鐘,可接石英是高速外部時鐘,可接石英 /陶瓷諧振器,或者接外部陶瓷諧振器,或者接外部時鐘源,頻率范圍為時鐘源,頻率范圍為4MHz16MHz。 我們的開發(fā)板接的是我們的開發(fā)板接的是 8M 的晶振。的晶

30、振。、 LSI 是低速內(nèi)部時鐘,是低速內(nèi)部時鐘, RC 振蕩器,頻率為振蕩器,頻率為 40kHz。 獨立獨立看門狗的時鐘源只能是看門狗的時鐘源只能是 LSI,同時,同時 LSI 還可以作為還可以作為 RTC 的時鐘的時鐘源。源。、 LSE 是低速外部時鐘,接頻率為是低速外部時鐘,接頻率為 32.768kHz 的石英晶體。的石英晶體。 這個主要是這個主要是 RTC 的時鐘源。的時鐘源。、 PLL 為鎖相環(huán)倍頻輸出,其時鐘輸入源可選擇為為鎖相環(huán)倍頻輸出,其時鐘輸入源可選擇為 HSI/2、 HSE 或者或者 HSE/2。倍頻可選擇為。倍頻可選擇為216 倍,但是其輸出頻率最大倍,但是其輸出頻率最大不

31、得超過不得超過 72MHz。那么這那么這 5 個時鐘源是怎么給各個外設(shè)以及系統(tǒng)提供時鐘的呢?個時鐘源是怎么給各個外設(shè)以及系統(tǒng)提供時鐘的呢?A. MCO 是是 STM32 的一個時鐘輸出的一個時鐘輸出 IO(PA8),它可以選擇一個,它可以選擇一個時鐘信號輸出,時鐘信號輸出, 可以選擇為可以選擇為 PLL 輸出的輸出的 2 分頻、分頻、 HSI、 HSE、或者系統(tǒng)時鐘。這個時鐘可以用來給外部其他系統(tǒng)提供時鐘源?;蛘呦到y(tǒng)時鐘。這個時鐘可以用來給外部其他系統(tǒng)提供時鐘源。B. 這里是這里是 RTC 時鐘源,從圖上可以看出,時鐘源,從圖上可以看出, RTC 的時鐘源可以的時鐘源可以選擇選擇 LSI, L

32、SE,以及,以及HSE 的的 128 分頻。分頻。C. 從圖中可以看出從圖中可以看出 C 處處 USB 的時鐘是來自的時鐘是來自 PLL 時鐘源時鐘源.STM32 中有一個全速功能的中有一個全速功能的 USB 模塊,其串行接口引擎需要一個頻率模塊,其串行接口引擎需要一個頻率為為 48MHz 的時鐘源。該時鐘源只能從的時鐘源。該時鐘源只能從 PLL 輸出端獲取,可以選輸出端獲取,可以選擇為擇為 1.5 分頻或者分頻或者 1 分頻,也就是,當(dāng)需要使用分頻,也就是,當(dāng)需要使用 USB模塊時,模塊時,PLL 必須使能,并且時鐘頻率配置為必須使能,并且時鐘頻率配置為 48MHz 或或 72MHz。D.

33、處就是處就是 STM32 的系統(tǒng)時鐘的系統(tǒng)時鐘 SYSCLK,它是供,它是供 STM32 中絕大中絕大部分部件工作的時鐘源。部分部件工作的時鐘源。 系統(tǒng)時鐘可選擇為系統(tǒng)時鐘可選擇為 PLL 輸出、輸出、 HSI 或或者者 HSE。系統(tǒng)時鐘最大頻率為。系統(tǒng)時鐘最大頻率為 72MHz. 這里的這里的 E 處是指其他所有外設(shè)了。從時鐘圖上可以看出,其處是指其他所有外設(shè)了。從時鐘圖上可以看出,其他所有外設(shè)的時鐘最終來源都是他所有外設(shè)的時鐘最終來源都是 SYSCLK。 SYSCLK 通過通過 AHB 分頻器分頻后送給各模塊使用。這些模塊包括:分頻器分頻后送給各模塊使用。這些模塊包括:、 AHB 總線、內(nèi)

34、核、內(nèi)存和總線、內(nèi)核、內(nèi)存和 DMA 使用的使用的 HCLK 時鐘。時鐘。、通過、通過 8 分頻后送給分頻后送給 Cortex 的系統(tǒng)定時器時鐘,也就是的系統(tǒng)定時器時鐘,也就是 systick 、直接送給、直接送給 Cortex 的空閑運行時鐘的空閑運行時鐘 FCLK。、送給、送給 APB1 分頻器。分頻器。 APB1 分頻器輸出一路供分頻器輸出一路供 APB1 外設(shè)使外設(shè)使用用(PCLK1,最大頻率,最大頻率 36MHz),另一路送給定時器,另一路送給定時器(Timer)2、 3、 4 倍頻器使用。倍頻器使用。、送給、送給 APB2 分頻器。分頻器。 APB2 分頻器分頻輸出一路供分頻器分頻

35、輸出一路供 APB2 外外設(shè)使用設(shè)使用(PCLK2,最大頻率,最大頻率 72MHz),另一路送給定時器,另一路送給定時器(Timer)1 倍頻器使用。倍頻器使用。 其中需要理解的是其中需要理解的是 APB1 和和 APB2 的區(qū)別,的區(qū)別, APB1 上面連接上面連接的是低速外設(shè),包括電源接口、備份接口、的是低速外設(shè),包括電源接口、備份接口、 CAN、 USB、 I2C1、 I2C2、 UART2、 UART3 等等,等等, APB2 上面連接的是高速外設(shè)包上面連接的是高速外設(shè)包括括 UART1、 SPI1、 Timer1、 ADC1、 ADC2、所有普通、所有普通 IO 口口(PAPE)、第

36、二功能、第二功能 IO 口等??诘取T谝陨系臅r鐘輸出中,有很多是帶使能控制的,例如在以上的時鐘輸出中,有很多是帶使能控制的,例如AHB 總線總線時鐘、內(nèi)核時鐘、各種時鐘、內(nèi)核時鐘、各種 APB1外設(shè)、外設(shè)、 APB2 外設(shè)等等。當(dāng)需要外設(shè)等等。當(dāng)需要使用某模塊時,記得一定要先使能對應(yīng)的時鐘。使用某模塊時,記得一定要先使能對應(yīng)的時鐘。 后面我們講解后面我們講解實例的時候會講解到時鐘使能的方法。實例的時候會講解到時鐘使能的方法。STM32 時鐘系統(tǒng)的配置除了初始化的時候在時鐘系統(tǒng)的配置除了初始化的時候在 system_stm32f10 x.c 中的中的 SystemInit()函數(shù)中外,其他的配置

37、主函數(shù)中外,其他的配置主要在要在 stm32f10 x_rcc.c 文件中,里面有很多時鐘設(shè)置函數(shù),大家文件中,里面有很多時鐘設(shè)置函數(shù),大家可以打開這個文件瀏覽一下,基本上看看函數(shù)的名稱就知道這可以打開這個文件瀏覽一下,基本上看看函數(shù)的名稱就知道這個函數(shù)的作用。這里需要指明一下,對于系統(tǒng)時鐘,默認情況個函數(shù)的作用。這里需要指明一下,對于系統(tǒng)時鐘,默認情況下是在下是在 SystemInit 函數(shù)的函數(shù)的 SetSysClock()函數(shù)中間判斷的,而設(shè)函數(shù)中間判斷的,而設(shè)置是通過宏定義設(shè)置的。我們可以看看置是通過宏定義設(shè)置的。我們可以看看 SetSysClock()函數(shù)體:函數(shù)體:static v

38、oid SetSysClock(void)#ifdef SYSCLK_FREQ_HSESetSysClockToHSE();#elif defined SYSCLK_FREQ_24MHzSetSysClockTo24();#elif defined SYSCLK_FREQ_36MHzSetSysClockTo36();#elif defined SYSCLK_FREQ_48MHzSetSysClockTo48();#elif defined SYSCLK_FREQ_56MHzSetSysClockTo56();#elif defined SYSCLK_FREQ_72MHzSetSysClock

39、To72();#endif這段代碼非常簡單,就是判斷系統(tǒng)宏定義的時鐘是多少,這段代碼非常簡單,就是判斷系統(tǒng)宏定義的時鐘是多少,然后設(shè)置相應(yīng)值。我們系統(tǒng)默認宏定義是然后設(shè)置相應(yīng)值。我們系統(tǒng)默認宏定義是 72MHz:#define SYSCLK_FREQ_72MHz 72000000如果你要設(shè)置為如果你要設(shè)置為 36MHz,只需要注釋掉上面代碼,然后,只需要注釋掉上面代碼,然后加入下面代碼即可:加入下面代碼即可:#define SYSCLK_FREQ_36MHz 36000000同時還要注意的是,當(dāng)我們設(shè)置好系統(tǒng)時鐘后,可以通過變量同時還要注意的是,當(dāng)我們設(shè)置好系統(tǒng)時鐘后,可以通過變量 Syste

40、mCoreClock 獲取系統(tǒng)時鐘值,如果系統(tǒng)是獲取系統(tǒng)時鐘值,如果系統(tǒng)是 72M 時鐘,時鐘,那么那么 SystemCoreClock=72000000。這是在。這是在 system_stm32f10 x.c 文件中設(shè)置的:文件中設(shè)置的:#ifdef SYSCLK_FREQ_HSEuint32_t SystemCoreClock = SYSCLK_FREQ_HSE;#elif defined SYSCLK_FREQ_36MHzuint32_t SystemCoreClock = SYSCLK_FREQ_36MHz;#elif defined SYSCLK_FREQ_48MHzuint32_t

41、 SystemCoreClock = SYSCLK_FREQ_48MHz;#elif defined SYSCLK_FREQ_56MHzuint32_t SystemCoreClock = SYSCLK_FREQ_56MHz;#elif defined SYSCLK_FREQ_72MHzuint32_t SystemCoreClock = SYSCLK_FREQ_72MHz;#elseuint32_t SystemCoreClock = HSI_VALUE;#endif這里總結(jié)一下這里總結(jié)一下 SystemInit()函數(shù)中設(shè)置的系統(tǒng)時鐘大?。汉瘮?shù)中設(shè)置的系統(tǒng)時鐘大?。篠YSCLK(系統(tǒng)時鐘)

42、(系統(tǒng)時鐘) =72MHzAHB 總線時鐘總線時鐘(使用使用 SYSCLK) =72MHzAPB1 總線時鐘總線時鐘(PCLK1) =36MHzAPB2 總線時鐘總線時鐘(PCLK2) =72MHzPLL 時鐘時鐘 =72MHz端口復(fù)用和重映射端口復(fù)用和重映射端口復(fù)用功能端口復(fù)用功能STM32 有很多的內(nèi)置外設(shè),這些外設(shè)的外部引腳都是有很多的內(nèi)置外設(shè),這些外設(shè)的外部引腳都是與與 GPIO 復(fù)用的。也就是說,一個復(fù)用的。也就是說,一個 GPIO如果可以復(fù)用為內(nèi)置如果可以復(fù)用為內(nèi)置外設(shè)的功能引腳,那么當(dāng)這個外設(shè)的功能引腳,那么當(dāng)這個 GPIO 作為內(nèi)置外設(shè)使用的時作為內(nèi)置外設(shè)使用的時候,就叫做復(fù)用

43、。候,就叫做復(fù)用。大家都知道,大家都知道, MCU 都有串口,都有串口, STM32 有好幾個串口。有好幾個串口。比如說比如說 STM32F103ZET6 有有 5 個串口,我們可以查手冊知道,個串口,我們可以查手冊知道,串口串口 1 的引腳對應(yīng)的的引腳對應(yīng)的 IO 為為 PA9,PA10。 PA9,PA10 默認功能是默認功能是GPIO, 所以當(dāng)所以當(dāng)PA9,PA10 引腳作為串口引腳作為串口 1 的的 TX,RX 引腳使用引腳使用的時候,那就是端口復(fù)用。的時候,那就是端口復(fù)用。復(fù)用端口初始化有幾個步驟:復(fù)用端口初始化有幾個步驟:1) GPIO 端口時鐘使能。要使用到端口復(fù)用,當(dāng)然要使端口時

44、鐘使能。要使用到端口復(fù)用,當(dāng)然要使能端口的時鐘了。能端口的時鐘了。RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);2) 復(fù)用的外設(shè)時鐘使能。比如你要將端口復(fù)用的外設(shè)時鐘使能。比如你要將端口 PA9,PA10 復(fù)復(fù)用為串口,所以要使能串口時鐘。用為串口,所以要使能串口時鐘。RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);3) 端口模式配置。端口模式配置。 在在 IO 復(fù)用位內(nèi)置外設(shè)功能引腳的時復(fù)用位內(nèi)置外設(shè)功能引腳的時候,必須設(shè)置候,必須設(shè)置 GPIO 端口的模式,至于在復(fù)用功能

45、下端口的模式,至于在復(fù)用功能下 GPIO 的模式是怎么對應(yīng)的,這個可以查看手冊的模式是怎么對應(yīng)的,這個可以查看手冊 。這里。這里我們拿我們拿 Usart1 舉例:舉例:從表格中可以看出,我們要配置全雙工的串口從表格中可以看出,我們要配置全雙工的串口 1,那么,那么 TX 管管腳需要配置為推挽復(fù)用輸出,腳需要配置為推挽復(fù)用輸出,RX 管腳配置為浮空輸入或者帶管腳配置為浮空輸入或者帶上拉輸入。上拉輸入。我們在使用復(fù)用功能的是時候,最少要使能我們在使用復(fù)用功能的是時候,最少要使能 2 個時鐘:個時鐘:1) GPIO 時鐘使能時鐘使能2) 復(fù)用的外設(shè)時鐘使能復(fù)用的外設(shè)時鐘使能同時要初始化同時要初始化

46、GPIO 以及復(fù)用外設(shè)功能以及復(fù)用外設(shè)功能/USART1_TX PA.9 復(fù)用推挽輸出復(fù)用推挽輸出GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; /PA.9GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; /復(fù)用推挽輸復(fù)用推挽輸出出GPIO_Init(GPIOA, &GPIO_InitStructure);/USART1_RX PA.10 浮空輸入浮空輸入GPIO_InitStructure.GPIO_Pin

47、 = GPIO_Pin_10;/PA10GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;/浮空輸入浮空輸入GPIO_Init(GPIOA, &GPIO_InitStructure);端口重映射端口重映射為了使不同器件封裝的外設(shè)為了使不同器件封裝的外設(shè) IO 功能數(shù)量達到最優(yōu),可功能數(shù)量達到最優(yōu),可以把一些復(fù)用功能重新映射到其他一些引腳上。以把一些復(fù)用功能重新映射到其他一些引腳上。 STM32 中有中有很多內(nèi)置外設(shè)的輸入輸出引腳都具有重映射很多內(nèi)置外設(shè)的輸入輸出引腳都具有重映射(remap) 的功能。的功能。 我們知道每個內(nèi)置外設(shè)

48、都有若干個輸入輸出引腳,一般這些引我們知道每個內(nèi)置外設(shè)都有若干個輸入輸出引腳,一般這些引腳的輸出端口都是固定不變的,為了讓設(shè)計工程師可以更好地腳的輸出端口都是固定不變的,為了讓設(shè)計工程師可以更好地安排引腳的走向和功能,在安排引腳的走向和功能,在 STM32 中引入了外設(shè)引腳重映射中引入了外設(shè)引腳重映射的概念,即一個外設(shè)的引腳除了具有默認的端口外,還可以通的概念,即一個外設(shè)的引腳除了具有默認的端口外,還可以通過設(shè)置重映射寄存器的方式,把這個外設(shè)的引腳映射到其它的過設(shè)置重映射寄存器的方式,把這個外設(shè)的引腳映射到其它的端口。簡單的講就是把管腳的外設(shè)功能映射到另一個管腳,但端口。簡單的講就是把管腳的外

49、設(shè)功能映射到另一個管腳,但不是可以隨便映射的不是可以隨便映射的.上圖是截取的中文參考手冊中的重映射表,從表中可以上圖是截取的中文參考手冊中的重映射表,從表中可以看出,默認情況下,串口看出,默認情況下,串口 1 復(fù)用的時候的引腳位復(fù)用的時候的引腳位 PA9,PA10,同,同時我們可以將時我們可以將 TX 和和 RX 重新映射到管腳重新映射到管腳 PB6 和和 PB7 上面去。上面去。所以重映射我們同樣要使能復(fù)用功能的時候講解的所以重映射我們同樣要使能復(fù)用功能的時候講解的 2 個時鐘外,個時鐘外,還要使能還要使能 AFIO 功能時鐘,然后要調(diào)用重映射函數(shù)。功能時鐘,然后要調(diào)用重映射函數(shù)。 1) 使

50、能使能 GPIOB 時鐘:時鐘:RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);2) 使能串口使能串口 1 時鐘:時鐘:RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);3) 使能使能 AFIO 時鐘:時鐘:RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);4) 開啟重映射:開啟重映射:GPIO_PinRemapConfig(GPIO_Remap_USART1, ENABLE);這樣就將串口的這樣就將串口的 TX 和和 RX

51、重映射到管腳重映射到管腳 PB6 和和 PB7 上面了。上面了。有哪些功能可以重映射,大家除了查看中文參考手冊之有哪些功能可以重映射,大家除了查看中文參考手冊之外,還可以從外,還可以從 GPIO_PinRemapConfig 函數(shù)入手查看第一個入函數(shù)入手查看第一個入口參數(shù)的取值范圍可以得知。在口參數(shù)的取值范圍可以得知。在 stm32f10 x_gpio.h 文件中定義文件中定義了取值范圍為下面宏定義的標(biāo)識符,這里我們貼一小部分:了取值范圍為下面宏定義的標(biāo)識符,這里我們貼一小部分:#define GPIO_Remap_SPI1 (uint32_t)0 x00000001)#define GPIO

52、_Remap_I2C1 (uint32_t)0 x00000002)#define GPIO_Remap_USART1 (uint32_t)0 x00000004)#define GPIO_Remap_USART2 (uint32_t)0 x00000008)#define GPIO_PartialRemap_USART3 (uint32_t)0 x00140010)#define GPIO_FullRemap_USART3 (uint32_t)0 x00140030)從上面可以看出,從上面可以看出, USART1 只有一種重映射,而對于只有一種重映射,而對于 USART3, 存在部分重映射和

53、完全重映射。存在部分重映射和完全重映射。 所謂部分重映射就是所謂部分重映射就是部分管腳和默認的是一樣的,而部分管腳是重新映射到其他管部分管腳和默認的是一樣的,而部分管腳是重新映射到其他管腳。腳。 而完全重映射就是所有管腳都重新映射到其他管腳。而完全重映射就是所有管腳都重新映射到其他管腳。部分重映射就是部分重映射就是 PB10, PB11,PB12 重映射到重映射到 PC10,PC11,PC12 上。而上。而 PB13 和和 PB14 和沒有重映射情況是一樣和沒有重映射情況是一樣的,都是的,都是USART3_CTS 和和 USART3_RTS 對應(yīng)管腳。對應(yīng)管腳。 完全重映完全重映射就是將這兩個

54、腳重新映射到射就是將這兩個腳重新映射到 PD11 和和 PD12 上去。上去。 我們要使用我們要使用 USART3 的部分重映射,我們調(diào)用函數(shù)方法為:的部分重映射,我們調(diào)用函數(shù)方法為:GPIO_PinRemapConfig(GPIO_PartialRemap_USART3, ENABLE);STM32 NVIC 中斷優(yōu)先級管理中斷優(yōu)先級管理CM3 內(nèi)核支持內(nèi)核支持 256 個中斷,其中包含了個中斷,其中包含了 16 個內(nèi)核中斷個內(nèi)核中斷和和 240 個外部中斷,并且具有個外部中斷,并且具有 256級的可編程中斷設(shè)置。但級的可編程中斷設(shè)置。但 STM32 并沒有使用并沒有使用 CM3 內(nèi)核的全部

55、東西,而是只用了它的一內(nèi)核的全部東西,而是只用了它的一部分。部分。STM32 有有 84 個中斷,包括個中斷,包括 16 個內(nèi)核中斷和個內(nèi)核中斷和 68 個可屏個可屏蔽中斷,具有蔽中斷,具有 16 級可編程的中斷優(yōu)先級。而我們常用的就是這級可編程的中斷優(yōu)先級。而我們常用的就是這 68 個可屏蔽中斷,但是個可屏蔽中斷,但是 STM32 的的 68 個可屏蔽中斷,在個可屏蔽中斷,在 STM32F103 系列上面,又只有系列上面,又只有 60 個(在個(在 107 系列才有系列才有 68 個)。個)。所以我們就只針對所以我們就只針對 STM32F103 系列這系列這 60 個可屏蔽中斷進行介個可屏蔽

56、中斷進行介紹。紹。在在 MDK 內(nèi),與內(nèi),與 NVIC 相關(guān)的寄存器,相關(guān)的寄存器, MDK 為其定義為其定義了如下的結(jié)構(gòu)體:了如下的結(jié)構(gòu)體:typedef structvu32 ISER2;u32 RESERVED030;vu32 ICER2;u32 RSERVED130;vu32 ISPR2;u32 RESERVED230;vu32 ICPR2;u32 RESERVED330;vu32 IABR2;u32 RESERVED462;vu32 IPR15; NVIC_TypeDef;STM32 的中斷在這些寄存器的控制下有序的執(zhí)行的。只的中斷在這些寄存器的控制下有序的執(zhí)行的。只有了解這些中斷寄

57、存器,才能了解有了解這些中斷寄存器,才能了解STM32 的中斷。下面簡要介的中斷。下面簡要介紹這幾個寄存器:紹這幾個寄存器:ISER2: ISER 全稱是:全稱是: Interrupt Set-Enable Registers,這,這是一個中斷使能寄存器組。上面說了是一個中斷使能寄存器組。上面說了 STM32F103 的可屏蔽中的可屏蔽中斷只有斷只有 60 個,這里用了個,這里用了 2 個個 32 位的寄存器,總共可以表示位的寄存器,總共可以表示 64 個中斷。而個中斷。而 STM32F103 只用了其中的前只用了其中的前 60 位。位。 ISER0的的 bit0bit31 分別對應(yīng)中斷分別對

58、應(yīng)中斷 031。 ISER1的的 bit027 對應(yīng)中斷對應(yīng)中斷 3259;這樣總共;這樣總共 60 個中斷就分別對應(yīng)上了。你要使能某個中個中斷就分別對應(yīng)上了。你要使能某個中斷,必須設(shè)置相應(yīng)的斷,必須設(shè)置相應(yīng)的 ISER 位為位為 1,使該中斷被使能,使該中斷被使能(這里僅僅這里僅僅是使能,還要配合中斷分組、屏蔽、是使能,還要配合中斷分組、屏蔽、 IO 口映射等設(shè)置才算是口映射等設(shè)置才算是一個完整的中斷設(shè)置一個完整的中斷設(shè)置)。ICER2:全稱是:全稱是: Interrupt Clear-Enable Registers,是一個中斷除能,是一個中斷除能寄存器組。該寄存器組與寄存器組。該寄存器組

59、與 ISER 的作用恰好相反,是用來清除某個中斷的作用恰好相反,是用來清除某個中斷的使能的。其對應(yīng)位的功能,也和的使能的。其對應(yīng)位的功能,也和 ICER 一樣。這里要專門設(shè)置一個一樣。這里要專門設(shè)置一個 ICER 來清除中斷位,而不是向來清除中斷位,而不是向 ISER 寫寫 0 來清除,是因為來清除,是因為 NVIC 的這的這些寄存器都是寫些寄存器都是寫 1 有效的,寫有效的,寫 0 是無效的。是無效的。ISPR2:全稱是:全稱是: Interrupt Set-Pending Registers,是一個中斷掛起,是一個中斷掛起控制寄存器組。每個位對應(yīng)的中斷和控制寄存器組。每個位對應(yīng)的中斷和 I

60、SER 是一樣的。通過置是一樣的。通過置 1,可以,可以將正在進行的中斷掛起,而執(zhí)行同級或更高級別的中斷。寫將正在進行的中斷掛起,而執(zhí)行同級或更高級別的中斷。寫 0 是無效的是無效的.ICPR2:全稱是:全稱是: Interrupt Clear-Pending Registers,是一個中斷解,是一個中斷解掛控制寄存器組。其作用與掛控制寄存器組。其作用與 ISPR 相反,對應(yīng)位也和相反,對應(yīng)位也和 ISER 是一樣的。是一樣的。通過設(shè)置通過設(shè)置 1,可以將掛起的中斷接掛。寫,可以將掛起的中斷接掛。寫 0 無效。無效。IABR2:全稱是:全稱是: Interrupt Active Bit Registers,是一個中斷激活標(biāo),是一

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

最新文檔

評論

0/150

提交評論