写这部分的应用,关键在于电路的连接方式与SMG12864的驱动方法。驱动来源于网络,这个博客说的比较详细,里面有时序图以及各种功能的使用方法列表,详细的说明了如何使用该模块显示常用的汉字信息,我对该方法做了一些修改,电路连接方式被简化,代码被修改,并没有直接搬运该博客内容。该方法也许对于波形发生器,波形测量,物联网应用的数据显示有一定的作用,所以写这篇文章。
以下为现在的电路连接方式,忽略了单片机的最小系统,大家可以自行添加。
现有的经过修改和编译的代码如下:
#include#include #include #define DATA P2 typedef unsigned char uchar; sbit rs = P3 ^ 2; sbit rw = P3 ^ 1; sbit en = P3 ^ 0; sbit cs1 = P3 ^ 4; sbit cs2 = P3 ^ 3; unsigned char number = 0; uchar code zhCN[] = { //每个位置占据1列8行 //第1个字 //上半部分:第1列,第2列,第3列...第8列 0x00,0x00,0x00,0x00,0xC0,0x70,0x1E,0x03,0x07,0x1C,0xF0,0x80,0x00,0x00,0x00,0x00, //下半部分 0x00,0x70,0x78,0x0E,0x07,0x06,0x06,0x06,0x06,0x06,0x06,0x0F,0x78,0x40,0x00,0x00, //第2个字 0x00,0x00,0x00,0x00,0xC0,0x70,0x1E,0x03,0x07,0x1C,0xF0,0x80,0x00,0x00,0x00,0x00, 0x00,0x70,0x78,0x0E,0x07,0x06,0x06,0x06,0x06,0x06,0x06,0x0F,0x78,0x40,0x00,0x00, //第3个字 0x00,0x00,0x00,0x00,0xC0,0x70,0x1E,0x03,0x07,0x1C,0xF0,0x80,0x00,0x00,0x00,0x00, 0x00,0x70,0x78,0x0E,0x07,0x06,0x06,0x06,0x06,0x06,0x06,0x0F,0x78,0x40,0x00,0x00, //第4个字 0x00,0x00,0x00,0x00,0xC0,0x70,0x1E,0x03,0x07,0x1C,0xF0,0x80,0x00,0x00,0x00,0x00, 0x00,0x70,0x78,0x0E,0x07,0x06,0x06,0x06,0x06,0x06,0x06,0x0F,0x78,0x40,0x00,0x00, //第5个字 0x00,0x00,0x00,0x00,0xC0,0x70,0x1E,0x03,0x07,0x1C,0xF0,0x80,0x00,0x00,0x00,0x00, 0x00,0x70,0x78,0x0E,0x07,0x06,0x06,0x06,0x06,0x06,0x06,0x0F,0x78,0x40,0x00,0x00, //第6个字 0x00,0x00,0x00,0x00,0xC0,0x70,0x1E,0x03,0x07,0x1C,0xF0,0x80,0x00,0x00,0x00,0x00, 0x00,0x70,0x78,0x0E,0x07,0x06,0x06,0x06,0x06,0x06,0x06,0x0F,0x78,0x40,0x00,0x00, //第7个字 0x00,0x00,0x00,0x00,0xC0,0x70,0x1E,0x03,0x07,0x1C,0xF0,0x80,0x00,0x00,0x00,0x00, 0x00,0x70,0x78,0x0E,0x07,0x06,0x06,0x06,0x06,0x06,0x06,0x0F,0x78,0x40,0x00,0x00, //第8个字 0x00,0x00,0x00,0x00,0xC0,0x70,0x1E,0x03,0x07,0x1C,0xF0,0x80,0x00,0x00,0x00,0x00, 0x00,0x70,0x78,0x0E,0x07,0x06,0x06,0x06,0x06,0x06,0x06,0x0F,0x78,0x40,0x00,0x00, }; void Delay(uchar m) { uchar i; for (; m > 0; --m) for (i = 0; i < 110; ++i) ; } void CheckState() { //通过读取BF标志位(引脚9,对应P0^7)状态判断模块是否繁忙 uchar dat; //读状态下RS=0,R/W=1,E=1 rs = 0; rw = 1; do { DATA = 0x00; //RST=0正常,BUSY=0准备状态,ON/OFF=0显示关, en = 1; _nop_(); //打开使能后检测模块状态 dat = DATA; //状态读入dat en = 0; dat = 0x80 & dat; // 1000 0000 & dat 通过与操作隔离后7位,仅判断最高位 } while(dat != 0x00); //P0^7为0时跳出循环,BUSY=0准备状态 } void SelectScreen(uchar screen) { //CS为低电平时亮 switch(screen) { case 0: //全屏显示 cs1 = 0; //IC1控制右半屏 _nop_(); _nop_(); _nop_(); cs2 = 0; //IC2控制左半屏 _nop_(); _nop_(); _nop_(); break; case 1: //右屏显示 cs1 = 0; _nop_(); _nop_(); _nop_(); cs2 = 1; _nop_(); _nop_(); _nop_(); break; case 2: //左屏显示 cs1 = 1; _nop_(); _nop_(); _nop_(); cs2 = 0; _nop_(); _nop_(); _nop_(); break; } } void SendCommandToLCD(uchar com) { //p.s.在CS1或CS2低电平情况下才能写入命令 CheckState(); rs = 0; rw = 0; DATA = com; en = 1; _nop_(); _nop_(); en = 0; } void SetonOff(uchar onoff) { //传入0,关显示,00111110|00000000 = 00111110 //传入1,开显示,00111110|00000001 = 00111111 onoff = 0x3E | onoff; SendCommandToLCD(onoff); //写指令onoff } void SetLine(uchar page) { //10111000|00000000 = 10111000 //10111000|00000001 = 10111001 //10111000|00000010 = 10111010 //... //10111000|00000111 = 10111111 //共8页,设置页地址 page = 0xb8 | page; SendCommandToLCD(page); } void SetColumn(uchar column) { //01xxxxxx 后六位为列地址 //先通过与操作屏蔽前2位,将地址范围限制在0-63之间 //再通过或操作将列操作指令前两位代入 column = column & 0x3F; //00000000 & 00111111 = 00000000 column = 0x40 | column; //01000000 | 00000000 = 01000000 SendCommandToLCD(column); } void WriteByte(uchar dat) { CheckState(); rs = 1; rw = 0; DATA = dat; en = 1; _nop_(); _nop_(); en = 0; } void ClearScreen(uchar screen) { uchar i, j; SelectScreen(screen); for (i = 0; i < 8; ++i) //书上源码建立16页,此处建立8页正常运行 { SetLine(i); //建立行 SetColumn(0); //建立列 for (j = 0; j < 64; ++j) //通过遍历该行的64列写入内容,列地址自动 WriteByte(0x00); } } void SetStartLine(uchar startline) { //设置开始行时前两位为11 startline = 0xC0 | startline; SendCommandToLCD(startline); } void InitLCD() { CheckState(); //检查LCD状态,是否繁忙,每次操作前都要进行检查 SelectScreen(0); //全屏显示,将要显示的屏幕部分置为低电平 SetonOff(0); //关显示,1为开显示,0位关显示 SelectScreen(0); SetonOff(1); //开显示 SelectScreen(0); ClearScreen(0); //0清全屏,1清左屏,2清右屏 SetStartLine(0); //从第0行开始 } void Display(uchar screen, uchar page, uchar column, uchar num) { uchar i; SelectScreen(screen); //选择对应要亮的屏 SetLine(page); //建立行(页) column = column & 0x3F; // column & 00111111 屏蔽前两位 SetColumn(column); //建立列 //写入字库第32*num~32*num+16位的数据 //第1个字:0~15,对应字库第1行 //第2个字:32~47,对应字库第3行 //第3个字:64~79,对应字库第5行 //... for (i = 0; i < 16; ++i) WriteByte(zhCN[i + 32 * num]); SetLine(page + 1); SetColumn(column); //写入字库第32*num+16~32*num+32位的数据 //第1个字:16~31,对应字库第2行 //第2个字:48~63,对应字库第4行 //第3个字:80~95,对应字库第6行 //... for (i = 0; i < 16; ++i) WriteByte(zhCN[i + 32 * num + 16]); } int main() { uchar i; uchar j; uchar line; //+ uchar m; //+ uchar n; //+ uchar screen; //+ uchar tempt; //+ uchar n2 = 1,n3 = 0,s = 1,t = 1; // InitLCD(); ClearScreen(0); //清屏 while(1) //余晖效应 { for (i = 0; i < 64; ++i) //如果此处改成10,则在向上移动10行后重新出现在第0行,此处使用64的倍数来实现无限循环(无间断),书上源码循环128次,64次也无影响 { if(i==0){ for(t == 1;t<64;t++){ SetStartLine(t); //循环建立开始行,每一次循环都上移1行 Display(2, 0, 0 * 16, 0); //左屏,第0页, 0列,第0个字 Display(2, 0, 1 * 16, 1); //左屏,第0页, 16列,第1个字 Display(2, 0, 2 * 16, 2); //左屏,第0页, 32列,第2个字 Display(2, 0, 3 * 16, 3); //左屏,第0页, 48列,第3个字 Display(1, 0, 4 * 16, 4); //右屏,第0页, 64列,第4个字 Display(1, 0, 5 * 16, 5); //右屏,第0页, 80列,第5个字 Display(1, 0, 6 * 16, 6); //右屏,第0页, 96列,第6个字 Display(1, 0, 7 * 16, 7); //右屏,第0页,128列,第7个字 } } ClearScreen(0); //清屏 for(screen = 1;screen<3;screen++){ SelectScreen(screen); for (m = 0; m < 8; ++m) //书上源码建立16页,此处建立8页正常运行 { SetLine(m); //建立行 //for (line = 0; line < 64; ++line) { SetColumn(m*8-8); //建立列 //for (n = 0; n < 64*2; ++n){ //通过遍历该行的64列写入内容,列地址自动+1 for (j = 0; j < 64 - m*8; ++j){ //通过遍历该行的64列写入内容,列地址自动+1 n2 = (j+m*8)/8+1; n3 = n2; s = 1; for(;n2>0;n2--) s = s*2; //if(m - 1 == (j + m*8)/8){ if((m+1)*8 == j+1+m*8){ if(screen == 2){ SetLine(7-m); //建立行 for(tempt = 0x80;tempt>0x01;tempt=tempt/2) WriteByte(tempt); break; } else{ for(tempt = 0x01;tempt<0x80;tempt=tempt*2) WriteByte(tempt); break; } } else{ //if((m+1)*8 == j+1+m*8) // WriteByte(s); //else WriteByte(0x00); //} } } //} } //} } SelectScreen(0); //由于显示后四个字符时左屏处于关显示状态,需要打开全屏 Delay(50); } } }
编译后的效果图,文字显示(一):
编译后的效果图,简单三角函数全屏显示(二):
文字的取模方式为软件PCTOLCD2002:
注意取模大小为16*16,方向或数据样式为列行式。
文章源代码来源:https://www.cnblogs.com/hughdong/p/6895631.html
THANK YOU FOR YOUR READING!
THE END.



