回答

收藏

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

#线上活动 #线上活动 3153 人阅读 | 0 人回复 | 2017-06-30

使用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]复制代码

程序的执行效果如下:


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

使用道具 举报

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

本版积分规则

关闭

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