您的位置:首页 > 产品设计 > UI/UE

我的RTOS 之六 -- Touch移植(s5pv210+threadx+ucgui+touch)

2016-02-25 16:31 423 查看
非常久没有关注RTOS了,所以也一直没有更新。近期闲了,把GPIO I2C调通了。简单移植了Touch。在S5PV210上使用。

调试I2C时。废了非常多周折,最后借助示波器才发现一个小小的错误。折腾了非常久非常久。

简要说下步骤:

1、首先I2C驱动,使用GPIO

I2C的方式

#include <stdio.h>
#include <touch.h>

#define DELAY  10

#define SDA 0
#define SCL 1

#define 	GPD1CON 	(*(volatile unsigned long *) 0xE02000C0)
#define 	GPD1DAT		(*(volatile unsigned long *) 0xE02000C4)
#define 	GPD1PUD		(*(volatile unsigned long *) 0xE02000C8)
#define 	GPD1DRV		(*(volatile unsigned long *) 0xE02000CC)

#define SDA2_SET_INPUT (GPD1CON &= ~(0xf<<16))
#define SDA2_SET_OUTPUT (GPD1CON = (GPD1CON & (~(0x0f<<16))) | (0x1<<16))
#define SCL2_SET_INPUT (GPD1CON &= ~(0xf<<20));
#define SCL2_SET_OUTPUT (GPD1CON = (GPD1CON & (~(0x0f<<20))) | (0x1<<20))

#define SDA2_SET_VALUE(x) (GPD1DAT = (GPD1DAT & ~(1<<4)) | (x << 4))
#define SCL2_SET_VALUE(x) (GPD1DAT = (GPD1DAT & ~(1<<5)) | (x << 5))

#define SDA2_GET_VALUE ((GPD1DAT & (1<<4)) > 0 ? 1:0)
#define SCL2_GET_VALUE ((GPD1DAT & (1<<5)) > 0 ?

1:0)

void gpio_i2c_init(void)
{
GPD1DRV = (GPD1DRV & ~(0x5 << 10) | (0x5 << 10));
GPD1PUD = (GPD1DRV & ~(0xf << 10) | 0xa << 10);
SCL2_SET_OUTPUT;
SDA2_SET_OUTPUT;
SDA2_SET_VALUE(1);
SCL2_SET_VALUE(1);

}
void i2c_start(void)
{
SCL2_SET_OUTPUT;
SDA2_SET_OUTPUT;
SDA2_SET_VALUE(1);
SCL2_SET_VALUE(1);

udelay(DELAY);

SDA2_SET_VALUE(0);
udelay(DELAY);

SCL2_SET_VALUE(0);
udelay(DELAY);
}

void i2c_stop(void)
{
SCL2_SET_OUTPUT;
SDA2_SET_OUTPUT;
SDA2_SET_VALUE(0);
SCL2_SET_VALUE(0);
udelay(DELAY);

SCL2_SET_VALUE(1);
udelay(DELAY);
SDA2_SET_VALUE(1);
udelay(DELAY);
}

void i2c_send_ack(unsigned char ack)
{
SCL2_SET_OUTPUT;
SDA2_SET_OUTPUT;

if(ack)
SDA2_SET_VALUE(1);
else
SDA2_SET_VALUE(0);
udelay(DELAY);

SCL2_SET_VALUE(1);
udelay(DELAY);

SCL2_SET_VALUE(0);
udelay(DELAY);
}

char i2c_receive_ack(void)
{
char rc = 0;

SCL2_SET_OUTPUT;
SDA2_SET_INPUT;

SCL2_SET_VALUE(1);
udelay(DELAY);

if(SDA2_GET_VALUE) {
rc = 1;
}
SCL2_SET_VALUE(0);
SDA2_SET_OUTPUT;
SDA2_SET_VALUE(1);
return rc;
}

unsigned char i2c_send_byte(unsigned char send_byte)
{
unsigned char rc = 0;
unsigned char out_mask = 0x80;
unsigned char value;
unsigned char count = 8;

SDA2_SET_OUTPUT;
SCL2_SET_OUTPUT;

while(count > 0) {
value = ((send_byte & out_mask) ?

1 : 0);
if (value == 1) {
SDA2_SET_VALUE(1);
}
else {
SDA2_SET_VALUE(0);
}
udelay(DELAY);

SCL2_SET_VALUE(1);
udelay(DELAY);

SCL2_SET_VALUE(0);
udelay(DELAY);

out_mask >>= 1;
count--;
}

SDA2_SET_VALUE(1);
rc = i2c_receive_ack();
return rc;
}

void i2c_read_byte(unsigned char *buffer, unsigned char ack)
{
unsigned char count = 0x08;
unsigned char data = 0x00;
unsigned char temp = 0;

SDA2_SET_INPUT;
SCL2_SET_OUTPUT;

while(count > 0) {
SCL2_SET_VALUE(1);
udelay(DELAY);
temp = SDA2_GET_VALUE;
data <<= 1;
if (temp)
data |= 0x01;
SCL2_SET_VALUE(0);
udelay(DELAY);
count--;
}
i2c_send_ack(ack);//0 = ACK    1 = NACK
*buffer = data;
}

int gpio_i2c_master_send(unsigned int SlaveAddr, unsigned char *Data, unsigned int length)
{
unsigned int i, j;
int rc;

SlaveAddr = (SlaveAddr << 1) & ~0x01;

i2c_start();
rc = i2c_send_byte(SlaveAddr);
if(rc){
printf("i2c_send_byte no ack 1\n");
return -1;
}

for(j = 0; j < length; j++)	{
rc = i2c_send_byte(Data[j]);//发送data
if(rc){
printf("i2c_send_byte no ack 2\n");
return -1;
}
}
i2c_stop();//停止信号
udelay(10);
return 0;
}

int gpio_i2c_master_recv(unsigned int SlaveAddr, unsigned char *Data, unsigned int length)
{
unsigned int i, j;
unsigned int data;
int rc;

SlaveAddr = (SlaveAddr << 1) | 0x01;

i2c_start();

rc = i2c_send_byte(SlaveAddr);
if(rc) {
printf("i2c_read_byte no ack 1\n");
return -1;
}

for(j=0; j<length; j++){
i2c_read_byte(Data++, !(length - j -1));//读取数据;
}

i2c_stop();//停止信号
return length;
}

int i2c_read_data(unsigned int SlaveAddr,
char *reg, unsigned char *values, int length)
{
int ret;
int count = 0;
retry:
/* select register*/
ret = gpio_i2c_master_send(SlaveAddr, reg , 1);
if (ret < 0) {
udelay(DELAY * 2);

if (++count < 2)
goto retry;

return ret;
}
/* for setup tx transaction. */
udelay(DELAY);
ret = gpio_i2c_master_recv(SlaveAddr,  values , length);
if (ret < 0)
return ret;

udelay(DELAY);
return length;
}


2、Touch驱动

Touch IC为 FT5406, slave地址为0x70.

借助博友的一页芯片资料,写了最简单的单点读取:



多点也非常easy。能够參考android 多点触控协议上报点

#include <touch.h>
#include <exception.h>

struct touch_data touch_data;

int touch_irq()
{
int i;
int num = 0;
int x, y;
char reg[1] = {0};
unsigned char buf[10];

i2c_read_data(0x38, reg, buf, 7);

if((num = (buf[2] & 0x0f)) == 0)
{
if(touch_data.isPress)
{
touch_data.isPress = 0;
touch_data.x = -1;
touch_data.y = -1;
touch_event(touch_data.x, touch_data.y);
}
//printf("release\r\n");
return 0;
}
x = (buf[3]&0x0f) << 8 | buf[4];
y = (buf[5]&0x0f) << 8 | buf[6];
//printf("num:%d, x:%d, y:%d\r\n", num, x, y);
touch_data.x		= x;
touch_data.y		= y;
if(touch_data.isPress  == 0)
touch_data.isPress  = 1;
touch_event(touch_data.x, touch_data.y);
return 0;
}

void touch_init(void)
{
unsigned char uc_reg_value;
unsigned char uc_reg_addr;
unsigned char buf[1];
unsigned char dst[1];

touch_int_setup();

i2c_read_data(0x38, buf, dst, 1);
printf("touch fw:0x%x\r\n", dst[0]);
buf[0] = 0x88;
i2c_read_data(0x38, buf, dst, 1);
printf("report rate:0x%x\r\n", dst[0] * 10);
buf[0] = 0x80;
i2c_read_data(0x38, buf, dst, 1);
printf("touch threshold:0x%x\r\n", dst[0] * 4);

intc_enable(NUM_EINT14);
}


在touch_init 初始化中可以取到touch固件信息。就说明

i2c通信正常了。

3、看下效果^^







最后两张的动画比較卡。

4:、存在问题及缺点

因为是电容屏,中断出发,触摸的时候。会不停的上报中断,会导致其它线程block。发生卡顿的情况,尤其画面比較复杂的时候。后期能够採取查询的方法,放在单独的线程其中或者减少touch的报点率;

另外就是lcd仅仅有一层framebuffer,多层显示倒是ucgui的效率低下,后期优化能够同一时候打开至少两个framebuffer。

5、源代码
http://download.csdn.net/detail/liujia2100/8859911
后期尝试移植lwip,搭配arduino。物联网^^.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: