切换到宽版
  • 35113阅读
  • 85回复

[C51]基于STC12LE*单片机的TFT真彩屏日历Flash字库DS3231时基【不断更新添加所有C程序】 [复制链接]

上一主题 下一主题
离线慕名而来
 

发帖
1706
M币
6089
专家
11
粉丝
68
只看楼主 倒序阅读 我要置顶 楼主  发表于: 2016-03-29
— 本帖被 發騷友 设置为精华,作者+3000M币+5专家(2016-04-12) —
说来惭愧,玩了好久51单片机,只会做时钟、万年历啥的,也是无奈的事情,只是以玩单片机消磨时间,也没有啥工程可做,也就只能玩这些了,好在还有玩的兴趣在,且玩且娱乐着吧。这次用到了这些东西:1】.单片机=STC12LE5A60S2。2】.W25Q64flash芯片。3】.DS3231芯片。4】.TFT真彩屏4.6寸480*272分辨率。
一.原理图:


二.PCB图:

印刷版图是用Sprint-Layout 6.0 绿色汉化版完成的,第一次画这个东西,感觉这个小软件真的很好用,不用学,上手就能出图,只是线路布局要事先做一下腹稿,我是边画变想,最终修改了好几次才完成,尤其是镜像一定要想清楚,我最终也把小名和日期搞反了,好在不影响使用。
关于打印菲林片、晒板、蚀刻等详见: http://bbs.mydigit.cn/read.php?tid=1533510
三.完成后的线路板:




电路板制作很简单,没啥可说的,先焊装排针座,而后贴片、而后就完成了。
四.装配:




那个亚克力框是用5MM厚度的亚克力板材,在钻床上手工铣出来的,虽然很粗糙但可以凑合用,正面的打磨是用锉刀、各种砂纸,最后用牙膏抛光的。
五.成形:


成形后就是这个样子的,抽空再用铁皮做一个后壳、支架,就可以满足使用要求了,那是后话现在暂且不提。
六.关于液晶屏:
这块4.6寸的TFT真彩液晶屏(含触屏功能),内部集成了ILI9486控制器,转接板上集成了电阻式触屏控制器,是C51单片机较好驱动的彩屏,它还在是去年的这个时候淘的,用了48.00RMB,一直在吃灰,但是就是为现在这个计划买的,一是感觉不算贵,二者他的分辨率较低,不作为单纯的文字显示时,可以显示较大的字符。
接下来就是驱动代码了,说实话我玩单片机好些年了,因为只是玩玩也是因为年龄的问题,所以从一开始就没有按教材学过C语言编程,都是用到啥才翻书看看,所以只会几个常用的类似if、for等代码,至今我都不能用键盘完整输入#include、#define等定义符,都是贴上去的,但我却能移植修改现成的程序,而且可以把很烂、很复杂的C51程序简化到最简单(依我的水平的感觉),所以这单片机一路玩下来,倒也津津有味不亦乐乎。这次,因为整个系统由液晶屏+flash-W25Q64+DS3231这三个部分组成,我采用的是各个击破的方法,首先把液晶屏弄出显示,而后用W25Q64是制作字库,而后才是DS3231的使用,接下来就逐一大概的说说这三项工作的情形,至于万年历的代码,公历、农历啥的满网的资料就不探讨了,闲话少说,书归正传:
提示:新手有兴趣可以看一下,高手请直接绕行,没啥看点不用耽搁时间!!
ILI9486控制器TFT真彩屏的驱动:
这个工作在去年这块彩屏入手后就开始了,完成后一直仍在那里将近一年多了,当时调试的很多细节都忘记了,这里就只贴一下代码吧。
ILI9486控制器的初始化代码,如果有人恰巧用到了这个控制器,复制粘贴就能应用,为了方便大家就直接贴了:
void LCD_Init(void)
{
LCD_Reset(); //初始化之前复位
RD=1;     //RD引脚没有用到,拉高处理
//=========================液晶屏初始化=============================//
LCD_WR_REG(0XF9);
LCD_WR_DATA(0x00);
LCD_WR_DATA(0x08);
LCD_WR_REG(0xC0);
LCD_WR_DATA(0x19);//VREG1OUT POSITIVE
LCD_WR_DATA(0x1a);//VREG2OUT NEGATIVE
LCD_WR_REG(0xC1);
LCD_WR_DATA(0x45);//VGH,VGL    VGH>=14V.
LCD_WR_DATA(0x00);
LCD_WR_REG(0xC2);
LCD_WR_DATA(0x33);
LCD_WR_REG(0XC5);
LCD_WR_DATA(0x00);
LCD_WR_DATA(0x28);//VCM_REG[7:0]. <=0X80.
LCD_WR_REG(0xB1);
LCD_WR_DATA(0xB0);//0XB0 =70HZ, <=0XB0.
LCD_WR_DATA(0x11);
LCD_WR_REG(0xB4);
LCD_WR_DATA(0x02); //2 DOT FRAME MODE,F<=70HZ.
LCD_WR_REG(0xB6);
LCD_WR_DATA(0x00);
LCD_WR_DATA(0x42);//0 GS SS SM ISC[3:0];
LCD_WR_DATA(0x3B);
LCD_WR_REG(0xB7);
LCD_WR_DATA(0x07);
LCD_WR_REG(0xE0);
LCD_WR_DATA(0x1F);
LCD_WR_DATA(0x25);
LCD_WR_DATA(0x22);
LCD_WR_DATA(0x0B);
LCD_WR_DATA(0x06);
LCD_WR_DATA(0x0A);
LCD_WR_DATA(0x4E);
LCD_WR_DATA(0xC6);
LCD_WR_DATA(0x39);
LCD_WR_DATA(0x00);
LCD_WR_DATA(0x00);
LCD_WR_DATA(0x00);
LCD_WR_DATA(0x00);
LCD_WR_DATA(0x00);
LCD_WR_DATA(0x00);
LCD_WR_REG(0XE1);
LCD_WR_DATA(0x1F);
LCD_WR_DATA(0x3F);
LCD_WR_DATA(0x3F);
LCD_WR_DATA(0x0F);
LCD_WR_DATA(0x1F);
LCD_WR_DATA(0x0F);
LCD_WR_DATA(0x46);
LCD_WR_DATA(0x49);
LCD_WR_DATA(0x31);
LCD_WR_DATA(0x05);
LCD_WR_DATA(0x09);
LCD_WR_DATA(0x03);
LCD_WR_DATA(0x1C);
LCD_WR_DATA(0x1A);
LCD_WR_DATA(0x00);
LCD_WR_REG(0XF1);
LCD_WR_DATA(0x36);
LCD_WR_DATA(0x04);
LCD_WR_DATA(0x00);
LCD_WR_DATA(0x3C);
LCD_WR_DATA(0x0F);
LCD_WR_DATA(0x0F);
LCD_WR_DATA(0xA4);
LCD_WR_DATA(0x02);
LCD_WR_REG(0XF2);
LCD_WR_DATA(0x18);
LCD_WR_DATA(0xA3);
LCD_WR_DATA(0x12);
LCD_WR_DATA(0x02);
LCD_WR_DATA(0x32);
LCD_WR_DATA(0x12);
LCD_WR_DATA(0xFF);
LCD_WR_DATA(0x32);
LCD_WR_DATA(0x00);
LCD_WR_REG(0XF4);
LCD_WR_DATA(0x40);
LCD_WR_DATA(0x00);
LCD_WR_DATA(0x08);
LCD_WR_DATA(0x91);
LCD_WR_DATA(0x04);
LCD_WR_REG(0XF8);
LCD_WR_DATA(0x21);
LCD_WR_DATA(0x04);
LCD_WR_REG(0x36);
LCD_WR_DATA(0x60);
LCD_WR_REG(0x3A);
LCD_WR_DATA(0x55);
LCD_WR_REG(0x11);
delay_ms(120);
LCD_WR_REG(0x29);
}
虽然代码没问题,但是使用时还是建议你下一个9486的数据手册,仔细了解一下那些赋值的数据含义,对清楚的控制彩屏有至关重要的意义,代码使用时先将代码复制粘贴到一个新建的文本文挡里,保存后将文件更名为ILI9486.c,而后将这个文件放在工程的文件夹里就能在程序中调用了。
接下来是彩屏驱动的程序:
#include<STC12C5A60S2.h>
#include <intrins.h> //含_nop_()语句的头文件
#define uchar unsigned char  
#define uint unsigned int  
//--------------定义颜色数据-------------------------
//--寄存器0x36的D3=0为R-G-B顺序;若D3=1则为B-G-R顺序
//--以下为R-G-B顺序的颜色数据#define White          0xFFFF
#define Black          0x0000#define Blue           0x001F
#define Blue2          0x051F#define Red            0xF800
#define Magenta        0xF81F#define Green          0x07E0
#define Cyan           0x7FFF#define Yellow         0xFFE0
//--------------定义与触摸屏有关的变量、命令字------------------
sbit CS_t    =P2^0;
sbit SCK_t    =P2^1;
sbit MISO_t    =P2^2;    //数据输出
sbit MOSI_t    =P2^3;    //数据输入
sbit IQR_t    =P2^4;
#define    x_x    0x90    //横屏横向坐标
#define    y_y    0xD0    //横屏纵向坐标uint xn,yn,x_n,y_n;
//--------------定义与TFT-LCD有关的变量、命令字------------------
#define DP_DAT P0         //8位数据/指令输出端口  
sbit CS        =P3^2;            //片选
sbit RS        =P3^3;            //数据/命令选择
sbit RW        =P3^4;
sbit RD        =P3^5;
sbit RES    =P3^6;            //复位
//==================ms延时函数========================
void delay_ms(uint count)
{
int i,j;  
for(i=0;i<count;i++)                                                                    
{        
for(j=0;j<260;j++);
}  }
//===================8bit数据==写地址=============
void LCD_WR_REG(uchar dat)
{    
CS=0;
RS=0;//0写地址    
DP_DAT=dat;
RW=0;  
RW=1;
CS=1;
}
//===================8bit数据==写数据=============
void LCD_WR_DATA(uchar dat)
{    
CS=0;
RS=1;//1写数据    
DP_DAT=dat;
RW=0;    
RW=1;
CS=1;
}
//==================16bit数据==写地址/写数据=============
void LCD_WR_16bit(bit i,uint dat)
{    
CS=0;
RS=i;//0写地址;1写数据    RD=1;
DP_DAT=dat>>8;  
RW=0;
RW=1;    
DP_DAT=dat;
RW=0;    
RW=1;
CS=1;
}
//===============定义显示窗体===========================
//*********************************************************
//此屏为4.68寸、分辨率480*272//横屏的行起始地址为24、行范围24---320
//*********************************************************
void LCD_SetPos(uint x0,uint x1,uint y0,uint y1)
{    
LCD_WR_16bit(0,0x2a);//行地址、横屏时为X坐标
LCD_WR_16bit(1,x0);    LCD_WR_16bit(1,x1);

LCD_WR_16bit(0,0x2b);//列地址、横屏时为Y坐标    
LCD_WR_16bit(1,y0+24);    LCD_WR_16bit(1,y1+24);

LCD_WR_16bit(0,0x2c);//开始写入GRAM;地址指针累加
}
//========光标位置=======================================
/*void LCD_SetCursor(uint x0, uint y0){                          
LCD_WR_16bit(0,0x2a);//行地址、横屏时为X坐标    
LCD_WR_16bit(1,x0);

LCD_WR_16bit(0,0x2b);//列地址、横屏时为Y坐标    
LCD_WR_16bit(1,y0+24);

LCD_WR_16bit(0,0x2c);//开始写入GRAM;地址指针累加}*/
//===========画点儿函数==================================
/*void LCD_DrawPoint(uint x,uint y,uint color)
{    
LCD_SetCursor(x,y);//设置光标位置
LCD_WR_16bit(1,color);
}*/
//===========画线函数=====================================
/*void LCD_DrawLine(uint x1,uint x2,uint y1,uint y2,uint color)
{    
uint t;
int xerr=0,yerr=0,delta_x,delta_y,distance;    
int incx,incy,uRow,uCol;

delta_x=x2-x1; //计算坐标增量
delta_y=y2-y1;     uRow=x1;
uCol=y1;     if(delta_x>0)incx=1; //设置单步方向
else if(delta_x==0)incx=0;//垂直线    
else {incx=-1;delta_x=-delta_x;}
if(delta_y>0)incy=1;    
else if(delta_y==0)incy=0;//水平线
else{incy=-1;delta_y=-delta_y;}    
if( delta_x>delta_y)distance=delta_x; //选取基本增量坐标轴
else distance=delta_y;    
for(t=0;t<=distance+1;t++ )//画线输出
{          
LCD_DrawPoint(uRow,uCol,color);//画点
xerr+=delta_x ;        
yerr+=delta_y ;
if(xerr>distance)        
{
xerr-=distance;            
uRow+=incx;
}        
if(yerr>distance)
{            
yerr-=distance;
uCol+=incy;        
}
}  } */
//=============全屏涂色====================================
//长边==0--480;短边==24--296
void ClearScreen(uint bColor){
uint i,j;LCD_SetPos(0,480-1,0,296-1);    //给出显示范围
for (i=0;i<480;i++)            //充填  
{
for (j=24;j<296;j++)        
{LCD_WR_16bit(1,bColor);}
}}
//=============局部涂色=====================================//
/*void Show_RGB (uint x0,uint x1,uint y0,uint y1,uint Color)
{uint i,j;
LCD_SetPos(x0,x1-1,y0,y1-1);    for(i=y0;i<=y1;i++)
    {       for (j=x0;j<=x1;j++)
       {LCD_WR_16bit(1,Color);}    }
}*/
//===============================================
void LCD_Reset(void){
    RES=1;    delay_ms(50);    
    RES=0;    delay_ms(50);
    RES=1;    delay_ms(50);
}//================================================
#include "GB3232.h"    //调用32*32汉字字模
//(x行,y列,"字",字色,底色)
void PutGB3232(uint x, uint  y, uchar c[2], uint fColor,uint bColor)
{
uint i,j,k;x*=32;y*=32;
LCD_SetPos(x,  x+32-1,y, y+32-1);
for (k=0;k<3;k++)//3标示自建汉字库中的个数,循环查询内码
{    
if ((codeGB_32[k].Index[0]==c[0])&&(codeGB_32[k].Index[1]==c[1]))
{
for(i=0;i<128;i++)
{          
uint m=codeGB_32[k].Msk;
for(j=0;j<8;j++)
{
if((m&0x80)==0x80)
{
LCD_WR_16bit(1,fColor);                
}
else
{                
LCD_WR_16bit(1,bColor);
}            
m<<=1;
} }
} }    
}
//===以下代码涉及触摸屏控制========================
//====读触摸位置===================================
/*uint read_x_y(uchar cmd)
{uint Num;
uchar i;CS_t=0;
SCK_t=0;  for(i=0;i<8;i++) // 发送1字节读取命令
{if(cmd&0x80)
MOSI_t=1;else MOSI_t= 0;
cmd<<=1;SCK_t=0;    
SCK_t=1;}
delay_ms(1);SCK_t=1;    
SCK_t=0;       for(i=0;i<16;i++) // 接收2字节结果
{                   Num<<=1;      
SCK_t=0;                  SCK_t=1;
if(MISO_t==1)Num++;          }      
Num>>=4;  // 结果右移4位,获取高12位有效数据        CS_t=1;
return(Num);}*/
//=========触屏采集数据与串口输出===============
/**********以下程序用于串口通信显示************/
/*void InitUart()//串口初始化函数{
SCON = 0x50;     //T1工作于方式1TMOD = 0x20;     //T1 8位自动重装
TH1 = 0xf3;      //晶体12MHz\波特率2400(仅适合2400)TR1 = 1;         //启动T1
}*/
//==============================================
/*void dat_out(uint dat){
SBUF =dat>>8;while (!TI);
TI = 0; delay_ms(5);
SBUF =dat;while (!TI);
TI = 0; delay_ms(5);
}*/
//==============================================
/*LCD_DrawLine(0,480,16,16,Red);LCD_DrawLine(0,480,32,32,Red);
//uint n;for(n=0;n<480;n=n+16)
{LCD_DrawLine(n,n,0,32,Red);
}if(IQR_t==0)
{xn=read_x_y(x_x);
x_n=480-((xn-90)/3.969);dat_out(x_n);
delay_ms(5);dat_out(0xaaaa);
delay_ms(5);yn=read_x_y(y_y);
y_n=272-((yn-89)/6.9);dat_out(y_n);
delay_ms(5);dat_out(0xbbbb);
delay_ms(5);}*/
//==============================================
#include "ILI9486.c"//调用控制器初始化代码
void  main(void)
{
LCD_Init();        //TFT-LCD初始化
ClearScreen(Black);    //全屏涂黑Black
//InitUart();while(1)
{PutGB3232(1,1,"年",Yellow,Black);//在屏上的第二行第二个位置显示一个32*32的黑底黄色汉字
}}
建好新的工程后,贴上这段代码,编译后就能使用了,但一定要记得在工程文件夹里一定要有一个临时测试用的字库文件,待到Flash字库完成后就可以删除了,下面是临时字库文件。
// ------------------  汉字字模的数据结构定义 ------------------------ //
struct  typFNT_GB32                 // 汉字字模数据结构
{      
unsigned char  Index[3];               // 汉字内码索引    
unsigned char   Msk[128]; //128        // 点阵码数据 };
//======阴码、顺向、逐行=========//
code struct  typFNT_GB32 codeGB_32[] =          // 数据表
{
"年",
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x78,0x00,0x00,
0x00,0x70,0x00,0x00,0x00,0xE0,0x00,0x00,0x00,0xE0,0x00,0x00,0x01,0xFF,0xFF,0xF0,
0x03,0xFF,0xFF,0xF0,0x03,0x80,0xE0,0x00,0x07,0x00,0xE0,0x00,0x0F,0x00,0xE0,0x00,
0x1E,0x00,0xE0,0x00,0x3C,0x00,0xE0,0x00,0x09,0xFF,0xFF,0xE0,0x01,0xFF,0xFF,0xE0,
0x01,0xC0,0xE0,0x00,0x01,0xC0,0xE0,0x00,0x01,0xC0,0xE0,0x00,0x01,0xC0,0xE0,0x00,
0x01,0xC0,0xE0,0x00,0x01,0xC0,0xE0,0x00,0x3F,0xFF,0xFF,0xFC,0x3F,0xFF,0xFF,0xFC,
0x00,0x00,0xE0,0x00,0x00,0x00,0xE0,0x00,0x00,0x00,0xE0,0x00,0x00,0x00,0xE0,0x00,
0x00,0x00,0xE0,0x00,0x00,0x00,0xE0,0x00,0x00,0x00,0xE0,0x00,0x00,0x00,0x00,0x00,
"月",
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0xFF,0xFF,0x80,0x00,0xFF,0xFF,0x80,0x00,0xC0,0x01,0x80,0x00,0xC0,0x01,0x80,
0x00,0xC0,0x01,0x80,0x00,0xC0,0x01,0x80,0x00,0xC0,0x01,0x80,0x00,0xFF,0xFF,0x80,
0x00,0xFF,0xFF,0x80,0x00,0xC0,0x01,0x80,0x00,0xC0,0x01,0x80,0x00,0xC0,0x01,0x80,
0x00,0xC0,0x01,0x80,0x00,0xC0,0x01,0x80,0x00,0xFF,0xFF,0x80,0x00,0xFF,0xFF,0x80,
0x00,0xC0,0x01,0x80,0x01,0xC0,0x01,0x80,0x01,0xC0,0x01,0x80,0x01,0xC0,0x01,0x80,
0x01,0x80,0x01,0x80,0x03,0x80,0x01,0x80,0x03,0x80,0x01,0x80,0x07,0x00,0x03,0x80,
0x0F,0x00,0x0F,0x80,0x1E,0x00,0x0F,0x80,0x04,0x00,0x0C,0x00,0x00,0x00,0x00,0x00,
"日",
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0xFF,0xFF,0xC0,
0x01,0xFF,0xFF,0xC0,0x01,0xFF,0xFF,0xC0,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x01,0xC0,
0x01,0xC0,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x01,0xC0,
0x01,0xC0,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x01,0xFF,0xFF,0xC0,0x01,0xFF,0xFF,0xC0,
0x01,0xC0,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x01,0xC0,
0x01,0xC0,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x01,0xC0,
0x01,0xC0,0x01,0xC0,0x01,0xFF,0xFF,0xC0,0x01,0xFF,0xFF,0xC0,0x01,0xC0,0x01,0xC0,
0x01,0xC0,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,
};

将这段代码复制粘贴到一个文本文档里,保存后将.txt重新命名为GB3232.h即可,经过以上的折腾,屏上就会显示出汉字了。程序中被封闭的代码含有画点、画线等函数,都是在折腾这块彩屏时用到的,显示字符时没有用途,就闲置在哪里如果有用到的可以玩一下,而那些涉及触摸屏的代码当初是费了好些力气调试出来的,最终还要用到的。
----------继续更新在1楼-----------------    











[ 此帖被慕名而来在2016-04-20 11:14重新编辑 ]
本文内容包含图片或附件,获取更多资讯,请 登录 后查看;或者 注册 成为会员获得更多权限
本帖最近打赏记录:共15条打赏 ,M币+43
12
离线慕名而来

发帖
1706
M币
6089
专家
11
粉丝
68
只看该作者 1楼 发表于: 2016-03-29
请登录后查看
[ 此帖被慕名而来在2016-04-13 10:48重新编辑 ]
本文内容包含图片或附件,获取更多资讯,请 登录 后查看;或者 注册 成为会员获得更多权限
本帖最近打赏记录:共13条打赏 ,M币+38
12
离线majiwu1234

发帖
14860
M币
7592
专家
7
粉丝
1319
只看该作者 2楼 发表于: 2016-03-29
请登录后查看
离线benli

发帖
33704
M币
6633
专家
91
粉丝
488
只看该作者 3楼 发表于: 2016-03-29
离线fsss007

发帖
755
M币
8006
专家
3
粉丝
68
只看该作者 4楼 发表于: 2016-03-29
请登录后查看
离线zxz281
发帖
12
M币
887
专家
0
粉丝
1
只看该作者 5楼 发表于: 2016-03-29
请登录后查看
离线lailai518

发帖
1056
M币
4113
专家
4
粉丝
21
只看该作者 6楼 发表于: 2016-03-29
请登录后查看
离线zqf900605

发帖
1789
M币
865
专家
2
粉丝
40
只看该作者 7楼 发表于: 2016-03-29
请登录后查看
离线crg_t35

发帖
111
M币
6
专家
0
粉丝
11
只看该作者 8楼 发表于: 2016-03-30
请登录后查看
离线慕名而来

发帖
1706
M币
6089
专家
11
粉丝
68
只看该作者 9楼 发表于: 2016-03-30
请登录后查看
快速回复
限80 字节
温馨提示:欢迎交流讨论,请勿发布纯表情、纯引用等灌水帖子;以免被删除
 
上一个 下一个