今天主要是熟悉下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));这种写法也方便移植