标题:
51单片机TFT9325液晶显示SD卡中的图片源程序
[打印本页]
作者:
hongniu
时间:
2015-6-23 16:54
标题:
51单片机TFT9325液晶显示SD卡中的图片源程序
经过近两个星期的奋战!今天我敢说我成功了,因为我在液晶屏上成功的显示了彩色图片!真是不容易啊。回顾这些日子,我没睡一个安稳觉,实验达一百多次,与现在兴奋相比,都是浮云了!再一次次失败中我也在总结经验,一直在问位什么?下面:
我开始做TFT液晶实在做完SD卡之后,虽然我没有弄文件系统,可是SD作为一个超大容量的RAM还是可以的,这一点我在技术上是能实现的!那么怎样才能把SD卡上的数据准确无误的显示在TFT液晶上呢?没有任何头绪,虽然做过12864但是你看看TFT的数据手册,你就明白了什么叫做不是一个级别!做之前,我在网上疯狂的搜着关于TFT液晶的资料,最后只找到了一份英文的TFT手册,我不懂英文!但还没有中文的!在网上的大都是只言片语的简介!于是开始用金山词霸翻译!大约有一个星期左右,关于TFT大概的知识懂了一点g点,当然现在的我也只是知道一点!因为他的功能实在是太强了!知道了控制器是9325的!知道了他的数据操作时分很多种的(16,8,SPI,...)。知道了他内部的寄存器很多!但是那是的我认为,不就是一块液晶吗!能难倒哪去?我现在才知道我当时错了!大概有个了解后,我开始搭接实验板!单片机驱动液晶调试正式开始,按照8位数据传输模式连接接口!数据按照一次传送8位,传两次(因为不论是数据还是指令都是16位的数据结构)高字节在前的顺序!开始我只想运行刷屏的程序,可是迟迟不能运行,后来发现是数据跟指令没搞明白!RS=1表示写的是数据,RS=0表示写的是寄存器的地址。然后初始化,这里的初始话我是调用别人的做好的!后来程序开始在液晶上运行了!当然是刷屏程序!接下来市让屏幕上显示彩条!就想电视里的那种一条红一条绿,一样,这是为了测试液晶的GRAM你能可靠地控制!我实现这一步也要感谢网络!正式网络我才一点点的积累经验,实现了自如的控制GRAM的显示!(我想在液晶的任意坐标系内显示任意的颜色或色条!)到这里我不禁想起了12864,因为当你控制了这一点时,你基本上离显示图片不远了!因为你控制了这一点很容易的能实现行和场的扫描!有了行场扫描你就可以显示一幅画了!当然这是理论上!这是前天晚上的事!昨天一天我都在调一个东西!那就是关键的也是最后一步!SD卡和TFT液晶联合试验!单片机要完成从SD卡中读取数据!然后送入到TFT液晶的控制器里,并且提供行扫描光和场扫描!SD卡的程序我以前调好的,直接拿来用!液晶的也拿来用,组合起来用XDATE中的RAM作为联系两个期间的数据缓冲单元!当我写入内存卡一幅图片!想着显示出的画面有多好时!打开电源!扫描开始!然而我失望了!出来的竟然是无数的红绿白黑的点!俗称花屏!为什么会这样那?我开始考虑!是不是取模有问题!然后改变image2lcd的取模方式!复制粘贴!WINHEX中查看数据!这样反复,还是不能显示!相反出现了一个有趣的现象!出现了很多网文!这是行场不同步,像素没有正确的写入自己的位置造成的!这个问题从昨天下午直到半夜!还是没解决!心情很郁闷!但是我总感觉我里成功很近了,一步之遥!昨晚上做到很晚,梦里还在想!结果谁大了,7:30才醒!醒了我就在想这个网文!我忽略了一个细节!当时我扫描方式时!我曾采用过行逆程显示!结果表明有一部分图像显现出来!不过在边缘!,里面都是网文!和乱踢八糟的彩色点!只有在边缘是细腻的图像,只有一小块,而且每隔多少行一块!突然一个想法在脑子里闪现!是不是我重复数据扫描了!有一想我主程序里是512个扫描周期,分了两个字节!总共是1024!而我读一扇区只有512,所以肯定有一半的数据是重复的!,想到这里我想赶紧验证下!电话响了!安保近的,说工地有事让我去趟!我也没顾得实验!直接去工地,办完事回来吧程序改了,512改成了256,这样正是512字节,然后又实验!这次能显示图像的轮廓了,但是很模糊!我有WINHEX开查看!是字节未按高字节在前的顺序,排列,调整后,一点也不大差的显示在屏幕上了!IMAGE取模吧JPG转换成BMP的彩色图片宽度240,高度320,16位色,高位在前,水平扫描!生成BIN文件存入存储卡中OVER!当然在中间还要用串口查看数据是否正确!
}
程序:
#include <reg52.h>
#define uchar unsigned char
#define uint unsigned int
#define DATE P0
//bit flage;
//SD卡的
sbit p1_7=P1^7;
sbit CS=P2^0; //片选信号(低电平有效)
sbit DATEIN =P2^1;//主-从数据输入
sbit SCLK=P2^2;//时钟信号
sbit DATEOUT=P2^3;//从-主数据输出
//液晶的
sbit RS=P3^7;
sbit RW=P3^6;
sbit RES=P3^5;
sbit CStft=P3^4;
uint btime;
uchar c;
unsigned char bdata dat;
sbit dat_0=dat^0;
sbit dat_1=dat^1;
sbit dat_2=dat^2;
sbit dat_3=dat^3;
sbit dat_4=dat^4;
sbit dat_5=dat^5;
sbit dat_6=dat^6;
sbit dat_7=dat^7;
bit is_init;//决定是否延时;
uchar lpp;
unsigned char fhz;//返回值
uchar fhz_buff; //读返回值中间量
unsigned char xdata tab[512];
void delay(uint time)
{ while(time)
time--;
}
//**********************************************
/*读sd卡子程序,无返回值,有参函数,参数为要写入DATEIN数据线的字节*/
void write(unsigned char wr_)// 写入一个字节SD卡
{
dat=wr_;
DATEIN=dat_7;
SCLK=0;
if(is_init)delay(200);
if(!is_init)delay(2);
SCLK=1;
if(is_init) delay(200);
if(!is_init)delay(2);
DATEIN=dat_6;
SCLK=0;
if(!is_init)delay(2);
if(is_init)delay(200);
SCLK=1;
if(is_init) delay(200);
if(!is_init)delay(2);
DATEIN=dat_5;
SCLK=0;
if(is_init)delay(200);
if(!is_init)delay(2);
SCLK=1;
if(is_init) delay(200);
if(!is_init)delay(2);
DATEIN=dat_4;
SCLK=0;
if(is_init)delay(200);
if(!is_init)delay(2);
SCLK=1;
if(is_init) delay(200);
if(!is_init)delay(2);
DATEIN=dat_3;
SCLK=0;
if(is_init)delay(200);
if(!is_init)delay(2);
SCLK=1;
if(is_init) delay(200);
if(!is_init)delay(2);
DATEIN=dat_2;
SCLK=0;
if(is_init)delay(200);
if(!is_init)delay(2);
SCLK=1;
if(is_init) delay(200);
if(!is_init)delay(2);
DATEIN=dat_1;
SCLK=0;
if(is_init)delay(200);
if(!is_init)delay(2);
SCLK=1;
if(is_init) delay(200);
if(!is_init)delay(2);
DATEIN=dat_0;
SCLK=0;
if(is_init)delay(200);
if(!is_init)delay(2);
SCLK=1;
if(is_init) delay(200);
if(!is_init)delay(2);
}
unsigned char read()// 读取一个字节SD卡
{
DATEOUT=1;
SCLK=1;
if(is_init)delay(200);
if(!is_init)delay(2);
SCLK=0;
if(is_init)delay(200);
if(!is_init)delay(2);
dat_7=DATEOUT;
SCLK=1;
if(is_init)delay(200);
if(!is_init)delay(2);
SCLK=0;
if(is_init)delay(200);
if(!is_init)delay(2);
dat_6=DATEOUT;
SCLK=1;
if(is_init)delay(200);
if(!is_init)delay(2);
SCLK=0;
if(is_init)delay(200);
if(!is_init)delay(2);
dat_5=DATEOUT;
SCLK=1;
if(is_init)delay(200);
if(!is_init)delay(2);
SCLK=0;
if(is_init)delay(200);
if(!is_init)delay(2);
dat_4=DATEOUT;
SCLK=1;
if(is_init)delay(200);
if(!is_init)delay(2);
SCLK=0;
if(is_init)delay(200);
if(!is_init)delay(2);
dat_3=DATEOUT;
SCLK=1;
if(is_init)delay(200);
if(!is_init)delay(2);
SCLK=0;
if(is_init)delay(200);
if(!is_init)delay(2);
dat_2=DATEOUT;
SCLK=1;
if(is_init)delay(200);
if(!is_init)delay(2);
SCLK=0;
if(is_init)delay(200);
if(!is_init)delay(2);
dat_1=DATEOUT;
SCLK=1;
if(is_init)delay(200);
if(!is_init)delay(2);
SCLK=0;
if(is_init)delay(200);
if(!is_init)delay(2);
dat_0=DATEOUT;
return (dat);
}
void restsd()//复位SD卡
{ uchar i;
uchar pcmd[6]={0x40,0x00,0x00,0x00,0x00,0x95};
is_init=1;
CS=1;
for(i=0;i<15;i++)
{
//120时钟
write(0xff);
}
CS=1;
write(0xff);//据说是提高兼容性
CS=0;//片选开
write( pcmd[0]);
write( pcmd[1]);
write( pcmd[2]);
write( pcmd[3]);
write( pcmd[4]);
write( pcmd[5]);
fhz=read();
for(;;)
{
fhz=read();
if(fhz==0x01)break;
}
CS=1;
write(0xff);
}
void initsd()//初始化
{
//
uchar pcmd[6]={0x41,0x00,0x00,0x00,0x00,0xff};//
//
CS=1;
write(0xff);//据说是提高兼容性
CS=0;//片选开
write( pcmd[0]);
write( pcmd[1]);
write( pcmd[2]);
write( pcmd[3]);
write( pcmd[4]);
write( pcmd[5]);
fhz=read();
for(;;)
{
fhz=read();
if(fhz==0x00)break;
}
CS=1;
write(0xff);
}
void readsd(unsigned long addstart)//读SD卡物理扇区
{ unsigned long sdbuff1,sdbuff2,sdbuff3,sdbuff4;
uint j,n;
uchar zh1,zh2,zh3,zh4;
sdbuff1=addstart;
sdbuff2=addstart;
sdbuff3=addstart;
sdbuff4=addstart;
zh1=(sdbuff1>>24)&0x000000ff;
zh2=(sdbuff2>>16)&0x000000ff;
zh3=(sdbuff3>>8)&0x000000ff;
zh4=sdbuff4&0x000000ff;
// uchar pcmd[6]={0x51,zh1,zh2,zh3,zh4,0xff};//原来这里是高地址字节在前地地址在后啊201012月14日逻辑扇区在253*512=0X0001fa00
CS=1;
write(0xff);//据说是提高兼容性
CS=0;//片选开
write( 0x51);
write( zh1);
write( zh2);
write( zh3);
write( zh4);
write( 0xff);
DATEOUT=1;
for(;;)
{
fhz=read();
if(fhz==0x00)break;
}
DATEOUT=1;
for(;;)
{
fhz=read();
if(fhz==0xfe)break;
}
DATEOUT=1;
n=0;
for(j=512;j;j--)
{
tab[n]=read();
n++;
}
fhz=read();
fhz=read();
CS=1;
write(0xff);
}
/*
//********************************一下是液晶的
void delay1ms(uint x) //延时程序
{ unsigned char a,b,c;
uint z;
for(z=x;z;z--)
{
for(c=8;c>0;c--)
for(b=197;b>0;b--)
for(a=2;a>0;a--);
}
}
void write_date(uchar hight,uchar low) //定义搞八位字节和低八位字节写然后写入数据
{
CStft=0;
RS=1;
DATE=hight;
RW=0;
RW=1;
DATE=low;
RW=0;
RW=1;
CStft=1;
}
void write_cmd(uchar hight,uchar low )//定义搞八位字节和低八位字节写然后写入指令
{
CStft=0;
RS=0;
DATE=hight;
RW=0;
RW=1;
DATE=low;
RW=0;
RW=1;
CStft=1;
}
void wr_cmd_date(uint cmmd,uint datesh) //写入指令和相应的数据;
{
uchar g,d,g1,d1; /* 2010年12月21日与天津第四项目部终于做完了9325的TFT262万色彩色液晶,感觉比他妈的12864爽多了,
毕竟一个是黑白的一个是彩色的,呵呵,加油啊,下一步是组合SD卡和TFT液晶,让液晶显示彩色图片,加油吧!*/
d=datesh;
d=(d&0x00ff);
g=(datesh>>8)&0x0ff;
d1=cmmd;
d1=(d1&0x00ff);
g1=(cmmd>>8)&0x0ff;
write_cmd(g1,d1 );
write_date(g,d ) ;
}
void initTFT()//注意:这里是用的设置库,网络上多的很,感谢网络啊。
{
wr_cmd_date(0x0001,0x0100); //s1-s720
wr_cmd_date(0x0002,0x0700);
wr_cmd_date(0x0003,0x1030);
wr_cmd_date(0x0004,0x0000);
wr_cmd_date(0x0008,0x0207);
wr_cmd_date(0x0009,0x0000);
wr_cmd_date(0x000A,0x0000);
wr_cmd_date(0x000C,0x0000);
wr_cmd_date(0x000D,0x0000);
wr_cmd_date(0x000F,0x0000);
//power on sequence VGHVGL
wr_cmd_date(0x0010,0x0000);
wr_cmd_date(0x0011,0x0007);
wr_cmd_date(0x0012,0x0000);
wr_cmd_date(0x0013,0x0000);
//vgh
wr_cmd_date(0x0010,0x1290);
wr_cmd_date(0x0011,0x0227);
delay1ms(100);
//vregiout
wr_cmd_date(0x0012,0x001d); //0x001b
delay1ms(100);
//vom amplitude
wr_cmd_date(0x0013,0x1500);
delay1ms(100);
//vom H
wr_cmd_date(0x0029,0x0018);
wr_cmd_date(0x002B,0x000D);
//gamma
wr_cmd_date(0x0030,0x0004);
wr_cmd_date(0x0031,0x0307);
wr_cmd_date(0x0032,0x0002);// 0006
wr_cmd_date(0x0035,0x0206);
wr_cmd_date(0x0036,0x0408);
wr_cmd_date(0x0037,0x0507);
wr_cmd_date(0x0038,0x0204);//0200
wr_cmd_date(0x0039,0x0707);
wr_cmd_date(0x003C,0x0405);// 0504
wr_cmd_date(0x003D,0x0F02);
//ram
wr_cmd_date(0x0050,0x0000);
wr_cmd_date(0x0051,0x00EF);
wr_cmd_date(0x0052,0x0000);
wr_cmd_date(0x0053,0x013F);
wr_cmd_date(0x0060,0xA700);
wr_cmd_date(0x0061,0x0001);
wr_cmd_date(0x006A,0x0000);
//
wr_cmd_date(0x0080,0x0000);
wr_cmd_date(0x0081,0x0000);
wr_cmd_date(0x0082,0x0000);
wr_cmd_date(0x0083,0x0000);
wr_cmd_date(0x0084,0x0000);
wr_cmd_date(0x0085,0x0000);
//
wr_cmd_date(0x0090,0x0010);
wr_cmd_date(0x0093,0x0003);
wr_cmd_date(0x0095,0x0110);
wr_cmd_date(0x0097,0x0000);
wr_cmd_date(0x0098,0x0000);
wr_cmd_date(0x0007,0x0133);
}
//****************以上是液晶的
void lcm_coordinate(unsigned int x1,unsigned int y1 )//扫描地
{
wr_cmd_date(0x0050,x1);
wr_cmd_date(0x0051,x1);
wr_cmd_date(0x0052,y1);
wr_cmd_date(0x0053,y1);
wr_cmd_date(0x0020,x1);
wr_cmd_date(0x0021,y1);
}
void main()
{ unsigned long numb;
unsigned int x,y; //扫描地址;
uint a;
uint f,buff_sd_tft;
uint m1,m2;
delay1ms(30);
CS=1;
RES=0;
delay1ms(150);
RES=1;
delay1ms(50);
//******
initTFT();
//InitUART(); //串口初始化
is_init=1;
restsd();
initsd();
is_init=0;//提高始终频率
//p1_7=0;
//********
while(1)
{
/* x=0;y=0;
for(;;)
{
lcm_coordinate(x,y );
wr_cmd_date(0x0022,0x0000);
x++;
delay20us();
if(x==240){x=0;y++;}
if(y==80)break; //检测是否写到屏的边缘 240x320
}
for(;;)
{
lcm_coordinate(x,y );
wr_cmd_date(0x0022,0xf800);
x++;
delay20us(); //必须加延时,实时胜于雄辩,如果不加延时的话,极易出现花屏,及扫描过高引起的数据无法写入,他妈的耽误了我一下午时间啊!2010年12月22日
if(x==240){x=0;y++;}
if(y==160)break; //检测是否写到屏的边缘 240x320
}
for(;;)
{
lcm_coordinate(x,y );
wr_cmd_date(0x0022,0x0000);
x++;
delay20us(); //必须加延时,实时胜于雄辩,如果不加延时的话,极易出现花屏,及扫描过高引起的数据无法写入,他妈的耽误了我一下午时间啊!2010年12月22日
if(x==240){x=0;y++;}
if(y==240)break; //检测是否写到屏的边缘 240x320
}
for(;;)
{
lcm_coordinate(x,y );
wr_cmd_date(0x0022,0x001f);
x++;
delay20us(); //必须加延时,实时胜于雄辩,如果不加延时的话,极易出现花屏,及扫描过高引起的数据无法写入,他妈的耽误了我一下午时间啊!2010年12月22日
if(x==240){x=0;y++;}
if(y==320)break; //检测是否写到屏的边缘 240x320
}
}*/
// while(1);
//p1_7=1;
// btime=65536;
// SendOneByte(0x88);
x=0;y=0;
numb=4327936;
do
{
readsd(numb);//读物理扇区
//SendOneByte(0x88);
f=0;
for(a=256;a;a--)
{
m1=tab[f];
// SendOneByte(m1);
m1=(m1<<8)&0xff00;
f++;
m2=tab[f];
// SendOneByte(m2);
f++;
buff_sd_tft=m1+m2;
lcm_coordinate(x,y );
wr_cmd_date(0x0022,buff_sd_tft);
x++;
delay1ms(1); //必须加延时,实时胜于雄辩,如果不加延时的话,极易出现花屏,及扫描过高引起的数据无法写入,他妈的耽误了我一下午时间啊!2010年12月22日
if(x==240){x=0;y++;}
if(y==320)y=0; //检测是否写到屏的边缘 240x320
}
//SendOneByte(0xcc);
numb=(numb+512);
}
while(0x0044620!=numb);
// EA=0;
// ES = 0;
// TR1 = 0;
while(1);
}
复制代码
欢迎光临 (http://www.51hei.com/bbs/)
Powered by Discuz! X3.1