// SCL-------PB10
// SDA-------PB11
// INT--------PB1
// RST--------PB2編程
定義所需的IO操做宏:緩存
//IO操做函數
#define IIC_SCL PBout(10) //SCL
#define IIC_SDA PBout(11) //SDA
#define READ_SDA PBin(11) //輸入SDA 函數
宏定義模擬IIC的引腳:spa
#define GT911_PIN_SCL GPIO_Pin_10
#define GT911_PIN_SDA GPIO_Pin_113d
void SDA_IN(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
GPIO_InitStructure.GPIO_Pin = GT911_PIN_SDA;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING ;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);
}調試
void SDA_OUT(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB, ENABLE);
GPIO_InitStructure.GPIO_Pin = GT911_PIN_SDA;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP ;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);
}orm
//初始化IIC
void IIC_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB, ENABLE );
GPIO_InitStructure.GPIO_Pin = GT911_PIN_SCL|GT911_PIN_SDA;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP ;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);
GPIO_SetBits(GPIOB,GT911_PIN_SCL|GT911_PIN_SDA);
}
//產生IIC起始信號
void IIC_Start(void)
{
SDA_OUT();
IIC_SDA=1;
IIC_SCL=1;
delay_us(4);
IIC_SDA=0;//START:when CLK is high,DATA change form high to low
delay_us(4);
IIC_SCL=0;//鉗住I2C總線,準備發送或接收數據
}
//產生IIC中止信號
void IIC_Stop(void)
{
SDA_OUT();
IIC_SCL=0;
IIC_SDA=0;//STOP:when CLK is high DATA change form low to high
delay_us(4);
IIC_SCL=1;
IIC_SDA=1;//發送I2C總線結束信號
delay_us(4);
}
//等待應答信號到來
//返回值:1,接收應答失敗
// 0,接收應答成功
u8 IIC_Wait_Ack(void)
{
u8 ucErrTime=0;
SDA_IN(); //SDA設置爲輸入
IIC_SDA=1;delay_us(1);
IIC_SCL=1;delay_us(1);
while(READ_SDA)
{
ucErrTime++;
if(ucErrTime>250)
{
IIC_Stop();
return 1;
}
}
IIC_SCL=0;//時鐘輸出0
return 0;
}
//產生ACK應答
void IIC_Ack(void)
{
IIC_SCL=0;
SDA_OUT();
IIC_SDA=0;
delay_us(2);
IIC_SCL=1;
delay_us(2);
IIC_SCL=0;
}
//不產生ACK應答
void IIC_NAck(void)
{
IIC_SCL=0;
SDA_OUT();
IIC_SDA=1;
delay_us(2);
IIC_SCL=1;
delay_us(2);
IIC_SCL=0;
}
//IIC發送一個字節
//返回從機有無應答
//1,有應答
//0,無應答
void IIC_Send_Byte(u8 txd)
{
u8 t;
SDA_OUT();
IIC_SCL=0;//拉低時鐘開始數據傳輸
for(t=0;t<8;t++)
{
//IIC_SDA=(txd&0x80)>>7;
if((txd&0x80)>>7)
IIC_SDA=1;
else
IIC_SDA=0;
txd<<=1;
delay_us(2); //對TEA5767這三個延時都是必須的
IIC_SCL=1;
delay_us(2);
IIC_SCL=0;
delay_us(2);
}
}
//讀1個字節,ack=1時,發送ACK,ack=0,發送nACK
u8 IIC_Read_Byte(unsigned char ack)
{
unsigned char i,receive=0;
SDA_IN();//SDA設置爲輸入
for(i=0;i<8;i++ )
{
IIC_SCL=0;
delay_us(2);
IIC_SCL=1;
receive<<=1;
if(READ_SDA)receive++;
delay_us(1);
}
if (!ack)
IIC_NAck();//發送nACK
else
IIC_Ack(); //發送ACK
return receive;
}blog
查閱《GT911編程指南》:ip
//I2C讀寫命令
#define GT_CMD_WR 0X28 //寫命令
#define GT_CMD_RD 0X29 //讀命令
//GT911 部分寄存器定義
#define GT_CTRL_REG 0X8040 //GT911控制寄存器
#define GT_CFGS_REG 0X8047 //GT911配置起始地址寄存器
#define GT_CHECK_REG 0X80FF //GT911校驗和寄存器
#define GT_PID_REG 0X8140 //GT911產品ID寄存器get
#define GT_GSTID_REG 0X814E //GT911當前檢測到的觸摸狀況
#define GT911_PIN_INT GPIO_Pin_1
#define GT911_PIN_RST GPIO_Pin_2
typedef struct _POINT{
u16 x;
u16 y;
}POINT, *PPOINT;
typedef struct _GT911_POINT_DATA{
u8 cnt;
POINT points[5];
}GT911_POINT_DATA, *PGT911_POINT_DATA;
extern GT911_POINT_DATA gt911_data;
void GT911_INT_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
GPIO_InitStructure.GPIO_Pin = GT911_PIN_INT;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);
GPIO_ResetBits(GPIOB, GT911_PIN_INT);
}
void GT911_INT(u8 cmd)
{
if(cmd) GPIO_SetBits(GPIOB, GT911_PIN_INT);
else GPIO_ResetBits(GPIOB, GT911_PIN_INT);
}
void GT911_INT_Change(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
GPIO_InitStructure.GPIO_Pin = GT911_PIN_INT;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);
GPIO_ResetBits(GPIOB, GT911_PIN_INT);
}
void GT911_RST_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
GPIO_InitStructure.GPIO_Pin = GT911_PIN_RST;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);
GPIO_ResetBits(GPIOB, GT911_PIN_RST);
}
void GT911_RST(u8 cmd)
{
if(cmd) GPIO_SetBits(GPIOB, GT911_PIN_RST);
else GPIO_ResetBits(GPIOB, GT911_PIN_RST);
}
GT911_RST_Init();
GT911_INT_Init();
IIC_Init();GT911_RST(0);
GT911_INT(1);
delay_us(200);
GT911_RST(1);
delay_ms(6);
GT911_INT(0);
delay_ms(55);
GT911_INT_Change();
delay_ms(50);
//reg:起始寄存器地址
//buf:數據緩緩存區
//len:寫數據長度
//返回值:0,成功;1,失敗.
u8 GT911_WR_Reg(u16 reg,u8 *buf,u8 len)
{
u8 i;
u8 ret=0;
IIC_Start();
IIC_Send_Byte(GT_CMD_WR); //發送寫命令
IIC_Wait_Ack();
IIC_Send_Byte(reg>>8); //發送高8位地址
IIC_Wait_Ack();
IIC_Send_Byte(reg&0XFF); //發送低8位地址
IIC_Wait_Ack();
for(i=0;i<len;i++)
{
IIC_Send_Byte(buf[i]); //發數據
ret=IIC_Wait_Ack();
if(ret)break;
}
IIC_Stop(); //產生一箇中止條件
return ret;
}
//reg:起始寄存器地址
//buf:數據緩緩存區
//len:讀數據長度
void GT911_RD_Reg(u16 reg,u8 *buf,u8 len)
{
u8 i;
IIC_Start();
IIC_Send_Byte(GT_CMD_WR); //發送寫命令
IIC_Wait_Ack();
IIC_Send_Byte(reg>>8); //發送高8位地址
IIC_Wait_Ack();
IIC_Send_Byte(reg&0XFF); //發送低8位地址
IIC_Wait_Ack();
IIC_Start();
IIC_Send_Byte(GT_CMD_RD); //發送讀命令
IIC_Wait_Ack();
for(i=0;i<len;i++)
{
buf[i]=IIC_Read_Byte(i==(len-1)?0:1); //發數據
}
IIC_Stop();//產生一箇中止條件
}
//發送配置參數
//mode:0,參數不保存到flash
// 1,參數保存到flash
u8 GT911_Send_Cfg(u8 mode)
{
u8 buf[2];
u8 i=0;
buf[0]=0;
buf[1]=mode; //是否寫入到GT911 FLASH? 便是否掉電保存
for(i=0;i<sizeof(GT911_Cfg);i++)buf[0]+=GT911_Cfg[i];//計算校驗和
buf[0]=(~buf[0])+1;
GT911_WR_Reg(GT_CFGS_REG,(u8*)GT911_Cfg,sizeof(GT911_Cfg));//發送寄存器配置
GT911_WR_Reg(GT_CHECK_REG,buf,2);//寫入校驗和,和配置更新標記
return 0;
}
void GT911_Init(void)
{
GT911_RST_Init();
GT911_INT_Init();
IIC_Init();
GT911_RST(0);
GT911_INT(1);
delay_us(200);
GT911_RST(1);
delay_ms(6);
GT911_INT(0);
delay_ms(55);
GT911_INT_Change();
delay_ms(50);
u8 tmp[4]={0};
//讀取PID
GT911_RD_Reg(GT_PID_REG, tmp, 4);
//修改配置
tmp[0] = 0x02;
GT911_WR_Reg(GT_CTRL_REG, tmp, 1);
GT911_RD_Reg(GT_CFGS_REG, tmp, 1);
if(tmp[0] < 0x60){
printf("Default Ver:0x%X\r\n",tmp[0]);
GT911_Send_Cfg(1);
}
delay_ms(10);
tmp[0] = 0x00;
GT911_WR_Reg(GT_CTRL_REG, tmp, 1);
EXTIX_Init();
}
void EXTIX_Init(void)
{
EXTI_InitTypeDef EXTI_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);
GPIO_EXTILineConfig(GPIO_PortSourceGPIOB,GPIO_PinSource1);
EXTI_InitStructure.EXTI_Line=EXTI_Line1;
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
EXTI_Init(&EXTI_InitStructure);
NVIC_InitStructure.NVIC_IRQChannel = EXTI1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x02;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
查閱《GT911編程指南》:
void EXTI1_IRQHandler(void)
{
u8 tmp;
GT911_RD_Reg(0x8140, data, 0x40);
tmp = data[0x0E];
if((tmp&0x80) && ((tmp&0x0f)>0)){
GetPointData(tmp&0x0f, data);
ShowPointData();
}
tmp = 0;
GT911_WR_Reg(0x814E, &tmp, 1);
delay_ms(10);
EXTI_ClearITPendingBit(EXTI_Line1);
}
void GetPointData(u8 cnt, u8 data[])
{
gt911_data.cnt = 0;
switch(cnt){
case 5:
gt911_data.points[4].x = data[0x31]<<8 | data[0x30];
gt911_data.points[4].y = data[0x33]<<8 | data[0x32];
case 4:
gt911_data.points[3].x = data[0x29]<<8 | data[0x28];
gt911_data.points[3].y = data[0x2B]<<8 | data[0x2A];
case 3:
gt911_data.points[2].x = data[0x21]<<8 | data[0x20];
gt911_data.points[2].y = data[0x23]<<8 | data[0x22];
case 2:
gt911_data.points[1].x = data[0x19]<<8 | data[0x18];
gt911_data.points[1].y = data[0x1B]<<8 | data[0x1A];
case 1:
gt911_data.points[0].x = data[0x11]<<8 | data[0x10];
gt911_data.points[0].y = data[0x13]<<8 | data[0x12];
break;
default:
break;
}
gt911_data.cnt = cnt;
}
void ShowPointData(void)
{
u8 cnt = gt911_data.cnt;
for(u8 i=0; i<cnt; i++){
printf("Point%d(%d,%d)\t", i+1, gt911_data.points[i].x, gt911_data.points[i].y);
}
printf("\r\n");
memset(>911_data, 0, sizeof(gt911_data));
}
燒錄程序至MCU,接線、上電,打開串口調試助手查看打印信息(最多同時五點觸摸):