本实验源码为参考代码,可以在EK-TM4C123GXL上进行验证。
演示代码并非最优代码,是从易于理解的角度出发,争取做到最好理解的代码。
//*****************************************************************************
// 基础练习1.3: 按键控制LED灯亮灭
//
// 本例程在前一个例程的基础上,按键识别采用中断的方式进行实现。
//
// 过程描述:
// 1. 从硬件电路中可知,按键未按下时,引脚是高电平;按键按下时,接地,引脚是低电平;
// 用户按键时,从高电平到低电平的变化,产生一个下降沿。
// 把按键的引脚设置为输入,使能下降沿中断。
// 2. 把引脚配置成GPIO,输出。 通过输出高电平和低电平来控制LED的亮和灭。
// 3. 要简单点,可以直接在GPIO中断中对LED灯进行操作。为了后续的方便,采用存储按键值的方式。
// 4. K1->D2, K2->D3, K3->D4
//
// 硬件描述:
// LED2(蓝色) --PF0
// LED3(绿色) --PA4
// LED4(红色) --PD6
// K1 -- PD7
// K2 -- PF4
// K3 -- PA3
// K4 -- PA2
//
// 注意事项:
// 引脚PF0和PD7比较特殊,默认是保护的。要重新编程操作的话,需要先解锁
// 小技巧:
// 通过SysConfig工具进行引脚的初始配置,就不用考虑这些因素了.
// SysConfig的使用可参考链接: https://www.bilibili.com/read/cv6258251
//
//
//*****************************************************************************
#include
#include
#include "inc/hw_gpio.h"
#include "inc/hw_memmap.h"
#include "inc/hw_types.h"
#include "driverlib/gpio.h"
#include "driverlib/sysctl.h"
//宏定义,用一个变量来存储键值; 0000 x x x x
//低4位,有按键按下时,该比特位置位1; 按键响应后该比特位清零
#define KEY_VALUE_KEY1 0x01
#define KEY_VALUE_KEY2 0x02
#define KEY_VALUE_KEY3 0x04
#define KEY_VALUE_KEY4 0x08
#define KEY_VALUE_NOKEY 0x00
//变量定义
uint8_t key_value; //储存键值
//*****************************************************************************
//
// 中断服务函数--GPIO中断
//
// Key1 -- PD7
// Key2 -- PF4
// Key3 -- PA3
// Key4 -- PA2
// 因为按键分布在不同的端口,所以中断要分别处理。
// 该例程只是简单处理LED,可以直接在中断里边处理。
// 考虑到后续的延续性,在中断里只做键值的处理。
//*****************************************************************************
void Key1IntHandler()
{
static uint32_t ui32Status;
//读取中断标志,变量
ui32Status = GPIOIntStatus(GPIO_PORTD_BASE,true);
//手动清除中断标志
GPIOIntClear(GPIO_PORTD_BASE,ui32Status);
//对变量进行判断处理
if(ui32Status & GPIO_INT_PIN_7)
{
key_value |= KEY_VALUE_KEY1;
}
}
void Key2IntHandler()
{
static uint32_t ui32Status;
//读取中断标志,变量
ui32Status = GPIOIntStatus(GPIO_PORTF_BASE,true);
//手动清除中断标志
GPIOIntClear(GPIO_PORTF_BASE,ui32Status);
//对变量进行判断处理
if(ui32Status & GPIO_INT_PIN_4)
{
key_value |= KEY_VALUE_KEY2;
}
}
void Key3and4IntHandler()
{
static uint32_t ui32Status;
//读取中断标志,变量
ui32Status = GPIOIntStatus(GPIO_PORTA_BASE,true);
//手动清除中断标志
GPIOIntClear(GPIO_PORTA_BASE,ui32Status);
//对变量进行判断处理
if(ui32Status & GPIO_INT_PIN_3)
{
key_value |= KEY_VALUE_KEY3;
}
if(ui32Status & GPIO_INT_PIN_2)
{
key_value |= KEY_VALUE_KEY4;
}
}
void main(void)
{
//用来存储当前的LED状态.
//0表示关 ,1表示开.可以用宏定义.
uint8_t led2,led3,led4;
//-----------外设使能-------------
//使能PA外设的时钟,并等待Ready
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
while(!SysCtlPeripheralReady(SYSCTL_PERIPH_GPIOA))
{
}
//使能PD外设的时钟,并等待Ready
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOD);
while(!SysCtlPeripheralReady(SYSCTL_PERIPH_GPIOD))
{
}
//使能PF外设的时钟,并等待Ready
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);
while(!SysCtlPeripheralReady(SYSCTL_PERIPH_GPIOF))
{
}
//-----------引脚配置-------------
//PA4->绿色LED,将PA4配置成GPIO,输出
GPIOPinTypeGPIOOutput(GPIO_PORTA_BASE, GPIO_PIN_4);
//PD6->红色LED,将PD6配置成GPIO,输出
GPIOPinTypeGPIOOutput(GPIO_PORTD_BASE, GPIO_PIN_6);
//PF0->蓝色LED,将PF0配置成GPIO,输出
HWREG(GPIO_PORTF_BASE+GPIO_O_LOCK) = GPIO_LOCK_KEY;
HWREG(GPIO_PORTF_BASE+GPIO_O_CR) |= GPIO_PIN_0;
HWREG(GPIO_PORTF_BASE+GPIO_O_LOCK) = 0x0;
GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, GPIO_PIN_0);
//PD7->K1,将PD7配置成GPIO,输入
HWREG(GPIO_PORTD_BASE+GPIO_O_LOCK) = GPIO_LOCK_KEY;
HWREG(GPIO_PORTD_BASE+GPIO_O_CR) |= GPIO_PIN_7;
HWREG(GPIO_PORTD_BASE+GPIO_O_LOCK) = 0x0;
GPIOPinTypeGPIOInput(GPIO_PORTD_BASE, GPIO_PIN_7);
//PF4->K2,将PF4配置成GPIO,输入
GPIOPinTypeGPIOInput(GPIO_PORTF_BASE, GPIO_PIN_4);
//PA3->K3,将PA3配置成GPIO,输入
GPIOPinTypeGPIOInput(GPIO_PORTA_BASE, GPIO_PIN_3);
//PA2->K4,将PA2配置成GPIO,输入
GPIOPinTypeGPIOInput(GPIO_PORTA_BASE, GPIO_PIN_2);
//---------按键引脚的中断设置---------
//先设置为下降沿触发,然后使能中断,注册中断函数
// Key1 -- PD7
GPIOIntTypeSet(GPIO_PORTD_BASE,GPIO_PIN_7,GPIO_FALLING_EDGE);
GPIOIntEnable(GPIO_PORTD_BASE,GPIO_PIN_7);
GPIOIntRegister(GPIO_PORTD_BASE, Key1IntHandler);
// Key2 -- PF4
GPIOIntTypeSet(GPIO_PORTF_BASE,GPIO_PIN_4,GPIO_FALLING_EDGE);
GPIOIntEnable(GPIO_PORTF_BASE,GPIO_PIN_4);
GPIOIntRegister(GPIO_PORTF_BASE, Key2IntHandler);
// Key3 -- PA3
GPIOIntTypeSet(GPIO_PORTA_BASE,GPIO_PIN_3,GPIO_FALLING_EDGE);
GPIOIntEnable(GPIO_PORTA_BASE,GPIO_PIN_3);
GPIOIntRegister(GPIO_PORTA_BASE, Key3and4IntHandler);
// Key4 -- PA2
GPIOIntTypeSet(GPIO_PORTA_BASE,GPIO_PIN_2,GPIO_FALLING_EDGE);
GPIOIntEnable(GPIO_PORTA_BASE,GPIO_PIN_2);
//-----------LED状态初始化-------------
//PA4输出高电平,绿色LED灭
GPIOPinWrite(GPIO_PORTA_BASE,GPIO_PIN_4,0xFF);
//PD6输出高电平,红色LED灭
GPIOPinWrite(GPIO_PORTD_BASE,GPIO_PIN_6,0xFF);
//PF0输出高电平,蓝色LED灭
GPIOPinWrite(GPIO_PORTF_BASE,GPIO_PIN_0,0xFF);
led2 = 0;
led3 = 0;
led4 = 0;
while(1)
{
//依次对按键值的各个位进行判断
if(key_value & KEY_VALUE_KEY1)
{
//键值清零
key_value &= ~(KEY_VALUE_KEY1);
//判断当前的LED状态,取反
if(0==led2)
{
//PF0输出低电平,蓝色LED亮
GPIOPinWrite(GPIO_PORTF_BASE,GPIO_PIN_0,0x00);
//修改状态标志,led的状态为 亮
led2 = 1;
}
else
{
//PF0输出高电平,蓝色LED灭
GPIOPinWrite(GPIO_PORTF_BASE,GPIO_PIN_0,0xFF);
//修改状态标志,led的状态为 灭
led2 = 0;
}
}
if(key_value & KEY_VALUE_KEY2)
{
//键值清零
key_value &= ~(KEY_VALUE_KEY2);
//判断当前的LED状态,取反
if(0==led3)
{
//PA4输出低电平,绿色LED亮
GPIOPinWrite(GPIO_PORTA_BASE,GPIO_PIN_4,0x00);
//修改状态标志,led的状态为 亮
led3 = 1;
}
else
{
//PA4输出高电平,绿色LED灭
GPIOPinWrite(GPIO_PORTA_BASE,GPIO_PIN_4,0xFF);
//修改状态标志,led的状态为 灭
led3 = 0;
}
}
if(key_value & KEY_VALUE_KEY3)
{
//键值清零
key_value &= ~(KEY_VALUE_KEY3);
//判断当前的LED状态,取反
if(0==led4)
{
//PD6输出低电平,红色LED亮
GPIOPinWrite(GPIO_PORTD_BASE,GPIO_PIN_6,0x00);
//修改状态标志,led的状态为 亮
led4 = 1;
}
else
{
//PD6输出高电平,红色LED灭
GPIOPinWrite(GPIO_PORTD_BASE,GPIO_PIN_6,0xFF);
//修改状态标志,led的状态为 灭
led4 = 0;
}
}
}
}