想法有了, 那麼來安排一下硬體的規劃吧 . 我們還是利用 LanchPad 上現有的 LED 和 Button . 還記的 PF0 接 SW2, PF4 接 SW1. 這一次用右下角那顆 PF0 (SW2) , 順便可以練習如何解鎖. LED是PF1(紅色) , PF2(藍色) , PF3(綠色) . 等等 ! 不是說要黃色嗎 ? 這 3 顆 LED 沒有黃色啊 ! 沒關係 , 記得黃色是等於紅色 + 綠色 , 所以我們只要同時點亮 PF1 和 PF3 就可以了 . 詳細的腳位請參考底下這三張圖 .
TM4C123G的 PF4 ~ PF0分別接到SW2, Red LED, Blue LED, Green LED and SW1
RGB LEDs 電路
SW1 & SW2 電路
因為上次使用 TivaWare時, 啟動PLL並設定MCU 的時脈為 40MHZ, 所以這次想用直接控制暫存器的方式起動 PLL (相鎖迴路) , 並控制 MCU 的時脈為 80MHZ (此為TM4C123GH6PM的最大時脈) . 還有, 想改用SysTick的計數來得到更精準的 Delay 時間.
那麼, 先從簡單的來吧 ! 首先, 我們先設定 GPIO PORT F :
void PortF_Init(void)
{
volatile unsigned long delay;
SYSCTL_RCGC2_R |= 0x00000020;
delay = SYSCTL_RCGC2_R;
GPIO_PORTF_LOCK_R = 0x4C4F434B;
GPIO_PORTF_CR_R = 0x0F;
GPIO_PORTF_AMSEL_R &= ~0x0F;
GPIO_PORTF_PCTL_R &= ~0x0000FFFF;
GPIO_PORTF_DIR_R &= ~0x01;
GPIO_PORTF_DIR_R |= 0x0E;
GPIO_PORTF_AFSEL_R &= ~0x0F;
GPIO_PORTF_PUR_R |= 0x01;
GPIO_PORTF_DEN_R |= 0x0F;
}
嗯 ! 開始有點熟悉了.... 不過多了幾行設定, 說明如下: (其他的部分, 前一篇已作過說明, 不再贅述)
GPIO_PORTF_LOCK_R = 0x4C4F434B;
GPIO_PORTF_CR_R = 0x0F;
因為 PF0 預設是鎖住的狀態 , 要使用它之前要先將它解鎖 , 根據 Data Sheet , 也就是對 GPIOLOCK 這個暫存器寫入 0x4C4F434B . GPIOCR 這個暫存器叫做 Commit 暫存器 . 只有對 GPIOLOCK 這個暫存器解鎖了, GPIOCR 這個暫存器的設定才有效 . 然而 GPIOLOCK 的 Pin 腳解鎖了, GPIOCR 這個暫存器相對應的 bit要設定為 1 . 這樣才可以做其他的設定 , 像是 GPIOAFSEL, GPIOPUR, GPIOPDR, GPIODEN .
GPIO_PORTF_PUR_R |= 0x01;
GPIOPUR 這個暫存器是設定 Pin 腳是否接 Pull High 電阻, 當Set (1) 時 , 為 Pull High 電阻 enable , Clear(0)時 , 為 Pull High 電阻 disable . 因為 我們設 PF0 是 input , SW2是負邏輯動作( 0 為 enable ), 為避免SW2未按下時, PF0 的電位不確定而造成誤動作, 所以把它設定在 MCU 內部接 Pull High 電阻 . 另外一個就是GPIOPDR了, 顧名思義也就是 Pull Down, 在使用正邏輯的 Switch 時設定.
這裡補充一下 , 怎麼會有2個 DIR 的設定呢? 第一個 GPIO_PORTF_DATA_R &= ~0x01 是將PF0設為輸入, 所以把 bit 0 寫入 " 0 " , 第二個 GPIO_PORTF_DATA_R |= 0x0E 是將 PF1, PF2, PF3設為輸出 , 所以把 bit 1, 2, 3 寫入 " 1 " . 你可能會說 Data Sheet 上說明 GPIODIR 暫存器的 bit 7 ~ 0 , Reset 後是 0x00, 所以第一個是不是多此一舉呢 ? 這是關於前面提過 Friendly Code 的部分 , 如果確定程式只有這一個地方設定 PORTF, 當然第一個可以不寫 . 然而如果是一個大程式, 而你只負責其中一小部分 , 難保其他人也設定了 PORTF bit 0, 並且設為 " 1 " . 此時第二個 GPIO_PORTF_DATA_R |= 0x0E 並不會把 PF0 更改....那麼...結果就可想而知了.所以養成好習慣還是不錯的 .
PORT F 設定完成了, 那麼開始設定 80MHZ 的 System Clock 吧. 不過在開始之前, 還是先了解一下 TM4C123GH6PM 的 Clock Tree 如下圖 : (設置的路徑會如紅色的標線)
系統時鐘設置部分有兩個暫存器, RCC 和 RCC2 : (如下圖)
如果要設置 80MHZ 要選擇 RCC2 暫存器 . 設置步驟如下 :
- 設定 RCC2 -- USERCC2 (bit 31) : 寫入 1 , 也就是 0x8000.0000 .
- 設定 RCC2 -- BYPASS2 (bit 11) : 寫入 1 , 也就是 0x0000.0800 .
- 設定 RCC -- XTAL (bit 10 ~ 6) : 寫入 0x15 (16MHZ) , , 也就是 0x0000.0540 . 0x15 等於 10101b, 依序放入 bit 10 ~ bit 6 為 101.0100.0000 就等於 0x540 .
- 清除 RCC2 -- OSCSRC2 (bit 6 ~ 4) : 寫入 0x0 (選擇 main OSC). 也就是 ~0x0000.0070 .
- 清除 RCC2 -- PWRDN2 (bit 13) : 寫入 0 (啟動 PLL). 也就是 ~0x0000.2000 .
- 設定 RCC2 -- DIV400 (bit 30) : 寫入 1. 也就是 0x4000.0000 .
- 設定 RCC2 -- SYSDIV2 (bit 28 ~ 22) : 寫入 n. 它會除以 n+1, 以 80MHZ 為例 , 寫入 4, 則 400MHZ/(4+1) = 80 MHZ .
- 等待 PLL 穩定 , 讀取 SYSCTL_RIS_R 的 Bit 6, 如果是 1 就表示穩定了.
- 清除 RCC2 -- BYPASS2 (bit 11) : 寫入 0. Enable 使用 PLL.
第三步驟提到 16MHZ 是寫入 0x15 那如果外接的 Crystal 是其他的頻率可以查下表 :
我們來看程式的部分 :
void PLL_Init(void)
{
SYSCTL_RCC2_R |= 0x80000000;
SYSCTL_RCC2_R |= 0x00000800;
SYSCTL_RCC_R = (SYSCTL_RCC_R &~0x000007C0) + 0x00000540;
SYSCTL_RCC2_R &= ~0x00000070;
SYSCTL_RCC2_R &= ~0x00002000;
SYSCTL_RCC2_R |= 0x40000000;
SYSCTL_RCC2_R = (SYSCTL_RCC2_R&~ 0x1FC00000) + (4<<22);
while((SYSCTL_RIS_R&0x00000040)==0){};
SYSCTL_RCC2_R &= ~0x00000800;
}
那如果想要設置成 50MHZ 就直接把 4 改成 7 , 400MHZ/(7+1) = 50MHZ, 所以想要更換頻率只需要更改 SYSDIV2 的值就可以了. 不過記得 TM4C123GH6PM 最大頻率為 80MHZ.
接下來說一下 SysTick 計數. SysTick 是一個 24 bits 的下數計數器, 這次我們沒有用到中斷部分 , 以下是這次使用到的暫存器 :
- NVIC_ST_CTRL_R
- NVIC_ST_RELOAD_R
- NVIC_ST_CURRENT_R
NVIC_ST_CTRL_R 暫存器是設定 Enable/Disable, Interrupt 及 flag 狀態 , 詳細如下 :
因為這次我們沒有用到中斷部分 , 所以設成 0x05 . 另外 NVIC_ST_RELOAD_R 暫存器 , 顧名思義 , 就是我們要計數器從甚麼值開始下數 , 最大值為 0x00FFFFFF. NVIC_ST_CURRENT_R 暫存器 , 當計數到 0 時 , NVIC_ST_CTRL_R 暫存器 bit 16 (count) 會設成 1 . 下一個 Clock 會把 NVIC_ST_RELOAD_R 暫存器的值重新載入. 此時NVIC_ST_CTRL_R 暫存器 bit 16 (count) 會清為 0 . 以下是 SysTick Delay 的程式內容 :
void SysTick_Init(void)
{
NVIC_ST_CTRL_R = 0;
NVIC_ST_CTRL_R = 0x00000005;
}
void SysTick_Wait(unsigned long delay)
{
NVIC_ST_RELOAD_R = delay-1;
NVIC_ST_CURRENT_R = 0;
while((NVIC_ST_CTRL_R&0x00010000)==0){ }
}
void SysTick_Wait10ms(unsigned long delay)
{
unsigned long i;
for(i=0; i<delay; i++){
SysTick_Wait(800000);
}
}
以下是完整的程式 :
#include <stdint.h>
#include "inc/tm4c123gh6pm.h"
void PLL_Init(void);
void SysTick_Init(void);
void SysTick_Wait(unsigned long delay);
void SysTick_Wait10ms(unsigned long delay);
void PortF_Init(void);
int main(void)
{
PLL_Init();
SysTick_Init();
PortF_Init();
while(1)
{
GPIO_PORTF_DATA_R ^= 0x02;
SysTick_Wait10ms(50);
if ((GPIO_PORTF_DATA_R&0x01) == 0x00)
{
SysTick_Wait10ms(1);
if ((GPIO_PORTF_DATA_R&0x01) == 0x00){
GPIO_PORTF_DATA_R = 0x0A;
SysTick_Wait10ms(200);
GPIO_PORTF_DATA_R &= ~0x02;
SysTick_Wait10ms(500);
GPIO_PORTF_DATA_R &= ~0x08;
}
}
}
}
void PLL_Init(void)
{
SYSCTL_RCC2_R |= 0x80000000;
SYSCTL_RCC2_R |= 0x00000800;
SYSCTL_RCC_R = (SYSCTL_RCC_R &~0x000007C0) + 0x00000540;
SYSCTL_RCC2_R &= ~0x00000070;
SYSCTL_RCC2_R &= ~0x00002000;
SYSCTL_RCC2_R |= 0x40000000;
SYSCTL_RCC2_R = (SYSCTL_RCC2_R&~ 0x1FC00000) + (4<<22);
while((SYSCTL_RIS_R&0x00000040)==0){};
SYSCTL_RCC2_R &= ~0x00000800;
}
void SysTick_Init(void)
{
NVIC_ST_CTRL_R = 0;
NVIC_ST_CTRL_R = 0x00000005;
}
void SysTick_Wait(unsigned long delay)
{
NVIC_ST_RELOAD_R = delay-1;
NVIC_ST_CURRENT_R = 0;
while((NVIC_ST_CTRL_R&0x00010000)==0){ }
}
void SysTick_Wait10ms(unsigned long delay)
{
unsigned long i;
for(i=0; i<delay; i++){
SysTick_Wait(800000);
}
}
void PortF_Init(void)
{
volatile unsigned long delay;
SYSCTL_RCGC2_R |= 0x00000020;
delay = SYSCTL_RCGC2_R;
GPIO_PORTF_LOCK_R = 0x4C4F434B;
GPIO_PORTF_CR_R = 0x0F;
GPIO_PORTF_AMSEL_R &= ~0x0F;
GPIO_PORTF_PCTL_R &= ~0x0000FFFF;
GPIO_PORTF_DIR_R &= ~0x01;
GPIO_PORTF_DIR_R |= 0x0E;
GPIO_PORTF_AFSEL_R &= ~0x0F;
GPIO_PORTF_PUR_R |= 0x01;
GPIO_PORTF_DEN_R |= 0x0F;
}
好了, 按下 F7 編譯 然後下載到 LaunchPad , 按一下 Reset 鍵 , 看到紅色 LED 在閃爍了 , 按一下 SW2 , 嗯 , 如所預期的 黃燈 2 秒, 綠燈 5 秒 ....就在此刻心中有種莫名的快樂與感動....
參考文獻 :
Embedded Systems: Introduction to ARM® Cortex™-M Microcontrollers - Jonathan Valvano
Getting Started with the Tiva™ TM4C123G LaunchPad Workshop
TM4C123GH6PM DATA SHEET
Embedded Systems Shape The World
參考文獻 :
Embedded Systems: Introduction to ARM® Cortex™-M Microcontrollers - Jonathan Valvano
Getting Started with the Tiva™ TM4C123G LaunchPad Workshop
TM4C123GH6PM DATA SHEET
Embedded Systems Shape The World








沒有留言:
張貼留言