RTP转CTP 接口

本文介绍了一种将电阻式触摸屏(RTP)模块模拟为电容式触摸屏(CTP)模块的方法,用于替换原有CTP+LCD模块。主要内容包括通过SPI读取XPT2406数据,并进行滤波处理;实现I2C从机通信;触摸事件的识别与保存,以及在实际应用中遇到的问题与解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

开发环境:windows32 Keil4

开发平台: 基于新唐M0516

开发背景:客户主板先前用CTP+LCD模块,因需求改变,改用RTP+LCD模块替换成CTP+LCD模块.

主要功能: 用RTP来模拟CTP FT5306功能

定义说明:

REST :GPIO5

INT:PWM

SCL:TWI2_SCK

SDA:TWI2_SDA

a.实现能读取rtp的数据
通过MCU模拟spi来读取XPT2406数据.XPT2406最高精度12bits。对采样后的数据并对数据进行虑波,并上传给主机.
b.调试通i2c作为从机与主机通信
c.对rtp数据进行解析,分离出触摸事件 按下,保持,释放。

在定时器里分离出触摸事件。

void TMR0_IRQHandler()
{ 
    static uint32_t sec =0; 
	static uint16_t temp_x, temp_y; 
	static uint16_t cnt = 0;
			
	if(press_flag && (flag == 0)){
	  	touch_Status = TP_PUT_DOWN;
		flag = 1;
		SaveData(touch_Status, read_x, read_y);
	}else if(flag && Pen_Point.X &&  press_flag){
		touch_Status = TP_CONTACT;
		SaveData(touch_Status, read_x, read_y);
		temp_x = read_x;
		temp_y = read_y;
	}else if((!press_flag) && (touch_Status == TP_CONTACT)){
		flag = 0;
		touch_Status = TP_PUT_UP;
		SaveData(touch_Status, temp_x, temp_y);
	}else if(press_flag == 0){
		touch_Status = TP_NO_EVENT;
		SaveData(touch_Status, temp_x, temp_y);
		if(!FindMsg(TP_PUT_UP)){
			ClearAllMsg();
			PWM_DisableOutput(PWMA, 0xF);
		}
	}

	TIMER_ClearIntFlag(TIMER0); 
} 


d.对触摸事件进行保存,方便主机获取到触摸数据。

用队列来保存事件.

#define MAX_MSG 30
#define TP_NO_EVENT 3
#define TP_CONTACT  2
#define TP_PUT_UP   1
#define TP_PUT_DOWN 0
#define MSG_NULL 0xff
ctpmsg msg_pool[MAX_MSG];
void SaveOneMsg(ctpmsg* msg)
{
	uint8_t i;
	
	for(i=0;i<MAX_MSG;i++){
		if(msg_pool[i].type==MSG_NULL){
			msg_pool[i].type = msg->type;
			msg_pool[i].TOUCH_Points = msg->TOUCH_Points;
			msg_pool[i].TOUCH_XL=msg->TOUCH_XL;
			msg_pool[i].TOUCH_XH=msg->TOUCH_XH;
			msg_pool[i].TOUCH_YH=msg->TOUCH_YH;
			msg_pool[i].TOUCH_YL=msg->TOUCH_YL;
			break;
			}
		}
}
void ClearAllMsg(void)
{
	uint8_t i;

	for(i=0;i<MAX_MSG;i++){
		msg_pool[i].type = MSG_NULL;
		msg_pool[i].TOUCH_Points = 0;
		msg_pool[i].TOUCH_XL = 0xFF;
		msg_pool[i].TOUCH_XH = 0xFF;
		msg_pool[i].TOUCH_YH = 0xFF;
		msg_pool[i].TOUCH_YL= 0xFF;
	}
}
uint8_t FindMsg(uint8_t msgtype)
{
	uint8_t i,j;

	for(i=0;i<MAX_MSG;i++){
		if(msg_pool[i].type==msgtype)
			return 1;
	}
	return 0;
}

uint8_t getmessage(ctpmsg* msg0)
{
	uint8_t i;
	
	if(msg_pool[0].type==MSG_NULL){
			return 0;
	}
	
	msg0->type=msg_pool[0].type;
	msg0->TOUCH_Points=msg_pool[0].TOUCH_Points;
	
	msg0->TOUCH_XL=msg_pool[0].TOUCH_XL;
	msg0->TOUCH_XH=msg_pool[0].TOUCH_XH;
	msg0->TOUCH_YH=msg_pool[0].TOUCH_YH;
	msg0->TOUCH_YL=msg_pool[0].TOUCH_YL;
	msg_pool[0].type = MSG_NULL;
	msg_pool[0].TOUCH_Points = 0;
	msg_pool[0].TOUCH_XL = 0xff;
	msg_pool[0].TOUCH_XH = 0xff;
	msg_pool[0].TOUCH_YH = 0xff;
	msg_pool[0].TOUCH_YL = 0xff;
	for(i = 1;i<MAX_MSG;i++){
		if(msg_pool[i].type == MSG_NULL) break;
			msg_pool[i-1].type=msg_pool[i].type;
			msg_pool[i-1].TOUCH_Points=msg_pool[i].TOUCH_Points;
			msg_pool[i-1].TOUCH_XL=msg_pool[i].TOUCH_XL;
			msg_pool[i-1].TOUCH_XH=msg_pool[i].TOUCH_XH;
			msg_pool[i-1].TOUCH_YH=msg_pool[i].TOUCH_YH;
			msg_pool[i-1].TOUCH_YL=msg_pool[i].TOUCH_YL;

			msg_pool[0].type = MSG_NULL;
			msg_pool[0].TOUCH_Points = 0;
			msg_pool[0].TOUCH_XL = 0xff;
			msg_pool[0].TOUCH_XH = 0xff;
			msg_pool[0].TOUCH_YH = 0xff;
			msg_pool[0].TOUCH_YL = 0xff;
		
	}


	
	return 1;
}

e.编写I2C从机程序,在I2C中断中发出数据.

void I2C_SlaveTRx(uint32_t u32Status)
{
	int i;
    if(u32Status == 0x60)                       /* Own SLA+W has been receive; ACK has been return */
    {
        g_u8DataLen = 0;
        I2C_SET_CONTROL_REG(I2C0, I2C_I2CON_SI_AA);
    }
    else if(u32Status == 0x80) /* Previously address with own SLA address   Data has been received; ACK has been returned*/
    {
        raraddress = (unsigned char) I2C_GET_DATA(I2C0);
        I2C_SET_CONTROL_REG(I2C0, I2C_I2CON_SI_AA);
    }
    else if(u32Status == 0xA8)  /* Own SLA+R has been receive; ACK has been return */
    {	
   		 if(raraddress == I2CWRADDRESS){
			I2C_SET_DATA(I2C0, 0x00);
			g_u8DataLen = 1;
			I2C_SET_CONTROL_REG(I2C0, I2C_I2CON_SI_AA);	
		if( !getmessage(&mstTemp)){
			mstTemp.type = MSG_NULL;
			mstTemp.TOUCH_Points = 0;
			mstTemp.TOUCH_XH = 0xFF;
			mstTemp.TOUCH_XL = 0xFF;
			mstTemp.TOUCH_YH = 0xFF;
			mstTemp.TOUCH_YL = 0xFF;
		
		 	I2C_SET_CONTROL_REG(I2C0, I2C_I2CON_SI_AA);
			return ;
		}
		CopyCtpDataBuffer();

		}else if(raraddress == 0xa3){
			I2C_SET_CONTROL_REG(I2C0, I2C_I2CON_SI_AA);
		}else if(raraddress == 0xa6){
			I2C_SET_CONTROL_REG(I2C0, I2C_I2CON_SI_AA);
		}	
    }
    else if(u32Status == 0xC0)  /* Data byte or last data in I2CDAT has been transmitted   Not ACK has been received */
    {
        I2C_SET_CONTROL_REG(I2C0, I2C_I2CON_SI_AA);
    }
    else if(u32Status == 0x88)  /* Previously addressed with own SLA address; NOT ACK hasbeen returned */
    {
        I2C_SET_CONTROL_REG(I2C0, I2C_I2CON_SI_AA);
    }
    else if(u32Status == 0xA0) /* A STOP or repeated START has been received while still addressed as Slave/Receiver*/
    {
		I2C_SET_CONTROL_REG(I2C0, I2C_I2CON_SI_AA);
    }else if(u32Status == 0xb8)	{
		if(raraddress == I2CWRADDRESS){
			i = g_u8DataLen;
			if(i < sizeof(CtpBuff)){
				I2C_SET_DATA(I2C0, CtpBuff[i]);
				g_u8DataLen++;
			}
			I2C_SET_CONTROL_REG(I2C0, I2C_I2CON_SI_AA);
		}else if(raraddress == 0xa3){
			I2C_SET_CONTROL_REG(I2C0, I2C_I2CON_SI_AA);
		}else if(raraddress == 0xa6){
			I2C_SET_CONTROL_REG(I2C0, I2C_I2CON_SI_AA);	
		}
	}
}

整机调试
a.触摸缓慢
整机调试发现压根不能触摸。检查发现中断脚是上升沿触发,程序里设置是电平触发,修改后配置该脚为pwm作为输出。有触摸时,pwm打开以60hz的速度,无触摸时是高电平。再次调试发现触摸的速度很慢,在老大帮助下,发现是系统时钟频率过低导致的,对rtp数据的读取我放置在main函数里,用的是内部系统时钟22.0482M 修改时钟为50M后,发现触摸效果有明显改善。
b.开机重启,从机总是挂掉。
客户主板上,I2C挂载的不单单只有一个设备,还有其他设备。通过串口打印发现0xa3,0xa6主机发给从机没有应答。导致从机在I2C中断挂掉。
c.再次整机测试发现电容屏触摸屏设置的分辨率不对。
LCD的分辨有率为1024*600 当触摸左上角时,用逻辑分析仪捕获波形如下,发现坐标值压根不是(0,1024)而是水平方向是(0,932).当时调试的想死的心都有!只有在电阻上修改其分辨率了.



解决完上述问题后,RTP转CTP的模块能很好的在客户的主机上运行.这个项目加深了,我对I2C从机通信的理解,对应答信号的处理,主从机一问一答.I2C从机一般是由硬件来完成,用模拟的很难完成.感谢老大在背后给我的支持.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值