TA的每日心情 | 开心 2019-6-25 09:54 |
---|
签到天数: 216 天 连续签到: 1 天 [LV.7]常住居民III
|
楼主 |
发表于 2015-1-29 15:19:39
|
显示全部楼层
此楼是触屏测试程序
本帖最后由 PokeBox 于 2015-1-29 16:15 编辑
嗯,程序部分的话其实要写还是很简单的嘛……因为我偷懒了,直接把2个程序合成1个,首先你得准备2个原料~这一节我就教大家怎么把2个程序合成1个吧~以后要写程序就可以照搬别人的然后稍加修改一下自己就可以剩下很多时间了。
首先需要2个东西,一个是12864的基本程序,一个是彩屏的触屏测试程序,我直接用了最简单的,显示字符,因为我的12864是带字库的,所以就可以做基本的测试,触屏后显示芯片输出的AD值,只要有AD值就说明你的硬件制作成功了。
那么开始吧。
首先贴出12864的基本程序,主函数因为我们要自己写,原来的不需要,所以我就直接删掉了~ok,然后准备一个触屏的程序,别人都已经写为一个文件了很方便,直接拿过来修改一下即可。下面贴出原来的代码- #include <reg51.h>
- #include <intrins.h>
- #include <sys\sys.h>
- #include <touch\touch.h>
- #include <lcd\lcd.h>
- //***因触摸屏批次不同等原因,默认的校准参数值可能会引起触摸识别不准,建议校准后再使用,不建议使用固定的默认校准参数
- //uint vx=15242,vy=11131; //比例因子,此值除以1000之后表示多少个AD值代表一个像素点
- //uint chx=3898,chy=145; //默认像素点坐标为0时的AD起始值
- uint vx=15332,vy=11249;
- uint chx=137,chy=3957;
- //***因触摸屏批次不同等原因,默认的校准参数值可能会引起触摸识别不准,建议校准后再使用,不建议使用固定的默认校准参数
- struct tp_pix_ tp_pixad,tp_pixlcd; //当前触控坐标的AD值,前触控坐标的像素值
- uchar tpstate(void)
- {
- return IRQ;
- }
- //**********************************************************
- void spistar(void) //SPI开始
- {
- CS=1;
- DCLK=1;
- DIN=1;
- DCLK=1;
- }
- //**********************************************************
- void WriteCharTo7843(unsigned char num) //SPI写数据
- {
- unsigned char count=0;
- DCLK=0;
- for(count=0;count<8;count++)
- {
- num<<=1;
- DIN=CY;
- DCLK=0; _nop_();_nop_();_nop_(); //上升沿有效
- DCLK=1; _nop_();_nop_();_nop_();
- }
- }
- //**********************************************************
- uint ReadFromCharFrom7843() //SPI 读数据
- {
- uchar count=0;
- uint Num=0;
- for(count=0;count<12;count++)
- {
- Num<<=1;
- DCLK=1; _nop_();_nop_();_nop_(); //下降沿有效
- DCLK=0; _nop_();_nop_();_nop_();
- if(DOUT)
- {
- Num|=1;
- }
- }
- return(Num);
- }
- //从7846/7843/XPT2046/UH7843/UH7846读取adc值 0x90=y 0xd0-x
- uint ADS_Read_AD(unsigned char CMD)
- {
- uint l;
- CS=0;
- WriteCharTo7843(CMD); //送控制字即用差分方式读X坐标 详细请见有关资料
- DCLK=1; _nop_();_nop_();_nop_();_nop_();
- DCLK=0; _nop_();_nop_();_nop_();_nop_();
- l=ReadFromCharFrom7843();
- CS=1;
- return l;
- }
- //读取一个坐标值
- //连续读取READ_TIMES次数据,对这些数据升序排列,
- //然后去掉最低和最高LOST_VAL个数,取平均值
- #define READ_TIMES 15 //读取次数
- #define LOST_VAL 5 //丢弃值
- uint ADS_Read_XY(uchar xy)
- {
- uint i, j;
- uint buf[READ_TIMES];
- uint sum=0;
- uint temp;
- for(i=0;i<READ_TIMES;i++)
- {
- buf[i]=ADS_Read_AD(xy);
- }
- for(i=0;i<READ_TIMES-1; i++)//排序
- {
- for(j=i+1;j<READ_TIMES;j++)
- {
- if(buf[i]>buf[j])//升序排列
- {
- temp=buf[i];
- buf[i]=buf[j];
- buf[j]=temp;
- }
- }
- }
- sum=0;
- for(i=LOST_VAL;i<READ_TIMES-LOST_VAL;i++) sum+=buf[i];
- temp=sum/(READ_TIMES-2*LOST_VAL);
- return temp;
- }
- //带滤波的坐标读取
- //最小值不能少于100.
- uchar Read_ADS(uint *x,uint *y)
- {
- uint xtemp,ytemp;
- xtemp=ADS_Read_XY(CMD_RDX);
- ytemp=ADS_Read_XY(CMD_RDY);
- if(xtemp<100||ytemp<100) return 0;//读数失败
- *x=xtemp;
- *y=ytemp;
- return 1;//读数成功
- }
- //2次读取ADS7846,连续读取2次有效的AD值,且这两次的偏差不能超过
- //50,满足条件,则认为读数正确,否则读数错误.
- //该函数能大大提高准确度
- #define ERR_RANGE 20 //误差范围
- uchar Read_ADS2(uint *x,uint *y)
- {
- uint x1,y1;
- uint x2,y2;
- uchar flag;
- flag=Read_ADS(&x1,&y1);
- if(flag==0) return(0);
- flag=Read_ADS(&x2,&y2);
- if(flag==0) return(0);
- if(((x2<=x1&&x1<x2+ERR_RANGE)||(x1<=x2&&x2<x1+ERR_RANGE)) //前后两次采样在+-ERR_RANGE内
- &&((y2<=y1&&y1<y2+ERR_RANGE)||(y1<=y2&&y2<y1+ERR_RANGE)))
- {
- *x=(x1+x2)>>1;
- *y=(y1+y2)>>1;
- return 1;
- }else return 0;
- }
- //精确读取一次坐标,校准的时候用的
- uchar Read_TP_Once(void)
- {
- uchar re=0;
- uint x1,y1;
- while(re==0)
- {
- while(!Read_ADS2(&tp_pixad.x,&tp_pixad.y));
- delayms(10);
- while(!Read_ADS2(&x1,&y1));
- if(tp_pixad.x==x1&&tp_pixad.y==y1)
- {
- re=1;
- }
- }
- return re;
- }
- //////////////////////////////////////////////////
- //与LCD部分有关的函数
- //画一个触摸点
- //用来校准用的
- void Drow_Touch_Point(uint x,uint y)
- {
- LCD_DrawLine(x-12,y,x+13,y);//横线
- LCD_DrawLine(x,y-12,x,y+13);//竖线
- LCD_DrawPoint(x+1,y+1);
- LCD_DrawPoint(x-1,y+1);
- LCD_DrawPoint(x+1,y-1);
- LCD_DrawPoint(x-1,y-1);
- // Draw_Circle(x,y,6);//画中心圈
- }
- //转换结果
- //根据触摸屏的校准参数来决定转换后的结果,保存在X0,Y0中
- uchar Convert_Pos(void)
- {
- uchar l=0;
- if(Read_ADS2(&tp_pixad.x,&tp_pixad.y))
- {
- l=1;
- tp_pixlcd.x=tp_pixad.x>chx?((ulong)tp_pixad.x-(ulong)chx)*1000/vx:((ulong)chx-(ulong)tp_pixad.x)*1000/vx;
- tp_pixlcd.y=tp_pixad.y>chy?((ulong)tp_pixad.y-(ulong)chy)*1000/vy:((ulong)chy-(ulong)tp_pixad.y)*1000/vy;
- }
- return l;
- }
- //触摸屏校准代码
- //得到四个校准参数
- void Touch_Adjust(void)
- {
- float vx1,vx2,vy1,vy2; //比例因子,此值除以1000之后表示多少个AD值代表一个像素点
- uint chx1,chx2,chy1,chy2;//默认像素点坐标为0时的AD起始值
- ……用不上,省略,不然篇幅太长……
- }
复制代码 嗯……这是触屏的程序,然后,我们把两串代码合成一个文件,因为触屏是基于显示功能之上所以把触屏的程序复制粘贴到12864的程序文件里,然后整理一下,把程序定义的部分全部放在最全面,函数放在12864的函数下面,然后稍加整理,这时你就完成了1/3的工程了,然后把触屏的调用了屏幕显示的部分全部用12864的显示函数替换掉,没法使用的函数就直接删掉它不要,比如下面的触屏校准函数这里我们用不上就直接删,最后剩下的就是我们要的函数体程序。然后重新编写主函数,已经知道Convert_Pos()函数是触屏的值转换函数,所以我们只要调用这个就可以,其他函数都可以不用理会。但是别乱删函数体,因为你得弄清楚你需要用的函数的依赖关系,依赖用到的函数你不能删,不然会报错的。
最后,主函数写成这样:- #define Xa tp_pixad.x
- #define Ya tp_pixad.y
- #define Xc tp_pixlcd.x
- #define Yc tp_pixlcd.y
- main()
- {
- spistar();
- Init_ST7920(); //初始化
- while(1)
- {
- if(Penirq==0)//按键按下了
- {
- if(Convert_Pos())//得到单次按键值
- {
- LCD_PutString(0,1,"Xa:");LCD_ShowNum(Xa);
- LCD_PutString(0,2,"Ya:");LCD_ShowNum(Ya);
- LCD_PutString(0,3,"X:");LCD_ShowNum(Xc);
- LCD_PutString(0,4,"Y:");LCD_ShowNum(Yc);
- }
- }
- }
- }
复制代码 OK,保存拿去编译,
有9个警告,都是一些函数没有用到的警告,说明没用到的函数我们没删掉也没被调用,无关紧要,无视,只要没错误就OK了,毕竟只是测试触屏能不能用。但是真正想要用来做东西的话就最好做到0错误0警告!
写入单片机运行,效果如图,点击触屏任意位置都有不同的数值输出就说明你的触屏制作OK了。
下面我直接放源码吧,方便大家测试,至于引脚的定义大家自己修改好了。使用的单片机是STC12C5A60S2的。 |
|