今天主要是熟悉下gpio的一些應用。最簡單的就是LED燈的控制。
下面的例子就拿L5來說明吧。
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);//enable gpio b
GPIOPinTypeGPIOOutput(GPIO_PORTB_BASE, GPIO_PIN_0);//set PB0 output
還有一種模式設定的方法GPIODirModeSet(GPIO_PORTB_BASE, GPIO_PIN_0, GPIO_DIR_MODE_OUT) ;//這個方案可以設定多個引腳,參數2為位引腳的或
控制LED燈地亮滅,就是往引腳寫入值
ledstatus = GPIOPinRead(GPIO_PORTD_BASE, GPIO_PIN_0);
GPIOPinWrite(GPIO_PORTD_BASE, GPIO_PIN_0, GPIO_PIN_0&(~ledstatus));
上面的程式是讀取L5對應管腳的值,然後使燈地狀態進行翻轉。
這裡說下GPIOPinWrite()該函數的用法。
GPIOPinWrite(GPIO_PORTD_BASE, GPIO_PIN_1, GPIO_PIN_1);
GPIOPinWrite(GPIO_PORTD_BASE, GPIO_PIN_1, ~GPIO_PIN_1);
常式上常用上面的方法。主要也就是你要讓哪個管腳置一,參數3的值中管腳對應的位必須置一。
如下各條指令都能點亮響應連接埠(假設已經都定義成輸出了)。
GPIOPinWrite(GPIO_PORTD_BASE,GPIO_PIN_0,1);
GPIOPinWrite(GPIO_PORTD_BASE,GPIO_PIN_1,2);
GPIOPinWrite(GPIO_PORTD_BASE,GPIO_PIN_2,4);
GPIOPinWrite(GPIO_PORTD_BASE,GPIO_PIN_3,8);
GPIOPinWrite(GPIO_PORTD_BASE,GPIO_PIN_4,0x10);
GPIOPinWrite(GPIO_PORTD_BASE,GPIO_PIN_5,0x20);
GPIOPinWrite(GPIO_PORTD_BASE,GPIO_PIN_6,0x40);
GPIOPinWrite(GPIO_PORTD_BASE,GPIO_PIN_7,0x80);
下面我主要講述下鍵控LED的流程,其實就是利用按鍵中斷控制燈的亮滅。
首先是配置KEY。
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOC);//Enable GPIO C
GPIOPinIntEnable(GPIO_PORTC_BASE, GPIO_PIN_4);//Enable GPIO C pin 4
GPIOPinTypeGPIOInput(GPIO_PORTC_BASE, GPIO_PIN_4);//set the pin mode is input
GPIOIntTypeSet(GPIO_PORTC_BASE, GPIO_PIN_4, GPIO_LOW_LEVEL);//set interrupt type is low Falling edge
IntEnable(INT_GPIOC);//enable GPIO C interrupt
下面是按鍵中斷的處理函數
void userkey_handler(void)
{
unsigned char ucVal;
unsigned long ulStatus;
ulStatus = GPIOPinIntStatus(GPIO_PORTC_BASE, true);// get gpio c interrupt status
GPIOPinIntClear(GPIO_PORTC_BASE, ulStatus);
// clear interrupt status
if (ulStatus & GPIO_PIN_4) // 如果KEY的中斷狀態有效
{
ucVal = GPIOPinRead(GPIO_PORTD_BASE, GPIO_PIN_0); // 翻轉LED
GPIOPinWrite(GPIO_PORTD_BASE, GPIO_PIN_0, ~ucVal);
SysCtlDelay(10 * (SysCtlClockGet() / 3000)); // 延時約10ms,消除按鍵抖動
while (GPIOPinRead(GPIO_PORTC_BASE, GPIO_PIN_4) == 0x00); // 等待KEY抬起
SysCtlDelay(10 * (SysCtlClockGet() / 3000)); // 延時約10ms,消除松鍵抖動
}
}
既然用到了SysCtlDelay()函數。在這裡也順道分析下。
#if defined(ewarm) || defined(DOXYGEN)//iar環境下
void
SysCtlDelay(unsigned long ulCount)
{
__asm(" subs r0, #1\n"
" bne.n SysCtlDelay\n"
" bx lr");
}
#endif
#if defined(codered) || defined(gcc) || defined(sourcerygxx)//codered、gcc、sourcerygcc環境下
void __attribute__((naked))
SysCtlDelay(unsigned long ulCount)
{
__asm(" subs r0, #1\n"
" bne SysCtlDelay\n"
" bx lr");
}
#endif
#if defined(rvmdk) || defined(__ARMCC_VERSION)//keil MDK環境下
__asm void
SysCtlDelay(unsigned long ulCount)
{
subs r0, #1;
bne SysCtlDelay;
bx lr;
}
#endif
#if defined(ccs)//ccs
volatile unsigned long g_ulInlineCCSWorkaround;
void
SysCtlDelay(unsigned long ulCount)
{
__asm("delay?: subs r0, #1\n"
" bne.n delay?\n"
" bx lr\n");
//
// This is needed to keep TI compiler from optimizing away this code.
//
g_ulInlineCCSWorkaround += ulCount;
}
#endif
SysCtlDelay()執行了3個彙編語句,已耗用時間3個始終周期。函數說明上: The loop takes 3 cycles/loop.
1、在主晶振6MHZ的情況下
SysCtlDelay(2); delaytime = 2 * 3 * (1/6000000) = 1us
SysCtlDelay(10
* (TheSysClock / 3000)); delaytime = 10 * (6000000/3000)* 3 * (1/6000000) = 10ms
2、在主晶振8MHZ的情況下
SysCtlDelay(2);
delaytime = 2 * 3 * (1/8000000) = 0.75us
SysCtlDelay(10
* (TheSysClock / 3000)); delaytime = 10 * (8000000/3000)* 3 * (1/8000000) = 10ms
由此
可以看出無論是多大的晶振,都是除以3000。SysCtlDelay(10 * (TheSysClock
/ 3000));這種寫法也方便移植