找回密码
 立即注册

QQ登录

只需一步,快速开始

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

液晶MINI12864串行接口的单片机源码(不带字库)

[复制链接]
跳转到指定楼层
楼主
ID:325553 发表于 2018-5-8 22:35 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
串行LCD12864程序 验证过可用

单片机源程序如下:
  1. /****************************************************************
  2. 通用头文件
  3. ****************************************************************/
  4. #include <reg52.h>
  5. #include <intrins.h>
  6. #include "i2c.h"
  7. #define MAIN_Fosc                11059200UL        //宏定义主时钟HZ

  8. /****************************************************************
  9. 已有数据类型重新定义
  10. ****************************************************************/
  11. typedef signed char int8;  //8位有符号型
  12. typedef unsigned char INT8U;
  13. typedef signed int  int16; //16位有符号型
  14. typedef unsigned char uint8;  //8位无符号型
  15. typedef unsigned char uchar;  //8位无符号型
  16. typedef unsigned int  uint16; //16位无符号型
  17. typedef unsigned int INT16U;
  18. typedef unsigned int  uint; //16位无符号型
  19. typedef unsigned long uint32; //32位无符号型

  20. /****************************************************************
  21. 硬件接口定义
  22. ****************************************************************/
  23. /*LCD12864液晶引脚*/
  24. sbit LCD12864_CS = P0^3;        //片选使能脚, L:使能片选
  25. sbit LCD12864_RST= P0^4;        //系统复位选择脚
  26. sbit LCD12864_RS = P0^5;        //命令/数据选择脚,L:命令 H:数据
  27. sbit LCD12864_SCL= P0^6;        //命令/数据选择脚,L:命令 H:数据
  28. sbit LCD12864_SDA= P0^7;        //串行数据输入/输出脚

  29. /*数码管*/
  30. sbit WE = P2^7;        //数码管位选        
  31. sbit DU = P2^6;        //数码管段选

  32. sbit LED=P1^7;
  33. sbit beep=P2^3;         //蜂鸣器引脚定义
  34. sbit FUN=P2^2;//风扇引脚定义           风扇接 + D 通过4IN接到P22控制
  35. uchar code ascii_table_8x16[95][16]; //8*16字符
  36. uchar code ascii_table_5x7[95][5];        //5*7字符
  37. //PCF
  38. #define AddWr 0x90   //写数据地址
  39. #define AddRd 0x91   //读数据地址

  40. extern bit ack;
  41. bit ReadADFlag;

  42. uchar MQ[4];

  43. unsigned char dispos;//设置指针
  44. unsigned char setflag;//设置标志位

  45. unsigned char Q4H,Q4L,Q6H,Q6L,Q7H,Q7L;


  46. unsigned char ReadADC(unsigned char Chl);//读取对应通道的ADC值函数声明

  47. /*------------------------------------------------
  48.              读AD转值程序
  49. 输入参数 Chl 表示需要转换的通道,范围从0-3
  50. 返回值范围0-255
  51. ------------------------------------------------*/
  52. unsigned char ReadADC(unsigned char Chl)
  53. {
  54.           unsigned char Val;
  55.            Start_I2c();               //启动总线
  56.            SendByte(AddWr);             //发送器件地址
  57.              if(ack==0)return(0);
  58.            SendByte(Chl);            //发送器件子地址
  59.              if(ack==0)return(0);
  60.            Start_I2c();
  61.            SendByte(AddRd);
  62.               if(ack==0)return(0);
  63.            Val=RcvByte();
  64.            NoAck_I2c();                 //发送非应位
  65.            Stop_I2c();                  //结束总线
  66.           return(Val);
  67. }

  68. /*====================================
  69. 函数名        :void delay(INT16U ms)
  70. 参数        :ms,毫秒延时形参
  71. 返回值        :无
  72. 描述        :12T 51单片机自适应主时钟毫秒级延时函数
  73. ====================================*/
  74. void delay(INT16U ms)
  75. {
  76.      INT16U i;
  77.          do{
  78.               i = MAIN_Fosc / 96000;
  79.                   while(--i);   //96T per loop
  80.      }while(--ms);
  81. }
  82. /*====================================
  83. 函数        :LcdSendCmd(uchar DAT)
  84. 参数        :DAT需要发送的命令
  85. 返回值        :无
  86. 描述        :mini12864发送命令
  87. ====================================*/
  88. void LcdSendCmd(uchar DAT)
  89. {
  90.         uchar i;
  91.         LCD12864_CS = 0;        //片选使能脚, L:使能片选
  92.         LCD12864_RS = 0; //命令/数据选择脚,L:命令 H:数据
  93.         for(i=0; i<8; i++) //分别写8次,每次写1位
  94.         {
  95.                 LCD12864_SCL = 0;//拉低时钟总线,允许SDA变化
  96.                 if(DAT & 0x80)//先写数据最高位
  97.                         LCD12864_SDA = 1;  //写1
  98.                 else
  99.                         LCD12864_SDA = 0;  //写0
  100.                 LCD12864_SCL = 1;          //拉高时钟,让从机读SDA
  101.                 DAT <<= 1;          //为发送下一位左移1位
  102.         }
  103. }

  104. /*====================================
  105. 函数        :LcdSendData(uchar DAT)
  106. 参数        :DAT需要发送的数据
  107. 返回值        :无
  108. 描述        :mini12864发送数据
  109. ====================================*/
  110. void LcdSendData(uchar DAT)
  111. {
  112.         uchar i;
  113.         LCD12864_CS = 0;        //片选使能脚, L:使能片选
  114.         LCD12864_RS = 1; //命令/数据选择脚,L:命令 H:数据
  115.         for(i=0; i<8; i++) //分别写8次,每次写1位
  116.         {
  117.                 LCD12864_SCL = 0;//拉低时钟总线,允许SDA变化
  118.                 if(DAT & 0x80)//先写数据最高位
  119.                         LCD12864_SDA = 1;  //写1
  120.                 else
  121.                         LCD12864_SDA = 0;  //写0
  122.                 LCD12864_SCL = 1;          //拉高时钟,让从机读SDA
  123.                 DAT <<= 1;          //为发送下一位左移1位
  124.         }
  125. }
  126. /*====================================
  127. 函数        :LcdAddr
  128. 参数        :page设置显示页地址,column设置显示列地址
  129. 返回值        :无
  130. 描述        :mini12864显示数据地址
  131. ====================================*/
  132. void LcdAddr(uchar page, uchar column)
  133. {
  134.         LCD12864_CS = 0;        //使能片选
  135.         column = column - 1; //我们平常所说的第1 列,在LCD 驱动IC 里是第0 列。所以在这里减去1.
  136.         /*设置页地址。每页是8 行。一个画面的64 行被分成8 个页。我们平常所说的第1 页,
  137.         在LCD 驱动IC 里是第0 页,所以在这里减去1*/
  138.         page = page - 1;
  139.         LcdSendCmd(0xb0+page); //设置页地址
  140.         LcdSendCmd( ( (column >> 4) & 0x0f ) + 0x10 );//设置列地址的高4 位
  141.         LcdSendCmd(column & 0x0f);//设置列地址的低4 位        
  142. }

  143. /*====================================
  144. 函数        :LcdCls
  145. 函数        :Disp_Picture
  146. 参数        :page显示区页地址,column显示区行地址,x清除显示区域宽,y清除显示区域高
  147. 描述        :mini12864清屏
  148. ====================================*/
  149. void LcdCls(uchar page, uchar column,uchar x,uchar y)
  150. {
  151.         uchar i,j;
  152.         LCD12864_CS = 0;        //使能片选
  153.         y = y / 8;//页设置
  154.         for(j=0; j<y; j++)
  155.         {
  156.                 LcdAddr(page+j, column);
  157.                 for (i=0; i<x; i++)
  158.                 {
  159.                         LcdSendData(0); /*写数据到LCD,每写完一个8 位的数据后列地址自动加1*/
  160.                 }
  161.         }
  162.         LCD12864_CS = 1;        //片选关闭
  163. }

  164. /*====================================
  165. 函数        :Disp_16x16
  166. 参数        :page显示页地址,column显示行地址, dp显示内容
  167. 返回值        :无
  168. 描述        :mini12864显示16x16 点阵图像、汉字、生僻字或16x16 点阵的其他图标
  169.                         显示坐标设置说明16*16的字体占16行16列  对应占2页 16列
  170. ====================================*/
  171. void Disp_16x16(uchar page, uchar column, uchar *dp)
  172. {
  173.         uchar i,j;
  174.         LCD12864_CS = 0;        //使能片选
  175.         for(j=0; j<2; j++)
  176.         {
  177.                 LcdAddr(page+j, column);
  178.                 for (i=0; i<16; i++)
  179.                 {
  180.                         LcdSendData(*dp); /*写数据到LCD,每写完一个8 位的数据后列地址自动加1*/
  181.                         dp++;
  182.                 }
  183.         }
  184.         LCD12864_CS = 1;        //片选关闭
  185. }
  186. /*====================================
  187. 函数        :Disp_String_8x16
  188. 参数        :page显示页地址,column显示行地址, text显示内容
  189. 返回值        :无
  190. 描述        :mini12864显示8x16 数字,字符或8x16 点阵的其他图标
  191.                         显示坐标设置说明8*16的字体占8行16列  对应占1页 16列
  192. ====================================*/
  193. void Disp_String_8x16(uchar page, uchar column, uchar *text)
  194. {
  195.         uint i=0,j,k,n;
  196.         LCD12864_CS = 0;        //使能片选
  197.         while(text[i]>0x00)
  198.         {
  199.                 if((text[i]>=0x20)&&(text[i]<=0x7e))
  200.                 {
  201.                         j=text[i]-0x20;
  202.                         for(n=0;n<2;n++)
  203.                         {
  204.                                 LcdAddr(page+n, column);
  205.                                 for(k=0;k<8;k++)
  206.                                 {
  207.                                         LcdSendData(ascii_table_8x16[j][k+8*n]);/*显示8x16 的ASCII 字到LCD 上*/
  208.                                 }
  209.                         }
  210.                         i++;
  211.                         column+=8;
  212.                 }
  213.                 else
  214.                         i++;
  215.         }
  216.         LCD12864_CS = 1;        //片选关闭
  217. }

  218. /*====================================
  219. 函数        :Disp_String_5x7
  220. 参数        :page显示页地址,column显示行地址, text显示内容
  221. 返回值        :无
  222. 描述        :mini12864显示5x7 数字,字符或5x7 点阵的其他图标
  223.                         显示坐标设置说明5*7的字体占5行7列  对应占1页 7列
  224. ====================================*/
  225. void Disp_String_5x7(uchar page, uchar column, uchar *text)
  226. {
  227.         uint i=0,j,k;
  228.         LCD12864_CS = 0;        //使能片选
  229.         while(text[i]>0x00)
  230.         {
  231.                 if((text[i]>=0x20)&&(text[i]<0x7e))
  232.                 {
  233.                         j=text[i]-0x20;
  234.                         LcdAddr(page, column);
  235.                         for(k=0;k<5;k++)
  236.                         {
  237.                                 LcdSendData(ascii_table_5x7[j][k]);/*显示5x7 的ASCII 字到LCD 上*/
  238.                         }
  239.                         i++;
  240.                         column+=6;
  241.                 }
  242.                 else
  243.                 i++;
  244.         }
  245.         LCD12864_CS = 1;        //片选关闭
  246. }

  247. /*====================================
  248. 函数        :Disp_Picture
  249. 参数        :page显示页地址,column显示行地址,x图片宽,y图片高, dp显示内容
  250. 返回值        :无
  251. 描述        :mini12864显示图片
  252. ====================================*/
  253. void Disp_Picture(uchar page, uchar column,uchar x,uchar y, uchar *dp)
  254. {
  255.         uchar i,j;
  256.         LCD12864_CS = 0;        //使能片选
  257.         y = y / 8;//页设置
  258.         for(j=0; j<y; j++)
  259.         {
  260.                 LcdAddr(page+j, column);
  261.                 for (i=0; i<x; i++)
  262.                 {
  263.                         LcdSendData(*dp); /*写数据到LCD,每写完一个8 位的数据后列地址自动加1*/
  264.                         dp++;
  265.                 }
  266.         }
  267.         LCD12864_CS = 1;        //片选关闭
  268. }

  269. /*====================================
  270. 函数        :InitLcd()
  271. 参数        :无
  272. 返回值        :无
  273. 描述        :mini12864初始化
  274. ====================================*/
  275. void InitLcd()
  276. {
  277.         LCD12864_CS = 0;        //使能片选
  278.         LCD12864_RST= 0;        //系统复位
  279.         delay(1);
  280.         LCD12864_RST= 1; //系统复位完成
  281.         delay(1);
  282.         LcdSendCmd(0xe2);        //软件复位,执行这条指令之后,电路进入软件复位状态,各寄存器值详见复位状态寄存器表。
  283.         LcdSendCmd(0x2f);        //为液晶屏升压,提供所需电压
  284.         LcdSendCmd(0x23);        //粗调对比度,可设置范围0x20~0x27
  285.         LcdSendCmd(0x81);        //双行指令 设置EV微调对比度的值
  286.         LcdSendCmd(0x2f);        //EV可设置范围0x00~0x3f
  287.         LcdSendCmd(0xa2);        //1/9 偏压比(bias)全屏显示
  288.         LcdSendCmd(0xc8);        //行扫描顺序:从上到下
  289.         LcdSendCmd(0xa0);   //列扫描顺序:从左到右
  290.         LcdSendCmd(0x40);        //起始行:第一行开始
  291.         LcdSendCmd(0xaf);        //开显示
  292.         LCD12864_CS = 1;        //片选关闭                        
  293. }


  294. void keyfun(void)   //键盘扫描
  295. {
  296.                     unsigned char key;
  297.                          key = P3&0X0F;        //按键扫描
  298.                          if(key != 0X0F)
  299.                          {                 LED=0;
  300.                                         delay(10);                //去抖动
  301.                                  
  302.                                         if(key == 0X0e)  //加键
  303.                                         {
  304.                                                 switch (dispos)
  305.                                                 {
  306.                                                         case 0:        if(Q4H<250)Q4H=Q4H+10;else Q4H=255;        break;
  307.                                                 
  308.                                                         case 1:        if(Q6H<250)Q6H=Q6H+10;else Q6H=255; break;
  309.                                                         
  310.                                                         case 2:        if(Q7H<250)Q7H=Q7H+10;else Q7H=255;        break;
  311.                                                         
  312.                                                         default:break;

  313.                                                 }

  314.                                         }else if(key == 0X0d) //减键
  315.                                         {
  316.                                                    switch (dispos)
  317.                                                 {
  318.                                                         case 0:        if(Q4H>30)Q4H=Q4H-10;else Q4H=20;        break;
  319.                                                 
  320.                                                         case 1:        if(Q6H>130)Q6H=Q6H-10;else Q6H=128; break;
  321.                                                 
  322.                                                         case 2:        if(Q7H>130)Q7H=Q7H-10;else Q7H=128;        break;
  323.                                                         
  324.                                                         default:break;

  325.                                                 }
  326.                                         }
  327.                                         else if(key == 0X0b)  //选择设置位
  328.                                         {
  329.                                                         dispos++;
  330.                                                         dispos=dispos%3;
  331.                                         }
  332.                                         //else if(key == 0X08)  //选择设置位
  333.                                 //        {
  334.                                 //                        dispos--;
  335.                                 //                        dispos=dispos%3;
  336.                                 //        }
  337.                                         while((P3&0X0F) != 0X0F);  //等待按键释放
  338.                                          LED=1;
  339.                          }        
  340. }
  341.   /*------------------------------------------------
  342.                     定时器初始化子程序
  343. ------------------------------------------------*/
  344. void Init_Timer0(void)
  345. {
  346.          TMOD |= 0x01;          //使用模式1,16位定时器,使用"|"符号可以在使用多个定时器时不受影响                     
  347.          EA=1;            //总中断打开
  348.          ET0=1;           //定时器中断打开
  349.          TR0=1;           //定时器开关打开
  350. }

  351. void main()
  352. {
  353.     unsigned char num=0;
  354.         unsigned char error=0;
  355.         P0 = 0XFF;
  356.         WE = 1;
  357.         WE = 0;//关闭数码管显示
  358.         InitLcd();//mini12864初始化
  359.         LcdCls( 1, 1, 128, 64); //清屏指定区域
  360.         Disp_String_5x7( 1, 5, "Gas detection system");
  361.         Disp_String_5x7( 4, 1, "MQ4:");//显示5*7字符
  362.         Disp_String_5x7( 6, 1, "MQ6:");//显示5*7字符
  363.         Disp_String_5x7( 8, 1, "MQ7:");//显示5*7字符
  364.         Disp_String_5x7( 4, 55, "ppm");//显示5*7字符
  365.         Disp_String_5x7( 6, 55, "ppm");//显示5*7字符
  366.         Disp_String_5x7( 8, 55, "ppm");//显示5*7字符
  367.         Disp_String_5x7( 4, 112, "ppm");//显示5*7字符
  368.         Disp_String_5x7( 6, 112, "ppm");//显示5*7字符
  369.         Disp_String_5x7( 8, 112, "ppm");//显示5*7字符

  370.         Disp_String_5x7( 2, 34, "real");//显示5*7字符
  371.         Disp_String_5x7( 2, 90, "set");//显示5*7字符
  372.                
  373.         Init_Timer0();
  374.         Q4H=50;        //阈值初始值

  375.         Q6H=150;

  376.         Q7H=150;

  377.         beep=1;
  378.         FUN=0;
  379.         while(1)
  380.         {         
  381.            keyfun() ;
  382.            if(ReadADFlag==1) //定时AD采样和屏幕扫描
  383.            {
  384.                 ReadADFlag=0;
  385.                     num=ReadADC(0);
  386.                         if(num<Q4H) //在范围内
  387.                             error=error&0Xfe;
  388.                         else
  389.                                 error=error|0X01;
  390.                         MQ[0]=        0X30+num/100;
  391.                         MQ[1]=        0X30+num%100/10;
  392.                         MQ[2]=        0X30+num%10;
  393.                         MQ[3]=        '\0';
  394.                         Disp_String_5x7( 4, 34, MQ);//显示5*7字符
  395.                         //delay(10);//延时
  396.                         num=ReadADC(1);
  397.                         if(num<Q6H)
  398.                            error=error&0XfD;        
  399.                         else
  400.                            error=error|0X02;
  401.                         MQ[0]=        0X30+num/100;
  402.                         MQ[1]=        0X30+num%100/10;
  403.                         MQ[2]=        0X30+num%10;
  404.                         MQ[3]=        '\0';
  405.                
  406.                         Disp_String_5x7( 6, 34, MQ);//显示5*7字符
  407.                         //delay(10);//延时
  408.                         num=ReadADC(2);
  409.                         if(num<Q7H)
  410.                                    error=error&0XfB;
  411.                         else  
  412.                                 error=error|0X04;
  413.                         MQ[0]=        0X30+num/100;
  414.                         MQ[1]=        0X30+num%100/10;
  415.                         MQ[2]=        0X30+num%10;
  416.                         MQ[3]=        '\0';

  417.                         Disp_String_5x7( 8, 34, MQ);//显示5*7字符
  418.                         delay(10);//延时
  419.                         
  420.                         /////////////////////////////////////
  421.                

  422.                         MQ[0]=        0X30+Q4H/100;
  423.                         MQ[1]=        0X30+Q4H%100/10;
  424.                         MQ[2]=        0X30+Q4H%10;
  425.                         MQ[3]=        '\0';
  426.                         Disp_String_5x7( 4, 90, MQ);//显示5*7字符
  427.                 //        delay(10);//延时

  428.                         MQ[0]=        0X30+Q6H/100;
  429.                         MQ[1]=        0X30+Q6H%100/10;
  430.                         MQ[2]=        0X30+Q6H%10;
  431.                         MQ[3]=        '\0';
  432.                         Disp_String_5x7( 6, 90, MQ);//显示5*7字符
  433.                         //delay(10);//延时

  434.                         MQ[0]=        0X30+Q7H/100;
  435.                         MQ[1]=        0X30+Q7H%100/10;
  436.                         MQ[2]=        0X30+Q7H%10;
  437.                         MQ[3]=        '\0';
  438.                         Disp_String_5x7( 8, 90, MQ);//显示5*7字符
  439.                         //delay(10);//延时
  440.                 }
  441.                     if((error&0x07)!=0)
  442.                          {
  443.                                  beep=0;// 开蜂鸣器
  444.                                 FUN=1;//开风扇
  445.                          }else
  446.                          {
  447.                                  beep=1;// 关蜂鸣器
  448.                                 FUN=0; //关风扇
  449.                          }

  450.         }
  451. }




  452. /*------------------------------------------------
  453.                  定时器中断子程序
  454. ------------------------------------------------*/
  455. void Timer0_isr(void) interrupt 1
  456. {
  457.          static unsigned int count;
  458.          TH0=(65536-2000)/256;                  //重新赋值 2ms
  459.          TL0=(65536-2000)%256;
  460.          
  461.          count++;
  462.          if(count==50)        //大致100ms
  463.            {
  464.             count=0;
  465.             ReadADFlag=1; //读标志位置1
  466.                 }
  467. }


  468. uchar code ascii_table_5x7[95][5]={
  469. /*全体ASCII 列表:5x8 点阵*/
  470. 0x00,0x00,0x00,0x00,0x00,//- - //space
  471. 0x00,0x00,0x4f,0x00,0x00,//-!-
  472. 0x00,0x07,0x00,0x07,0x00,//-"-
  473. 0x14,0x7f,0x14,0x7f,0x14,//-#-
  474. 0x24,0x2a,0x7f,0x2a,0x12,//-$-
  475. 0x23,0x13,0x08,0x64,0x62,//-%-
  476. 0x36,0x49,0x55,0x22,0x50,//-&-
  477. 0x00,0x05,0x07,0x00,0x00,//-'-
  478. 0x00,0x1c,0x22,0x41,0x00,//-(-
  479. 0x00,0x41,0x22,0x1c,0x00,//-)-
  480. 0x14,0x08,0x3e,0x08,0x14,//-*-
  481. 0x08,0x08,0x3e,0x08,0x08,//-+-
  482. 0x00,0x50,0x30,0x00,0x00,//-,-
  483. 0x08,0x08,0x08,0x08,0x08,//---
  484. 0x00,0x60,0x60,0x00,0x00,//-.-
  485. 0x20,0x10,0x08,0x04,0x02,//-/-
  486. 0x3e,0x51,0x49,0x45,0x3e,//-0-
  487. 0x00,0x42,0x7f,0x40,0x00,//-1-
  488. 0x42,0x61,0x51,0x49,0x46,//-2-
  489. 0x21,0x41,0x45,0x4b,0x31,//-3-
  490. 0x18,0x14,0x12,0x7f,0x10,//-4-
  491. 0x27,0x45,0x45,0x45,0x39,//-5-
  492. 0x3c,0x4a,0x49,0x49,0x30,//-6-
  493. 0x01,0x71,0x09,0x05,0x03,//-7-
  494. 0x36,0x49,0x49,0x49,0x36,//-8-
  495. 0x06,0x49,0x49,0x29,0x1e,//-9-
  496. 0x00,0x36,0x36,0x00,0x00,//-:-
  497. 0x00,0x56,0x36,0x00,0x00,//-;-
  498. 0x08,0x14,0x22,0x41,0x00,//-<-
  499. 0x14,0x14,0x14,0x14,0x14,//-=-
  500. 0x00,0x41,0x22,0x14,0x08,//->-
  501. 0x02,0x01,0x51,0x09,0x06,//-?-
  502. 0x32,0x49,0x79,0x41,0x3e,//-@-
  503. ……………………

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

所有资料51hei提供下载:
1、MINI12864测试程序.rar (57.11 KB, 下载次数: 47)


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

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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