⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 s1620字符型液晶模块驱动程序.txt

📁 ATmega128单片机控制的1602液晶显示程序
💻 TXT
📖 第 1 页 / 共 2 页
字号:
菜鸟学PIC单片机(一):TS1620字符型液晶模块驱动程序编写苦与乐
   小弟学习PIC16F87X系列单片机已持续半个月了,遇到的困难还是比较多的,幸好单位的图书馆里还有一些相关的书籍,加之购买了第三方的ICD,因此学习起来还是比较充实的。
   虽说如此,但在单位里找不到志同道合者一起来琢磨她,不过这里却有许多热心的站友。

   今后,小弟打算将自己的一些学习心得和疑问写出来,与论坛里和我一样的初学者一起进步,并殷切希望能得到前辈的指点,  

   小弟写的第一个程序是控制三位八段数码管的显示,还没来得及总结,今天下午调试和总结了一下LCD的驱动程序,遇到了很多困难,但也有点小小的收获,拿出来晾晾,大家尽管扔砖,小弟开卡车兜着...


    TS1620字符型液晶模块驱动程序编写苦乐

该LCM的控制器为HD47780,其引脚功能如下:

Pin  1    2    3     4   5    6   7~17      15     16
功能 GND VDD   VO   RS   RW   E   DB0~7      BL+    BL-

说明:
RS:数据/命令选择,用来选择DB0~7输入的是显示数据还是控制字信息,(H/L)
RW:读写选择,(H/L),在延迟时间足够的情况下,一般不用读LCM忙信号,常接地。
E: 使能端,控制DB0~7的数据/命令的写入或者读取,上升或下降沿有效。
VO:LCD偏压信号,用来对调整对比度,一般接10K电位器/电阻到地。
DB0~7:数据I/O,可选择8位数据或者4位数据(分两次传输)。
BL+:背光电源正输入 +5V DV。
BL-:背光电源地。
VDD:电源正 +5V DC。
GND:电源地。
编写驱动:
  流程:
上电LCM自动复位—清屏—设置显示模式—开显示和光标设置—设置显示的起始位置—显示字符ASCII码输入显示。
  注意事项:
1.    LCM属于慢显示器件,其上电后复位的时间比较长,因此,可在系统初始化过程中最后初始化LCM;或者在初始化之前调用20~50ms的延迟子程序。并且,如果系统不需要通过延迟来等待LCM完成每一个操作的话,那么应检测(读)LCM忙标志,若不忙(该标志为低电平),那么指令能得到执行,否则指令失效。
2.    由于E输入的使能是上升沿有效还是下降沿有效存在争议,该问题在调试中将遇到,还没来得及分析,愿意与大家一起分析。 
3.    有时候LCM所显示的结果并不遵循我们原来的意愿,此时,需先检查程序中,初始化功能是否完成,尤其是在不检测忙标志的初始化程序中更要注意,可适当延长延迟时间或者重复初始化指令,另外,也要检查硬件连线是否有错。
4.      如果与LCM的引脚相连的端口,需注意该端口是否为普通数字端口,比如本例程中,RA口应先设置成普通数字端口。起初我没有如此设置,结果软件仿真模式下始终发现对RA口的操作均不能从SFR观察窗口中发现任何变化...
5.      由于我所用的DEMO板电路图上,其LCM模块是由RA和RC来控制的,因此,为了能观察运行结果,程序中依然采用RA和RC来控制LCM。


下面给出一个例程,该例程在小弟用的仿真器和DEMO板上通过,同时给出调试现象:

1)关于E的使能的问题,如果对LCM 的E输入脚进行复位置位(先复位或先置位结果均一样)操作时中间的延时过短或者过长的话,均会出现一些问题:
过短:5ms,运行正常,但在debug中复位后,会有部分字符残留
特短:3个nop指令,运行后无任何输出
较长:200ms,运行正常,但debug复位后,所有字符均残留
一般:50ms,显示正常,复位后无字符残留

前辈们能分析一下么?

2)由于采用的显示模式是16字x2行,发现,如果字符表_table1或者_table2中,伪指令dt定义的字符个数如果小于16的话,那么在该行字符的末尾会出现一些其他的字符,小弟这里出现的是 “||”,后用空格填充至16字符具体原因愿意与大家一起分析。

3) 该程序采用ICD模式调试烧写,运行正常之后,小弟打算脱机运行,即不烧入调试代码,但烧写过程老是停在 PROGRAMMING ID处,取消ID烧入,那么烧写过程就停在PROGRAMMING program,并且,ICD 就出现 连接错误的提示,需重新更改ICD模式至SIM模式下,此时发现ICD的连接指示灯不再闪烁,连接正常了。
(可能问题描述得不够准确,下次再重现故障,详细说明...)

4) 另外一个有趣的问题是,PIC16系列的指令系统中应该没有movfw这一指令,但是,在mplab中,却发现,诸如movfw VALUE ;(VALUE为一自定义的寄存器变量)却能通过编译,而且,功能似乎等同 movf VALUE,W  小弟感到纳闷(小弟用的是mplab 5.7full版,该第三方的ICD能直接使用在该版本下..

请前辈指点,如果能谈谈自己这些年来学习PIC单片机所走过的路就更好了:)


;****************************************************
    list        p=16F877    
    #include    <p16F877.inc>    
    
;定义保护现场用寄存器
w_temp        EQU    0x71        
status_temp    EQU    0x72        
pclath_temp    EQU    0x73

;定义主程序用寄存器
count       EQU     0x74          ; 定义计数寄存器地址
tmp1        EQU     0x75           ; 定义临时寄存器地址    
x    EQU    0x76        ; 延时子程序外循环计数器
y    EQU    0x77        ; 延时子程序内循环计数器            

;定义LCM控制位常量
RS         EQU     1        ; LCD寄存器选择信号脚定义在RA.1脚
RW         EQU     2            ; LCD读/写信号脚定义在RA.2脚
E          EQU     3            ; LCD片选信号脚定义在RA.3脚


;***该段e文注释的程序为模板内容
    org     0x000             ; processor reset vector
    nop              ; nop required for icd
      goto    main           ; go to beginning of program

    org     0x004          ; interrupt vector location
    movwf   w_temp        ; save off current W register contents
    movf    STATUS,w     ; move status register into W register
    movwf    status_temp  ; save off contents of STATUS register
    movf    PCLATH,w      ; move pclath register into w register
    movwf    pclath_temp ; save off contents of PCLATH register

; isr code can go here or be located as a call subroutine elsewhere

    movf    pclath_temp,w ; retrieve copy of PCLATH register
    movwf    PCLATH     ; restore pre-isr PCLATH register contents
    movf    status_temp,w&







  本人学习凌阳单片机已经一个多月了,最近在做液晶显示的时候,遇到一些困难,我拿到一个TS1620-1的液晶,
在网上找了一些程序,结果发现都是基于PIC的程序,经过近一天的调试,终于将程序由PIC改成编成凌阳的程序(注:我用的是凌阳61板)。

        根据我调试的结果来看,1620的指令码和1602的指令码应该是一样的,也就是说,要了解1620的指令码可以去查1602的相关资料,
它们的性质基本相同。

      以下提供一些网页链接: http://www.xie-gang.com/yjmk.htm

下面说明一下液晶的硬件连接口:

      (1)GND:接地端;

       (2 )      VCC :电源端 ,接5V电源;

       (3)VO:偏压端:对于1620而言,可以直接接地;

(4)RS:寄存 器选择,高电平时选择数据寄存器、低电平时选择指令寄存器。

(5) RW :       读写判断 ,高 电平时进行读操作,低电平时进行写操作。当RS和RW共同为低电平时可以写入指令或者显示地址,
当RS为低电平RW为高电平时可以读忙信号,当RS为高电平RW为低电平时可以写入数据。

(6)E端为使能端,当E端由高电平跳变成低电平时,液晶模块执行命令。

第7~14脚:D0~D7为8位双向数据线。


(15):BL1:液晶背光电源,接5V

(16):BL2:液晶背光接地端。

第15,16端口只是提供了液晶的背光,与液晶的显示没有任何关系,故可以不接。。


我的凌阳程序只是让液晶在第二行第一列显示一个数字:1

我的IO口是这样定义的:A口与B口均设置成同相低电平输出:

          A口0~7位 依次连接液晶数据口 D0~D7, B口的8位连接RS,10位连接RW,12位连接使能EU端;


具体的程序代码如下:

#include"hardware.h"


void delay1()
{
      int a;
      for(a=0;a<0xffff;a++)
        {
         *Port_Watchdog_Clear=0x0001;
        }   
   
}

void delay2()
{
      int b;
      for(b=0;b<0x00ff;b++)
        {
         *Port_Watchdog_Clear=0x0001;
        }   
   
}

void enable()
{
    
       *Port_IOB_Data&=0xf0ff;                   //RS 置0
       *Port_IOB_Data&=0x0fff;                   //RW置0
       delay2();
       *Port_IOB_Data= *Port_IOB_Data+0x1000;      //使能E置1;
   
} 
  
      int main()

{  
   
       *Port_IOA_Dir=0xffff;
       *Port_IOA_Attrib=0xffff;
       *Port_IOA_Data=0x0000;

       *Port_IOB_Dir=0xffff;
       *Port_IOB_Attrib=0xffff;
       *Port_IOB_Data=0x1000;
   
  
       delay1();

   
       *Port_IOA_Data=0x0001;      //清屏并光标复位
       enable();
       *Port_IOA_Data=0x0038;      //设置显示模式:8位2行5x7点阵
       enable();
       *Port_IOA_Data=0x000f;      //显示器开、光标开、光标允许闪烁
       enable();
       *Port_IOA_Data=0x0080;      //文字不动,光标自动右移
      enable(); 
       *Port_IOA_Data=0x00c2;      //写入显示起始地址(第二行第一个位置)
      enable();
  
       *Port_IOA_Data=0x0031;      // 数字1 的ASSIC码
   
   
       *Port_IOB_Data=*Port_IOB_Data+0x0100;        //RS置1;
       *Port_IOB_Data&=0xfbff;                      //RW置0;
       *Port_IOB_Data&=0xefff;                      // 使能E置0;
       delay2();                       //等待完成;
       *Port_IOB_Data=0x1000;        //将使能E重新置1,等待下次;

    
      while(1)
      {
       *Port_Watchdog_Clear=0x0001;
      }  
   
}













/*
时钟频率11.0592MHz
T0 为时钟基准
T1 为串口产生波特率

*/

/*
中断源            入口地址   C语言

外部中断0          0003 H      0
定时器0 中断       000B H      1
外部中断1          0013 H      2
定时器1 中断       001B H      3
串行口中断         0023 H      4
*/
/*
该LCM的控制器为HD47780,其引脚功能如下:

Pin  1    2    3     4   5    6   7~17      15     16
功能 GND VDD   VO   RS   RW   E   DB0~7     BL+    BL-

说明:
1 GND:电源地。
2 VDD:电源正 +5V DC。
3 VO:LCD偏压信号,用来对调整对比度,一般接10K电位器/电阻到地。
4 RS:数据/命令选择,用来选择DB0~7输入的是显示数据还是控制字信息,(H/L)
5 RW:读写选择,(H/L),在延迟时间足够的情况下,一般不用读LCM忙信号,常接地。
6 E: 使能端,控制DB0~7的数据/命令的写入或者读取,上升或下降沿有效。
7-14 DB0~7:数据I/O,可选择8位数据或者4位数据(分两次传输)。
15 BL+:背光电源正输入 +5V DV。
16 BL-:背光电源地。

*连线图:
* DB0---DPROT.0 DB4---DPROT.4 RS-------------P2.5
* DB1---DPROT.1 DB5---DPROT.5 RW-------------P2.6
* DB2---DPROT.2 DB6---DPROT.6 E--------------P2.7
* DB3---DPROT.3 DB7---DPROT.7 VLCD 接10K 可调电阻到GND*
*/
#include<reg51.h>

#include<absacc.h>
#include <intrins.h>
#define DPORT P0

sbit RS = P2^5;
sbit RW = P2^6;
sbit E  = P2^7;

sbit Add_Key   = P2 ^ 1;//前位加1键
sbit Add2_Key  = P2 ^ 0;//后位加1键
//sbit OK_Key    = P3 ^ 2;//确定键
sbit int_Key   = P2 ^ 3;//中断入口

unsigned Xpos; //列方向地址指针
/*
3,4 Hour
6,7 Minute
9,10 Second
*/
unsigned Ypos; //行方向地址指针

void LcdWcn(unsigned);
void LcdWc(unsigned);
void WriteChar(unsigned);
void LcdPos();
void LcdWd(unsigned);
void LcdWdn(unsigned);

void mDelay(unsigned char Delay)
{ 
 unsigned char i;
 for(;Delay>0;Delay--)
 { 
  for(i=124;i>0;i--)
  {;}
 }
}

/*清屏命令
*/


/*在指定的行与列显示
*/
void WriteChar(unsigned c)
{ 
 LcdPos();
 LcdWd(c);
}

/*正常读写操作之前检测LCD 控制器
*/
void WaitIdle()
{ 
 unsigned tmp;
 DPORT=0xff;
 RS=0;
 RW=1;
 E=1;
 _nop_();
 for(;;)
 { 
  tmp=DPORT;
  tmp&=0x80;
  if(tmp==0)
   break;
 }
 E=0;
}

/*不检测忙的写字符子程序
*/
void LcdWdn(unsigned c)
{

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -