【TI学习】从入门到熟悉6911(二)
之前提到的是对lm3s6911的GPIO,PWM,I2C等的学习,这里算是对GPIO口外部中断的使用。
很多人喜欢用轮询来做按键或者触摸屏,我选择的是用外部中断,第一我觉得中断的实时性高一些,
第二,当是对外部中断的学习。
先介绍一下我所使用的触摸屏驱动器是TSC2046,在认真研读文档之后,才明白触摸屏原来是
一种特殊的ADC,当然我所使用的是一般的电阻屏。当指尖触碰到屏幕的时候,连接外部中断的管
脚就产生一个低电平,读取那个引脚的值便可以判断,是否有接触。写过按键的朋友也一定知道,
消抖是必不可少的操作,这也是有些高手不愿意用中断的原因,消抖就会延时,简单的说,就会消
耗时间,这就使程序处理起来变得很慢。
能够判断是否有接触只是做了第一步,第二步,也是最重要的一步就是算出你所触控位置的坐标。
TSC2046可以通过SPI控制,不过我的板子上的SPI不够用,用GPIO口模拟的SPI。
下面是程序清单:
#include "hw_types.h"
#include "hw_memmap.h"
#include "sysctl.h"
#include "interrupt.h"
#include "hw_ints.h"
#include "gpio.h"
#include "touch.h"
#include "lcd.h"
#include "grlib.h"
extern unsigned long TheSysClock;
unsigned long g_sTouchX=0;
unsigned long g_sTouchY=0;
#define CS_PIN GPIO_PIN_4 //PB4
#define DCLK_PIN GPIO_PIN_5 //PB5
#define DOUT_PIN GPIO_PIN_7 //PB7
#define DIN_PIN GPIO_PIN_6 //PB6
#define IRQ_PIN GPIO_PIN_1 //PA1
#define CS_H GPIOPinWrite(GPIO_PORTC_BASE,CS_PIN,0xff);
#define CS_L GPIOPinWrite(GPIO_PORTC_BASE,CS_PIN,0x00);
#define DCLK_H GPIOPinWrite(GPIO_PORTC_BASE,DCLK_PIN,0xff);
#define DCLK_L GPIOPinWrite(GPIO_PORTC_BASE,DCLK_PIN,0x00);
//******************************初始化touchscreen*****************************
void Init_TouchScreen()
{
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOC);
GPIOPinTypeGPIOOutput(GPIO_PORTC_BASE,DCLK_PIN|DIN_PIN|CS_PIN);
GPIOPinTypeGPIOInput(GPIO_PORTC_BASE,DOUT_PIN);
GPIOPinTypeGPIOOutput(GPIO_PORTA_BASE,GPIO_PIN_1);
GPIOPinWrite(GPIO_PORTA_BASE,GPIO_PIN_1,0x00);
GPIOPinWrite(GPIO_PORTA_BASE,GPIO_PIN_1,0xff);
GPIOPinTypeGPIOInput(GPIO_PORTA_BASE,GPIO_PIN_1);
GPIOIntTypeSet(GPIO_PORTA_BASE,GPIO_PIN_1,GPIO_FALLING_EDGE);
GPIOPinIntEnable(GPIO_PORTA_BASE,GPIO_PIN_1);
IntEnable(INT_GPIOA);
IntMasterEnable();
}
unsigned long ulX=0;
unsigned long ulY=0;
//**************************PENIRQ中断处理程序********************************
void TouchScreenIntHandler()
{
//*******延时去抖*******
while(GPIOPinRead(GPIO_PORTA_BASE,IRQ_PIN)!=0x00);
SysCtlDelay(TheSysClock/300);
while(GPIOPinRead(GPIO_PORTA_BASE,IRQ_PIN)==0)
{
GPIOPinIntClear(GPIO_PORTA_BASE,IRQ_PIN);
getpoint(); //get the touch point on the panal
ulX=319*(g_sTouchX-200)/3600;
ulY=239*(g_sTouchY-300)/3300;
if(((ulX>0)&&(ulY>0))&&((ulX<320)&&(ulY<240)))
{
for(int i=0;i<=2;i++)
for(int j=0;j<=2;j++)
LCDPixelDraw(ulX+i,ulY+j,ClrBlue);
}
}
}
//******************************获取点得坐标*******************************
void getpoint(void)
{
CS_L
GPIOPinWrite(GPIO_PORTC_BASE,DCLK_PIN,0x00);
GPIOPinWrite(GPIO_PORTC_BASE,DIN_PIN,0X00); //启动SPI
Tsc2046_wr(0x90); //送控制字 10010000 即用差分方式读X坐标
g_sTouchX=Tsc2046_rd();
Tsc2046_wr(0xD0); //送控制字 11010000 即用差分方式读Y坐标
g_sTouchY=Tsc2046_rd();
CS_H;
}
//**********************************写数据************************************
void Tsc2046_wr(unsigned char num)
{
unsigned char i=0;
GPIOPinWrite(GPIO_PORTC_BASE,DCLK_PIN,0X00);
for(i=0;i<8;i++)
{
GPIOPinWrite(GPIO_PORTC_BASE,DIN_PIN,((num&0x80)==0x80) ? 0XFF:0X00);
GPIOPinWrite(GPIO_PORTC_BASE,DCLK_PIN,0X00);
SysCtlDelay(TheSysClock/30000*9);
GPIOPinWrite(GPIO_PORTC_BASE,DCLK_PIN,0xff);
// SysCtlDelay(TheSysClock/3000);
num<<=1;
}
}
//******************************读数据**********************************
unsigned int Tsc2046_rd()
{
unsigned char i=0;
unsigned int Num=0;
for(i=0;i<12;i++)
{
GPIOPinWrite(GPIO_PORTC_BASE,DCLK_PIN,0xff);
SysCtlDelay(TheSysClock/30000*9);
GPIOPinWrite(GPIO_PORTC_BASE,DCLK_PIN,0x00);
// SysCtlDelay(TheSysClock/3000);
if(GPIOPinRead(GPIO_PORTC_BASE,DOUT_PIN))
Num++;
Num<<=1;
}
return(Num);
}