
-
UID:1505079
-
- 注册时间2013-08-18
- 最后登录2026-09-17
- 在线时间384小时
-
-
访问TA的空间加好友用道具
|
—
本帖被 發騷友 设置为精华,作者+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 POSITIVELCD_WR_DATA(0x1a);//VREG2OUT NEGATIVELCD_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--296void 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重新编辑 ]
|