查看: 2316|回复: 0

爱玩板卡+使用orangepi zero控制LCD5110显示中文

[复制链接]
  • TA的每日心情
    奋斗
    2022-6-20 16:11
  • 签到天数: 19 天

    连续签到: 1 天

    [LV.4]偶尔看看III

    发表于 2017-6-30 00:19:26 | 显示全部楼层 |阅读模式
    分享到:

    使用GPIO模拟SPI是单片机开发中常用的一种手段,GPIO还可以模拟IIC等总线的时序,可以用在没有相应外设的处理器上,节省成本。

    下面的代码是软模SPI写LCD5110的程序:

    • void WriteByte(unsigned char byte,unsigned char dc)
    • {
    •     int i;
    •     CE(0);
    •     DC(dc);
    •     for(i=0;i<8;i++)
    •     {
    •         if(byte & 0x80)
    •             DIN(1);
    •         else
    •             DIN(0);
    •         CLK(0);
    •         // usleep(10);//LCD5110的响应速度很快,不加延时也行!!!
    •         CLK(1);
    •         // usleep(10);
    •         byte <<= 1;
    •     }
    •     CE(1);
    • }

    [color=rgb(51, 102, 153) !important]复制代码

    下面的代码是刷新LCD的两个函数,第一个是使用84*48点阵的数组,第二个是使用84*6点阵的数组:
    • int LCD_Buffer[48 * 84] =
    • {  0x00,};
    • void LCD_Refresh()
    • {
    •     unsigned int i,j,k;
    •     unsigned char data;
    •     WriteByte(0x40,0);
    •     WriteByte(0x80,0);
    •     for(i=0;i<6;i++)
    •     {
    •         for(j=0;j<84;j++)
    •         {
    •             for(k=0;k<8;k++)
    •             {
    •                 data >>= 1;
    •                 if( LCD_Buffer[ ( (i<<3) + k ) * 84 + j ] )
    •                     data |= 0x80;
    •             }
    •             // printf("%X ",data);
    •             WriteByte(data,1);
    •         }
    •         // printf("\r\n");
    •     }
    • }
    • unsigned char nBitmapDot[] =                  // 数据表
    • {
    •       0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    •       0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    •       0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xC0,0xE0,0xE0,0xE0,
    •       0xE0,0xE0,0xE0,0xE0,0xE0,0xC0,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    •       0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    •       0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    •       0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    •       0x00,0x06,0x0F,0x0F,0x07,0x0F,0x0E,0x1E,0x1C,0x00,0x00,0x00,0x00,0x00,0x00,0x01,
    •       0x01,0x01,0x00,0x00,0x80,0xC0,0xE0,0xF0,0xFF,0x7F,0x1F,0x00,0x00,0x00,0x00,0x00,
    •       0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    •       0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    •       0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    •       0x00,0x3C,0x7E,0x7C,0x70,0x70,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0xC0,0xE0,
    •       0xC0,0x30,0x78,0x78,0x78,0x7C,0x7E,0x7F,0x77,0x77,0xF3,0xF1,0xF0,0xF0,0x70,0x70,
    •       0x70,0xF0,0x70,0x70,0x70,0x70,0x70,0x70,0x70,0x70,0x70,0xF0,0xE0,0xE0,0xC0,0x80,
    •       0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    •       0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    •       0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,
    •       0xFF,0xFF,0x7F,0x01,0x00,0x00,0x00,0x00,0x00,0x80,0xC0,0xE0,0xF8,0xFF,0x3F,0x0F,
    •       0x03,0x03,0x03,0x00,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    •       0x01,0x01,0x07,0xFF,0xFF,0xFC,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    •       0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    •       0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x80,0x80,0xC0,0xE0,
    •       0xF8,0x7E,0x3F,0x1F,0x03,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x07,0x07,0x03,
    •       0x01,0x80,0xC0,0xE0,0xF0,0xF8,0x7C,0x3E,0x0F,0x8F,0xC7,0x80,0x00,0x00,0x00,0x00,
    •       0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,
    •       0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    •       0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x03,
    •       0x03,0x03,0x03,0x03,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    •       0x00,0x00,0x00,0x00,0x00,0x01,0x03,0x03,0x01,0x00,0x00,0x00,0x00,0x07,0x0F,0x0F,
    •       0x0E,0x0E,0x0E,0x0E,0x0E,0x0E,0x0E,0x0F,0x07,0x07,0x07,0x07,0x03,0x03,0x00,0x00,
    •       0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
    • };
    • void LCD_Refresh2(unsigned char *buff)
    • {
    •     unsigned int i,j;
    •     WriteByte(0x40,0);
    •     WriteByte(0x80,0);
    •     // for(i=0;i<6;i++)
    •     // {
    •         // for(j=0;j<84;j++)
    •         // {
    •             // WriteByte(buff[i*84 + j],1);
    •         // }
    •     // }
    •     for(i=0;i<6*84;i++)
    •     {
    •         WriteByte(buff,1);
    •     }
    • }

    [color=rgb(51, 102, 153) !important]复制代码

    初始化GPIO以及LCD5110代码:
    • GPIO_Init();
    • GPIO_ConfigPin(PC,0,OUT);   //CLK
    • GPIO_ConfigPin(PC,1,OUT);   //DC
    • GPIO_ConfigPin(PC,2,OUT);   //DIN
    • GPIO_ConfigPin(PC,3,OUT);   //CE
    • GPIO_ConfigPin(PA,15,OUT);  //LED
    • while(i--)
    • {
    •     GPIO_SetPin(PA,15,1);
    •     usleep(50000);
    •     GPIO_SetPin(PA,15,0);
    •     usleep(50000);
    • }
    • unsigned int data;
    • WriteByte(0x21,0);
    • WriteByte(0xc8,0);
    • WriteByte(0x06,0);
    • WriteByte(0x13,0);
    • WriteByte(0x20,0);
    • WriteByte(0x0c,0);
    • WriteByte(0x40,0);
    • WriteByte(0x80,0);

    [color=rgb(51, 102, 153) !important]复制代码

    初始化LCD之后调用LCD_Refresh或者LCD_Refresh2即可看到图片显示。

    在此基础上需要添加屏幕绘点的函数:
    • void LCD_DrawDot(int x,int y,int onoff)
    • {
    •     int a = y / 8,b = y % 8;
    •     if(onoff)
    •     {
    •         LCD_Buffer[a * 84 + x] |= (0x01 << b);
    •     }
    •     else
    •     {
    •         LCD_Buffer[a * 84 + x] &= ~(0x01 << b);
    •     }
    •     WriteByte(0x80 | x,0);
    •     WriteByte(0x40 | a,0);
    •     WriteByte(LCD_Buffer[a * 84 + x],1);
    • }

    [color=rgb(51, 102, 153) !important]复制代码

    使用的缓冲区是84*6的,所以这里的LCD_DrawDot函数是在84*6的数组中进行绘制点,绘点不会影响与该像素点在同一个字节中的其他7个像素,使用的是或操作和与操作。有了这个绘点的基础函数就可以进行画线、画圆等函数,同样的也可以进行绘制汉字和ASCII码。

    在绘制汉字和ASCII码之前需要了解一下GB2312和ASCII码表的编码规范,首先ASCII码比较简单,我制作的ASCII码字库是从‘ ’到‘~’的,全部字符如下: !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~,使用的是8*16点阵,有点浪费空间其实6*12就够了貌似,但是为了配合汉字的16*16还是使用了8*16点阵。ASCII字库一共使用了1520字节的空间,存储在字库文件的前1520字节,后面的空间用于存储GB2312字库空间。GB2312的内容 太多了,网上一大把的就不贴出来了,但是这里要说说GB2312的编码规则。

    ASCII码规定每个字符使用一个字节表示,并且该字节的范围为0x00到0x7F,所以当一个字符在0x00到0x7f之间的时候标志这个字符是一个ASCII字符,要从ASCII码库中提取对应的点阵数据显示。当一个字符的编码大于0xA0时则表示这个字符不是ASCII码字符了,是GB2312或者其他编码的字符例如UTF8等。程序中的汉字可能是GB2312编码也可能是其他编码格式,需要手动调节编辑器的编码方式,例如使用Notepad++时选择格式-》中文-》GB2312,这样才能保证程序中的中文是以GB2312的编码格式存储在字符串中的。GB2312编码规定一个字符是有两个字节组成的,两个字节的范围都是A1A1-FEFE,所以可以通过范围来判断是否是GB2312字符。GB2312的编码标准中有区码和位码,前者用于表示汉字所在的区,后者用于表示汉字所在区中的偏移量, 具体的编码规范可以参考:http://tools.jb51.net/table/gb2312 和 http://www.qqxiuzi.cn/zh/hanzi-gb2312-bianma.php两篇文章。

    程序上有三个关于绘制字符的函数,第一个是绘制ASCII字符函数,第二个是绘制GB2312字符函数,最后一用于整合前面两个函数。

    • void LCD_DrawAscii(int x,int y,unsigned short offset)
    • {
    •     unsigned int i,j;
    •     for(i=0;i<16;i++)
    •     {
    •         for(j=0;j<8;j++)
    •         {
    •             if(FontData[offset*16 + i] & (0x80 >> j))
    •                 LCD_DrawDot(x + j, y + i,1);
    •             else
    •                 LCD_DrawDot(x + j,y + i,0);
    •         }
    •     }
    • }
    • void LCD_DrawHanzi(int x,int y,unsigned short offset)
    • {
    •     unsigned int i,j;
    •     for(i=0;i<16;i++)
    •     {
    •         for(j=0;j<16;j++)
    •         {
    •             if(FontData[offset*32 + 0x5f0 + i*2 + j/8] & (0x80 >> j%8))
    •                 LCD_DrawDot(x + j, y + i,1);
    •             else
    •                 LCD_DrawDot(x + j,y + i,0);
    •         }
    •     }
    • }
    • void LCD_DrawText(int x,int y,char *text)
    • {
    •     unsigned int i,j;
    •     for(i=0;text!='\0';i++)
    •     {
    •         if(text < 0xA0)   //ASCII
    •         {
    •             LCD_DrawAscii(x,y,text - ' ');
    •             x += 8;
    •         }
    •         else    //chinese
    •         {
    •             LCD_DrawHanzi(x,y,(text-0xA1)*94 + (text[++i] - 0xA1));  //这里i要自加1个因为汉子占用两个字节
    •             x += 16;
    •         }
    •     }
    • }

    [color=rgb(51, 102, 153) !important]复制代码

    LCD_DrawText函数的具体功能是在x、y像素位置绘制一个字符串text,这个函数会根据字符的类型调用LCD_DrawAscii和LCD_DrawHanzi函数实现字符绘制功能,主函数测试程序如下:

    • int fd;
    • struct stat file_stat;
    • if((fd = open("ASCII+GB2312.bin",O_RDWR)) < 0)
    • {
    •     printf("open gb2312 failed\r\n");
    •     goto close;
    • }
    • if(stat("ASCII+GB2312.bin",&file_stat) < 0)
    • {
    •     printf("stat failed\r\n");
    •     goto close;
    • }
    • printf("filesize:%d\r\n",file_stat.st_size);
    • FontData = (unsigned char *)malloc(file_stat.st_size);
    • if(FontData == NULL)
    • {
    •     printf("malloc failed\r\n");
    •     goto close;
    • }
    • read(fd,FontData,file_stat.st_size);
    • LCD_DrawText(0,0,"汤权1994");
    • LCD_DrawText(0,16,"123我是谁");
    • LCD_DrawText(0,32,"中华人民");

    [color=rgb(51, 102, 153) !important]复制代码

    程序的执行效果如下:


    转载自网络,版权归原作所有。
    回复

    使用道具 举报

    您需要登录后才可以回帖 注册/登录

    本版积分规则

    关闭

    站长推荐上一条 /2 下一条



    手机版|小黑屋|与非网

    GMT+8, 2024-5-5 00:35 , Processed in 0.111482 second(s), 15 queries , MemCache On.

    ICP经营许可证 苏B2-20140176  苏ICP备14012660号-2   苏州灵动帧格网络科技有限公司 版权所有.

    苏公网安备 32059002001037号

    Powered by Discuz! X3.4

    Copyright © 2001-2024, Tencent Cloud.