EDN首页   博客首页

2

关于投票
搞定了用51控制1602CLCD模块

    前两天忙里偷闲(一直在复习考研),从同学那里搞了个1602C LCD玩,费了点事,但终于搞好了。心情愉快啊,呵呵!
    程序真的不难,网上资料也挺多的。不过没有经验的话,可能也要搞上一会儿。
    在51上编程不方便在于,程序运行没有什么显示,不能像在Dos/Windows下可以在程序里面加上一些调试的代码——特别是加了外电路以后,没有示波器这类东东,有时候操作1602C的时序不对,LCD就没有反应,很让人头疼!



    这里有几份网上的关于1602C的资料,如果有需要可以下载来看看

pdf这个资料不错,它上面有讲1602C的启动过程,不过代码是用AVR的C语言写的

zip这是网上的一份比较常见的资料,后面有用51汇编写的程序,完全可以使用!
zip这是一份英文资料,上面有讲如何使用一个174移位寄存器来实现用只使用三条或两条引脚来驱动LCD。他用的Hitachi 44780和我们的1602C基本是一样的。


电路很简单,按照网上给的接法自己找个51的端口接好就行了。

我使用的是现成的一个51学习板(使用的AT89S52),又引出了几个端口。

我没有把端口引线和LCD焊到一起。原来用面包板作为媒介,但它的接触不可靠;后来用了一个排针的插口加上一个40针的引脚(原来打算自己焊一个51的最小系统板时做的),这才连接可靠。

点击看大图

点击看大图



下面是我写的程序(在KeilC下使用MCS-51汇编编写):
;一个简单的1602C LCD的驱动
;程序实现了在LCD的第一行第一个字符位置开始显示“Hello World”字符串
;R7被用作WRITE_STRING过程的计数器,没有作现场保护

;V0 EQU P3.4,后来直接接低电平(对比度最高)了,就没再用
RS EQU P3.5
;低电平发送指令,高电平发送数据
RW EQU P3.6
;低电平写数据,高电平读状态
E  EQU P3.7

LCD_PORT EQU P0
;我把LCD的数据口接到了P0上了
BF EQU LCD_PORT.7
;忙标志位,但我没有判断标志位成功,所以还没有用
STRING: DB 'Hello World!',0
;作为要显示的数据
              ORG 0000H
START:   
              ACALL INIT_LCD
;初始化
              MOV A,#0H
              ACALL SEND_ADDR
;通过A寄存器发送位置地址,00h是第一行第一个字符位置
             ACALL WRITE_STRING
;写字符串,直接读取STRING,到0停止
             SETB RW
             AJMP $

;************************************
WRITE_STRING:
;Output a String which defined in STRING
;*************************************
;   PUSH AR7
           MOV DPTR,#STRING
           MOV R7,#00
WRITE_STRING_LOOP:
           MOV A,R7
           MOVC A,@A+DPTR
           JZ WRITE_STRING_END
;如果ACC==0, 说明字符串完了,则停止循环
           ACALL WRITE_TEXT
           INC R7
           JNZ WRITE_STRING_LOOP
WRITE_STRING_END:
;    POP AR7
           RET
;************************************
EXECCMD:
;Execute an Instruction
;************************************
           CLR RS
           CLR RW
           CLR E
;E由高到低——下降沿,执行指令
           ACALL DELAY
           SETB E
;后面的测试代码没有成功
;    ACALL DELAY
;    SETB E
;    SETB RW
;EXECCMD_TEST_BF:
;    MOV LCD_PORT,#0FFH
;    CLR E
;    NOP
;    SETB E
;    JB BF,EXECCMD
           RET
;*************************************
WRITE_TEXT:
;USE Register A TO TRANSMIT CHARS
;发送要显示的数据
;*************************************
           SETB RS
;RW is default to 0
;    CLR RW
           MOV LCD_PORT,A
           CLR E
           ACALL DELAY
           SETB E
           CLR RS
           RET
;*************************************
INIT_LCD:
;INITIALIZING LCD MODULE
;初始化LCD模块
;*************************************
    ;应该等待至少15毫秒
           ACALL DELAY
           SETB E
           CLR RS;
           CLR RW;
;          SETB V0

;这部分是许多文章上建议的附加的启动过程,但我试了,
;不加也是可以的——可能是为了防止高速芯片初始化错误吧
;Optional{
;    MOV LCD_PORT,#38H
;    ACALL EXECCMD
;    ACALL DELAY
;    MOV LCD_PORT,#38H
;    ACALL EXECCMD
;    ACALL DELAY
;    MOV LCD_PORT,#38H
;    ACALL EXECCMD
;    ACALL DELAY
;}
    ;SET DISPLAY MODE
    ;设置显示模式
           ACALL CLEAR_LCD;MOV LCD_PORT,#01H
           MOV LCD_PORT,#00111000B;#38H
           ACALL EXECCMD

;Optional{可加可不加
;    MOV LCD_PORT,#08H;Turn off the Display
;    ACALL EXECCMD
;}   
    ;CURSOR RETURNS TO HOME
    ;光标回到初始位置
           MOV LCD_PORT,#02H;#0000 0010B
           ACALL EXECCMD

    ;光标每次自动向右移位
           MOV LCD_PORT,#06H;#00000110B
           ACALL EXECCMD

    ;DISPLAY ON,CURSOR OFF
    ;显示开,不显示光标
           MOV LCD_PORT,#0CH ;#00001100B
           ACALL EXECCMD
       
    ACALL CLEAR_LCD;MOV LCD_PORT,#01H
           RET
;*************************************
SEND_ADDR:
;发送光标地址
;*************************************
           ORL A,#80H;OR 1000 0000B,地址的最高位必须为1
           MOV LCD_PORT,A
           ACALL EXECCMD
           RET
;*************************************
CLEAR_LCD:
;CLEAR LCD
;LCD清屏
;*************************************
           MOV LCD_PORT,#01H
           ACALL EXECCMD
           RET
DELAY:
    MOV R6,#064H
;100*200*1us=20ms,我使用的是20Mhz的晶振
DELAY_1:
    MOV R5,#0C8H
DELAY_2:
    DJNZ R5,DELAY_2
    DJNZ R6,DELAY_1
    RET

END

系统分类: 单片机
用户分类: 8051
标签: 无标签
来源: 原创
发表评论 阅读全文(2064) | 回复(3)
总共 , 当前 /