PIC单片机实现LCD1602滚动显示字符串

初始学习单片机,LCD1602的滚动只能实现2行同时移动,就改了哈,写了个滚动的程序。在测试的时候发现了一个问题,在学习板上能正常运行的代码放到Proteus上问题出错,不能正常显示,最后在网上搜索原因时发现可能是Proteus仿真时对端口有要求,最后将商品修改到PORTB和PORTD就正常了。

这是显示效果https://v.youku.com/v_show/id_XNDI5MDEwOTg4NA==.html?spm=a2h3j.8428770.3416059.1

原理图

 

LCD1602.c

//---------------------------------------------------------------
//LCD1602液晶控制与显示程序
//---------------------------------------------------------------

#include <pic.h>
#include <string.h>
#include <stdio.h>
#include "LCD1602.h"

//---------------------------------------------------------------
//LCD忙等待
//---------------------------------------------------------------
void LCD_BUSY_WAIT()
{
    INT8U status;
    TRIS_LCD_DAT=0xFF;                       //将端口设为输入
    RS=0;RW=1;                               //读寄存器状态
    do
    {
        E=1;NOP();status=PORT_LCD_DAT;E=0;   //读取忙信号
    }while(status & 0x80);                   //如果为0x80就是忙,继续进入循环
}

//----------------------------------------------------------------
//写LCD命令
//----------------------------------------------------------------
void Write_LCD_Command(INT8U cmd)
{
    TRIS_LCD_DAT=0x00;                       //LCD数据端口设为输出
    PORT_LCD_DAT=cmd;                        //发送命令
    PORT_LCD_CTL=TRIS_LCD_CTL=0x00;          //控制端口设为输出,初值为0x00
    RS=0;RW=0;E=1;NOP();E=0;                 //写命令
    LCD_BUSY_WAIT();                         //LCD忙等待
}

//----------------------------------------------------------------
//写LCD数据寄存器
//----------------------------------------------------------------
void Write_LCD_Data(INT8U dat)
{
    TRIS_LCD_DAT=0x00;                       //LCD数据端口设为输出
    PORT_LCD_DAT=dat;                        //发送数据
    RS=1;RW=0;E=1;NOP();E=0;                 //写数据
    LCD_BUSY_WAIT();                         //LCD忙等待
}

//----------------------------------------------------------------
//LCD初始化
//----------------------------------------------------------------
void LCD_Initialize()
{
    Write_LCD_Command(0x38);__delay_ms(2);    //置功能,8位,双行,5*7
    Write_LCD_Command(0x01);__delay_ms(2);    //清屏
    Write_LCD_Command(0x06);__delay_ms(2);    //字符进入模式:屏幕不动,字符后移
    Write_LCD_Command(0x0c);__delay_ms(2);    //显示开,关光标
}
//----------------------------------------------------------------
//在r行(0-1) C列(0-15)显示字符串
//----------------------------------------------------------------
void LCD_ShowString(INT8U r,INT8U c,char *str)
{
    INT8U i=0;
    //设置字符地址,第一行首地址为0x80,第二行首地址为0xc0
    if(r==0) Write_LCD_Command(0x80 | c);else
        if(r==1) Write_LCD_Command(0xc0 | c);
    
    //从字符串的第一个字符车起,如果大于16个字符或者碰到'\0'结束
    for(i=0;i<16 && str[i]!='\0';i++)
        Write_LCD_Data(str[i]);                //循环写入字符,地址自动增加
}

//----------------------------------------------------------------
//滚动显示字符串
//----------------------------------------------------------------
void LCD_ScrolShow(INT8U r,INT8U c,char *str)
{
    char tmp[]="                ";            //定义空字符串
    char tmp1[]="                ";
    INT8U k=0;
    INT8U len=strlen(str)-1;                  //字符总长度
    
//  循环显示
    do
    {
        LCD_ShowString(r,c,tmp);
        CopyString(tmp,str,k++);
        __delay_ms(500);
    }while(len--);
    
    //全部显示完后再显示16个空格,实现滚动
    for(k=0;k<16;k++)
    {
        CopyString(tmp,tmp1,k);
        LCD_ShowString(r,c,tmp);
        __delay_ms(500);
    }
}

//-----------------------------------------------------------------
//拷贝字符串来实现滚动 ds目标字符串,ss源字符串,c每次拷贝一个
//-----------------------------------------------------------------
void CopyString(char *ds,char *ss,INT8U c)
{
    INT8U i;
    
    for(i=0;i<16;i++)
    {
        ds[i]=ds[i+1];          //字符依次向前进一个
    }
   
    ds[i-1]=ss[c];             //加入新字符 
    ds[i]='\0';
}

LCD1602.h 

/* 
 * File:   LCD1602.h
 * Author: 5510
 *
 * Created on 2019年7月16日, 下午10:29
 */

#ifndef LCD1602_H
#define	LCD1602_H

#ifdef	__cplusplus
extern "C" {
#endif

#ifdef	__cplusplus
}
#endif

#endif	/* LCD1602_H */

#define INT8U unsigned char
#define INT16U unsigned char
#define _XTAL_FREQ 4000000UL            //定义晶振为4M

#define LCD_CLS           0x01          //清屏
#define LCD_HOME          0x02          //光标移到左上角
#define LCD_SETMODE       0x04
#define LCD_SETVISIBLE    0x08
#define LCD_SHIFT         0x10
#define LCD_SETFUNCTION   0x20
#define LCD_SETCGADDR     0x40
#define LCD_SETDDADDR     0x80

//仿真用端口定义
#define PORT_LCD_DAT      PORTB
#define PORT_LCD_CTL      PORTD
#define TRIS_LCD_DAT      TRISB
#define TRIS_LCD_CTL      TRISD

#define RS    RD0
#define RW    RD1
#define E     RD2

//开发板端口定义
//#define PORT_LCD_DAT      PORTD
//#define PORT_LCD_CTL      PORTB
//#define TRIS_LCD_DAT      TRISD
//#define TRIS_LCD_CTL      TRISB
//
//#define RS    RB5
//#define RW    RB4
//#define E     RB3

void LCD_Initialize();
void LCD_BUSY_WAIT();
void Write_LCD_Command(INT8U data);
void Write_LCD_Data(INT8U data);
void LCD_ShowString(INT8U r,INT8U c,char *str);
void LCD_ScrolShow(INT8U r,INT8U c,char *str);
void CopyString(char *ds,char *ss,INT8U c);

main.c 

/* 
 * 文件:   main.c
 * 编写:   金伟
 * 用途:   LCD1602测试程序
 * 时间:   2019年7月16日, 下午10:56
 */

// PIC16LF877A Configuration Bit Settings

// 'C' source line config statements

// CONFIG
#pragma config FOSC = XT        // Oscillator Selection bits (XT oscillator)
#pragma config WDTE = OFF       // Watchdog Timer Enable bit (WDT disabled)
#pragma config PWRTE = OFF      // Power-up Timer Enable bit (PWRT disabled)
#pragma config BOREN = ON       // Brown-out Reset Enable bit (BOR enabled)
#pragma config LVP = OFF        // Low-Voltage (Single-Supply) In-Circuit Serial Programming Enable bit (RB3 is digital I/O, HV on MCLR must be used for programming)
#pragma config CPD = OFF        // Data EEPROM Memory Code Protection bit (Data EEPROM code protection off)
#pragma config WRT = OFF        // Flash Program Memory Write Enable bits (Write protection off; all program memory may be written to by EECON control)
#pragma config CP = OFF         // Flash Program Memory Code Protection bit (Code protection off)

// #pragma config statements should precede project file includes.
// Use project enums instead of #define for ON and OFF.

#include <pic.h>
#include "LCD1602.h"

//显示的字符串
const char demo[]="----LCD DEMO----";            
const char tel[]="Welcome To PIC World  TEL:18627238500";
const char tel1[]="apple inc";
const char tel2[]="HUAWEI P10";

void main()
{
    LCD_Initialize();
    LCD_ShowString(0,0,demo);
    
//    LCD_ShowString(0,0,(char*)"----LCD DEMO----");
    
    while(1)
    {
        LCD_ScrolShow(1,0,tel);
        LCD_ScrolShow(1,0,tel1);
        LCD_ScrolShow(1,0,tel2);
    }
}

 

  • 3
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值