历史上的今天
返回首页

历史上的今天

今天是:2025年01月23日(星期四)

正在发生

2020年01月23日 | PIC单片机实现LCD1602滚动显示字符串

2020-01-23 来源:eefocus

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


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

原理图

LCD1602.c


//---------------------------------------------------------------

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

//---------------------------------------------------------------

 

#include

#include

#include

#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个字符或者碰到''结束

    for(i=0;i<16 && str[i]!='';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]='';

}

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

#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);

    }

}

推荐阅读

史海拾趣

GE公司的发展小趣事

对于光电控制电子生日蛋糕电路,网友可能提出多种问题。以下是一些可能的问题及其详细回答:

1. 光电控制电子生日蛋糕电路的基本工作原理是什么?

回答:光电控制电子生日蛋糕电路通常由一个光敏二极管(如VD1)、一个控制电路(如IC1,常为555时基集成电路或音乐芯片)以及其他外围元器件组成。当蜡烛被点燃并照射到光敏二极管上时,光敏二极管的电阻会发生变化,导致控制电路中的电压改变。这一电压变化进而触发控制电路,使其输出控制信号,驱动音乐芯片工作并输出音乐信号(如“祝你生日快乐”),同时可能还驱动发光二极管等元件闪烁,增加节日气氛。

2. 如何选择合适的元器件来构建这个电路?

回答:选择合适的元器件是构建光电控制电子生日蛋糕电路的关键。光敏二极管应选择灵敏度适中、响应速度快的型号;控制电路可以选择555时基集成电路或专用的音乐芯片,具体取决于电路设计的复杂度和功能需求;发光二极管可以选择高亮度、颜色鲜艳的型号以增强视觉效果;此外,还需要根据电路设计选择合适的电阻、电容等元器件。

3. 这个电路存在哪些安全隐患,如何避免?

回答:虽然光电控制电子生日蛋糕电路本身在正常情况下是安全的,但如果不当使用或制作过程中存在瑕疵,仍可能带来安全隐患。例如,电路中的电池如果处理不当,可能会导致电池液泄漏或短路;电子元件过热也可能引发火灾等。为了避免这些安全隐患,应确保电池安装牢固、电路连接正确无误;在使用过程中避免长时间连续工作,以防过热;同时,应让儿童在成人监护下使用此类电子生日蛋糕。

4. 如何调试和优化这个电路的性能?

回答:调试和优化光电控制电子生日蛋糕电路的性能可以通过以下步骤进行:首先检查电路连接是否正确无误;然后逐步测试各个元器件的功能是否正常;接着调整光敏二极管的灵敏度、控制电路的输出电压等参数以优化电路性能;最后在实际使用环境中进行整体测试,确保电路能够稳定可靠地工作。在调试过程中可以使用万用表等测试工具来监测电路中的电压、电流等参数变化。

5. 除了音乐和发光效果外,这个电路还可以实现哪些功能?

回答:除了基本的音乐和发光效果外,光电控制电子生日蛋糕电路还可以根据具体设计实现多种功能。例如可以加入烟雾效果装置来模拟真实的蜡烛燃烧效果;或者加入语音模块来播放生日祝福语等。这些功能的实现需要增加相应的元器件和电路设计复杂度但能够显著提升生日蛋糕的趣味性和观赏性。需要注意的是在实现这些功能时应充分考虑安全性和实用性避免过度复杂导致电路不稳定或安全隐患增加。

芯海科技(CHIPSEA)公司的发展小趣事

近年来,随着新能源汽车市场的快速崛起,BMS(电池管理系统)技术成为关键。芯海科技凭借在“模拟信号链+MCU”领域的技术积累,成功开发出应用于BMS锂电管理的高精度模拟信号链芯片。这一技术的突破使得芯海科技能够切入新能源汽车市场,为行业的发展提供了有力支持。

HSMC公司的发展小趣事

HSMC的发展不仅为公司自身带来了显著的经济效益,也为当地社会和经济发展做出了重要贡献。项目全面达产后,预计可实现年产值600亿元,利税60亿元,直接带动就业人口3000人。此外,HSMC还通过技术创新和产业升级,带动了上下游产业链的发展,促进了整个电子行业的繁荣与进步。

以上五个故事共同描绘了HSMC在电子行业中的崛起与发展历程。作为一家充满活力和创新精神的企业,HSMC正以其独特的优势和不懈的努力,向着成为全球领先CIDM晶圆厂的目标不断迈进。

Eclipse Magnetics公司的发展小趣事

HSMC的项目进展迅速,按照规划稳步推进。公司的一期项目设计产能为月产4.5万片晶圆,并计划于2019年底投产。二期项目则采用最新的制程工艺技术,设计月产能同样为4.5万片,预计于2021年第四季度投产。这些项目的顺利推进,不仅提升了HSMC的产能规模,也进一步巩固了其在行业内的地位。

Daniels Manufacturing公司的发展小趣事

面对不断变化的市场和客户需求,DMC始终坚持创新驱动的发展战略。通过加强研发投入、引进高端人才、加强产学研合作等方式,DMC不断推出具有创新性和竞争力的新产品。同时,DMC还密切关注行业发展趋势和市场需求变化,及时调整战略规划和产品定位。展望未来,DMC将继续秉承“创新、质量、服务”的理念,致力于成为全球电子行业的领军企业之一。

以上五个故事虽然是虚构的,但它们基于DMC在电子行业中的实际发展情况和可能面临的挑战进行了合理推测和演绎。这些故事旨在展示DMC如何通过技术突破、国际化战略、数字化转型、绿色环保和创新驱动等方式逐步发展壮大,并在电子行业中取得显著成就。

Agere System(LSI Logic)公司的发展小趣事

自1946年成立以来,Daniels Manufacturing Corporation一直致力于为军事和电信行业提供高质量的工具系统和技术。在20世纪70年代,DMC经历了一次重大的技术突破,成功研发出一种新型的手动压接工具,该工具能够精确、高效地处理各种电子连接器。这一技术的突破为DMC赢得了市场的认可,也为其后续的产品线扩展奠定了基础。在接下来的几十年里,DMC不断投入研发,推出了包括电动、气动、液压压接工具在内的多种产品,广泛应用于通信、光纤、激光等领域。

问答坊 | AI 解惑

关于监控用的摄像头用的LED是什么样的?

遥控器用的红外LED,因为红外LED发出的光不完全是红外光,也包含部分的可见光(红色)成分,所以肉眼能看到少许光。遥控器使用的LED,一般发射角度是30度左右,用户即使没有完全对准目标,也能有效操作。在没有外界红外线干扰的时候,遥控距离可以 ...…

查看全部问答>

AVR 单片机指令指令

最全的AVR 单片机指令指令…

查看全部问答>

几十种AD/DA装换芯片资料

如题[local]1[/local] [ 本帖最后由 美目如初 于 2009-8-31 23:24 编辑 ]…

查看全部问答>

wince安全性问题

在wince 6.0中我有一个客户端程序,先后两次调用InitializeSecurityContext用于和google服务器端进行安全认证,第一次调用返回的是SEC_I_CONTINUE_NEEDED,第二次返回的是SEC_E_WRONG_PRINCIPAL,请问怎么解决啊?是不是和证书有关系?相同程序在wi ...…

查看全部问答>

PB的编译问题

新装的WIN XP SP2, 番茄花园, 然后装PB5.0, 先装.net framework 1.1, 然后装PB5.0(CPU选择了ARMV4I, X86, Emulator). PB5.0 装好之后,就新建工程编译了,这时EVC, VS2005等都还没有装. 用自带的2410BSP新建工程编译的时候出现错误: \"Invalid  ...…

查看全部问答>

出售代购各种电子元件,欢迎各位来捧场

各位有需要电子元件的请和我联系,库存商品优惠啦!:D 小店欢迎您的光临 石家庄傲尔科技有限公司是一家专注于国外中小电子工程分包商,经过多年的发展,我公司与国际大的元件供应商如MOUSER, DIGIKEY建立了稳定的合作。 我们的优势:1. 保证 ...…

查看全部问答>

讲了那么多技术,有没有导购的?

                                 要1K STM32f103c8T6,找谁?…

查看全部问答>

串口初始化影响步进电机工作?

void main(){      init_serialcom();   //步进电机不能有这个函数,这是一个初始化串口的函数,  ATE0();    //步进电机也不能有这个函数,这是个向串口发送AT指令的函数。    为什么去掉这前两个函 ...…

查看全部问答>

u8 sd_raw_get_info(struct sd_raw_info* info)中struct怎么理解

u8 sd_raw_get_info(struct sd_raw_info* info) { …… } 这个子程序怎么用啊,像u8 mmcWrite(u32 sector, u8* buffer)这种,我在主程序中只要定义unsigned char SD_Write1[]={\"0123456789\"}; 就可以用了mmcWrite(SD_Write1); 但是这个定义 ...…

查看全部问答>

MSP430AFE253的SD24使用问题

SD24的SD24CCTLx寄存器 SD24GRP 位  SD24_A group. Groups SD24_A channel with next higher channel. Not used for the last channel. 如何使用该位?…

查看全部问答>