找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 3004|回复: 9
打印 上一主题 下一主题
收起左侧

单片机+无字库LCD12864显示汉字 英文 变量程序Proteus仿真图

  [复制链接]
跳转到指定楼层
楼主
LCD12864无字库
论坛有很多相关的例程
本小白利用空余时间,按照自己的重新写了一个小白都能看懂的驱动
大佬勿喷,仅供学习交流
下列是部分驱动程序靓照,请查阅
仿真原理图如下(proteus仿真工程文件可到本帖附件中下载)


单片机源程序如下:
  1. #include "12864.h"
  2. #include "ziku.h"

  3. void Delay_ms(unsigned int xms)  //@11.0592MHz
  4. {
  5.   unsigned int i,j;
  6.           for(i=xms;i>0;i--)   
  7.                 for(j=112;j>0;j--);  
  8. }

  9. static void LCD12864_Write(bit COM_Data,unsigned char  dat)  //12864操作函数
  10. {
  11.   LCD12864_RS=COM_Data;   //指令 0 数据 1
  12.         LCDData_Pro=dat;        //数据传输至P0扣
  13.         LCD12864_EN=1;          //置1
  14.         _nop_();
  15.         LCD12864_EN=0;          //置0   产生下降沿
  16. }

  17. void LCD12864_Init(void)   //12864初始化
  18. {
  19.         Delay_ms(300);   //等待系统上电稳定
  20. /******************************************************************************/
  21.   LCD12864_EN=1;                       
  22.   LCD12864_RS=1;                       
  23.         LCD12864_CS1=1;  //仿真 0 实物 1   
  24.         LCD12864_CS2=1;  //仿真 0 实物 1   
  25.         Delay_ms(10);
  26. /******************************************************************************/
  27.         LCD12864_Write(LCD12864_COM,0x3f);   //开显示
  28.         /*
  29.         LCD12864_Write(LCD12864_COM,0xc0);   //这段不写也可以正常显示
  30.         LCD12864_Write(LCD12864_COM,0xb8);
  31.         LCD12864_Write(LCD12864_COM,0x40);
  32.         */
  33.         LCD12864_Write(LCD12864_COM,0x30);   //打开基本指令
  34.         LCD_Clear();                         //清屏
  35. }
  36. /*****************************************************************************
  37. 函数功能:清平函数
  38. 入口参数:空
  39. 说    明:清空整个屏幕数据
  40. 版    本:V1.0
  41. 时    间:2020年5月9日
  42. *****************************************************************************/
  43. void LCD_Clear(void)
  44. {
  45.         unsigned char  i,j;
  46. #if LCD_Mode
  47.   LCD12864_CS1=1;   //选中左半屏
  48.         LCD12864_CS2=1;   //选中右半屏
  49. #else
  50.   LCD12864_CS1=0;   //选中左半屏
  51.         LCD12864_CS2=0;   //选中右半屏
  52. #endif
  53.         LCD12864_Write(LCD12864_COM,0xc0);  //行
  54.   for(i=0;i<8;i++)
  55.         {
  56.           LCD12864_Write(LCD12864_COM,0xb8+i); //页
  57.                 for(j=0;j<64;j++)
  58.                 {
  59.                   LCD12864_Write(LCD12864_COM,0x40+j); //列
  60.                         LCD12864_Write(LCD12864_DATA,0x00);
  61.                         Delay_ms(5);    //方便看清屏效果
  62.                 }
  63.         }
  64. }
  65. /*****************************************************************************
  66. 函数功能:地址写入函数
  67. 入口参数:X,Y
  68. 说    明:根据地址自动切换左、右屏
  69. 版    本:V1.0
  70. 时    间:2020年5月9日
  71. *****************************************************************************/
  72. void LCD12864_X_Y(unsigned char X,unsigned char Y)
  73. {
  74.   Y=Y&0x7f;   //限定范围,列不能超过127     
  75.         X=X&0x07;          //限定范围,行不能超过7
  76.         if(Y<64)
  77.         {
  78. #if LCD_Mode
  79.                  LCD12864_CS1=1;   //选中左半屏
  80.                  LCD12864_CS2=0;         //关闭右半屏
  81. #else
  82.                  LCD12864_CS1=0;   //选中左半屏
  83.                  LCD12864_CS2=1;         //关闭右半屏
  84. #endif
  85.                  LCD12864_Write(LCD12864_COM,0x40+Y);  //选择列基地址+Y 一共64行
  86.                  if(Y==63) Y=64;
  87.         }
  88.         else
  89.         {
  90. #if LCD_Mode
  91.           LCD12864_CS1=0;   //关闭左半屏
  92.                 LCD12864_CS2=1;          //选中右半屏
  93. #else
  94.     LCD12864_CS1=1;   //关闭左半屏
  95.                 LCD12864_CS2=0;          //选中右半屏
  96. #endif
  97.                 Y&=0x3f;
  98.           LCD12864_Write(LCD12864_COM,0x40+Y);  //选择列基地址+Y   一共64列
  99.         }
  100.           LCD12864_Write(LCD12864_COM,0xb8+X);  //选择页基地址+X   一共7页  
  101. }
  102. /*****************************************************************************
  103. 函数功能:6*16数值写入函数
  104. 入口参数:X,Y,num,*dat
  105. 说    明:X_横坐标 Y_纵坐标 num_数组的第num个数 *day_需要显示的数组
  106. 版    本:V1.5
  107. 修改时间:2022年7月10日
  108. 新    增:可实现跨左右屏
  109. *****************************************************************************/
  110. void LCD12864_Write_Number(unsigned char X,unsigned char Y,unsigned char num,unsigned char *dat)
  111. {
  112.         unsigned char  i;
  113.   for(i=0;i<6;i++)               
  114.         {
  115.           LCD12864_X_Y(X,Y+i);                          //每写一个字节 更新一次Y 防止不能出现跨屏
  116.                 LCD12864_Write(LCD12864_DATA,dat[num*12+i]);  //写上半字 共写6个字节
  117.         }
  118.   for(i=0;i<6;i++)
  119.         {
  120.           LCD12864_X_Y(X+1,Y+i);                         //同上
  121.                 LCD12864_Write(LCD12864_DATA,dat[num*12+6+i]); //写下半字 共写6个字节
  122.         }
  123. }
  124. /*****************************************************************************
  125. 函数功能:变量显示函数
  126. 入口参数:X,Y,num,len
  127. 说    明:在第X行的第Y个位置显示len个num数值
  128. 版    本:V1.2
  129. 修改时间:2022年7月10日
  130. 新    增:自动计算变量长度 最大计数99999
  131. *****************************************************************************/
  132. void LCD12864_Num(unsigned char X,unsigned char Y,unsigned int num)
  133. {
  134.         unsigned char i;
  135.   unsigned char Len;        
  136.   unsigned char Dis[5];
  137.         unsigned char Buf[5];
  138.         
  139.         sprintf(Buf,"%d",num);   //将数值转换成字符串
  140.         Len=strlen(Buf);         //计算字符串长度
  141.         
  142.   if(Len>4)Dis[Len-5]=num/10000     ;    //若数据更大 按照规律写即可
  143.   if(Len>3)Dis[Len-4]=num%10000/1000;
  144.   if(Len>2)Dis[Len-3]=num%1000/100  ;
  145.   if(Len>1)Dis[Len-2]=num%100/10    ;
  146.   if(Len>0)Dis[Len-1]=num%10        ;
  147.         
  148.   for(i=0;i<Len;i++) LCD12864_Write_Number(X,Y+(i*6),Dis[i],Num);
  149. }

  150. /*****************************************************************************
  151. 函数功能:12*16汉字写入函数
  152. 入口参数:X,Y,num,*dat
  153. 说    明:X_横坐标 Y_纵坐标 num_数组的第num个数 *day_需要显示的数组
  154. 版    本:V1.5
  155. 修改时间:2022年7月10日
  156. 新    增:左右跨屏
  157. *****************************************************************************/
  158. void LCD12864_Write_Chinese(unsigned char X,unsigned char Y,unsigned char num,unsigned char *dat)
  159. {
  160.         unsigned char  i;
  161.   for(i=0;i<12;i++)
  162.         {
  163.                 LCD12864_X_Y(X,Y+i);                         //跨屏重要函数  勿删除
  164.                 LCD12864_Write(LCD12864_DATA,dat[num*24+i]); //写上半字 共写12个字节
  165.         }
  166.   for(i=0;i<12;i++)
  167.         {
  168.           LCD12864_X_Y(X+1,Y+i);                          //同上
  169.                 LCD12864_Write(LCD12864_DATA,dat[num*24+12+i]); //写下半字 共写12个字节
  170.         }
  171. }
  172. /*****************************************************************************
  173. 函数功能:英文字母显示函数
  174. 入口参数:X,Y,*dat
  175. 说    明:X_横坐标 Y_纵坐标 *dat_需要显示的英文字母
  176. 版    本:V1.0
  177. 修改时间:2022年7月10日
  178. 注    明:带字库索引功能
  179. *****************************************************************************/
  180. void LCD12864_Write_English(unsigned char X,unsigned char Y,unsigned char *dat)
  181. {
  182.         unsigned char i,j;
  183.         unsigned char Len;
  184.         
  185.         Len=strlen(dat);        //获取数据长度
  186.                
  187.   for(j=0;j<Len;j++)      
  188.         {
  189.           for(i=0; ;i++)  if(English_Buf[i]==*dat) {dat++; break;}  //查找字库索引列表
  190.           LCD12864_Write_Number(X,Y+(j*6),i,English);               //写数据
  191. ……………………

  192. …………限于本文篇幅 余下代码请从51黑下载附件…………
复制代码

Keil代码与Proteus8.8仿真下载:
12864驱动.7z (51.32 KB, 下载次数: 214)

评分

参与人数 1黑币 +50 收起 理由
admin + 50 共享资料的黑币奖励!

查看全部评分

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏9 分享淘帖 顶 踩
回复

使用道具 举报

来自 2#
ID:293363 发表于 2023-3-20 11:51 | 只看该作者
/*****************************************************************************
函数功能:获取数值长度
入口参数:num
说    明:获取数值数据的长度
版    本:V1.0
修改时间:2023年3月20日
新    增:无
*****************************************************************************/
unsigned char Get_Num_Len(unsigned long num)
{
        unsigned int len = 0; //初始长度为0
        for(; num > 0; ++len) //判断num是否大于0,否则长度+1
        num /= 10;            //使用除法进行运算,直到num小于1
        return len;           //返回长度的值
}
/*****************************************************************************
函数功能:变量显示函数
入口参数:X,Y,num,len
说    明:在第X行的第Y个位置显示len个num数值
版    本:V1.2
修改时间:2022年7月10日
新    增:自动计算变量长度 最大计数99999
*****************************************************************************/
void LCD12864_Num(unsigned char X,unsigned char Y,unsigned long num)
{
        unsigned char i;
  unsigned char Len;       
  unsigned char Dis[5];
       
        Len=Get_Num_Len(num);
       
  if(Len>4)Dis[Len-5]=num/10000     ;    //若数据更大 按照规律写即可
  if(Len>3)Dis[Len-4]=num%10000/1000;
  if(Len>2)Dis[Len-3]=num%1000/100  ;
  if(Len>1)Dis[Len-2]=num%100/10    ;
  if(Len>0)Dis[Len-1]=num%10        ;
       
  for(i=0;i<Len;i++) LCD12864_Write_Number(X,Y+(i*6),Dis[i],Num);
}
回复

使用道具 举报

板凳
ID:582255 发表于 2022-7-11 12:52 | 只看该作者
为什么没有reg。h头文件
回复

使用道具 举报

地板
ID:293363 发表于 2022-7-11 13:35 | 只看该作者
aktuan007 发表于 2022-7-11 12:52
为什么没有reg。h头文件

因为 部分头文件在 12864.h 中引用
回复

使用道具 举报

5#
ID:293363 发表于 2022-7-11 14:12 | 只看该作者
本帖最后由 陈润源home 于 2022-7-11 14:16 编辑

发现一个Bug
/*************************************
函数功能:变量显示函数
入口参数:X,Y,num
*************************************/
这个函数最大只能显示32767
我暂时没找到是什么问题  望各路大佬指导一下

先谢谢各位大佬了
回复

使用道具 举报

6#
ID:582255 发表于 2022-7-12 22:22 | 只看该作者
陈润源home 发表于 2022-7-11 13:35
因为 部分头文件在 12864.h 中引用

谢谢
请教一下为啥我的编译有错误啊
回复

使用道具 举报

7#
ID:293363 发表于 2022-7-14 18:35 | 只看该作者
aktuan007 发表于 2022-7-12 22:22
谢谢
请教一下为啥我的编译有错误啊

你下载附件
回复

使用道具 举报

8#
ID:278457 发表于 2023-3-21 03:16 | 只看该作者
模块化编程,少了很多代码!是故意还是忘记了?
大家都懂的.
回复

使用道具 举报

9#
ID:293363 发表于 2023-5-12 11:54 | 只看该作者
shenqiwei 发表于 2023-3-21 03:16
模块化编程,少了很多代码!是故意还是忘记了?
大家都懂的.

我求求你下载附件后再来评论吧
回复

使用道具 举报

10#
ID:641483 发表于 2023-5-13 11:04 | 只看该作者
谢谢楼主 我先收藏 慢慢来学习
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表