51(52)单片机 LCD1602动态显示(一行固定一行滚动)与自定义字符显示

单片机小白

第一行向左滚动
第二行固定不动
右下角笑脸顺时针旋转一周,第一行向左滚动一个字符。

单片机存储空间不同,u8 a[16+sizeof(str)+16] 处可能会报溢出,改成
u8 pdata a[16+sizeof(str)+16] 就行

pdata:外部扩展RAM的低256个字节

运行效果:
为动态滚动效果,以下为截图
在这里插入图片描述

主函数main.c代码:

#include <reg52.h>
#include "lcd1602.h"


 
  

    u8 code cg_addr[]={0x40,0x48,0x50,0x58,0x60,0x68,0x70,0x78};
     //其中八个CGRom的地址
	u8 code read_cg[]={0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07};
     //以上八个CGRom的编号
	u8 code user[][8]={
                       {0x1F,0x0A,0x0A,0x1F,0x0A,0x0A,0x12,0x02},     //开
	                   {0x00,0x00,0x00,0x00,0x00,0x02,0x06,0x00},     //心
	                   {0x00,0x00,0x04,0x01,0x10,0x11,0x1F,0x00}
	                   };
	
	u8 code xiao[][8]={
		               {0x03,0x04,0x0A,0x08,0x0A,0x09,0x04,0x03},     //变幻左部笑脸
					   {0x03,0x04,0x09,0x0A,0x0A,0x09,0x04,0x03},
					   {0x03,0x04,0x09,0x0A,0x08,0x0A,0x04,0x03},
					   {0x03,0x04,0x0A,0x08,0x08,0x0A,0x04,0x03},
	                   {0x18,0x04,0x0A,0x02,0x0A,0x12,0x04,0x18},     //变幻右部笑脸
	                   {0x18,0x04,0x0A,0x02,0x02,0x0A,0x04,0x18},
					   {0x18,0x04,0x12,0x0A,0x02,0x0A,0x04,0x18},
					   {0x18,0x04,0x12,0x0A,0x0A,0x12,0x04,0x18}
					  };
	u8 code str[]="Have A Good Day !";
     
	
//自定义图形函数	 
/*思路是1.选中一个CGRAM(地址)
          01 ... ... 设置第3.4.5位选中前8个CGROM
                     设置低三位选CGRAM的8行像素点
                    (文章用的是设置初地址然后for(...8...)循环选中)

        2.向CGRAM填充图形(字符型为5*7,高电平亮)先填充行,自上而下依次重复操作
        0x1.. .....(8421 8421码)
        例如 dian[] = {0x07,0x05,0x07,0x00,0x00,0x00,0x00,0x00}
          只有低5位有效
          0x07=000 00111代表第一行的从右自左的第1.2.3个像素点亮    0  0  0
          0x05=000 00101代表第一行的从右自左的第1.3个像素点亮      0     0
          0x07=000 00111代表第三行的从右自左的第1.2.3个像素点亮    0  0  0
        3.设置要显示的位置
        4。从相应的CGRAM中取出自定义图形显示 
        ( 0000 0000  设置低三位选中前八个CGRAM编码)   
*/
void user_xie(u8 x,u8 y,u8 cg,u8 *User)
{
	 u8 i;
   LcdWriteCmd(cg_addr[cg]); //设定 CGRAM 地址
   for(i=0;i<8;i++ )
    {
      LcdWriteData(User[i]); //写入自定义图形
    }
   LcdSetCursor(x,y);    //显示的位置,x为列,y为行
   LcdWriteData(read_cg[cg]); //从 CGRAM 里取出自定义图形显示

}


//延时函数
//主要是引脚P2^5与蜂鸣器共用,不设置一下太吵人了
void delay_ds(unsigned short ms)
  {
    u8 T;
		while(ms--)
		{
			for(T=0;T<250;T++);
		}
		
  }

	
void xiao_xz()                              //笑脸旋转+延时(相当于四帧动画)
{
		user_xie(14,1,5,xiao[0]);
		user_xie(15,1,6,xiao[4]);
		delay_ds(125);
		user_xie(14,1,5,xiao[1]);
		user_xie(15,1,6,xiao[5]);
		delay_ds(100);
		user_xie(14,1,5,xiao[2]);
		user_xie(15,1,6,xiao[6]);
		delay_ds(100);
		user_xie(14,1,5,xiao[3]);
		user_xie(15,1,6,xiao[7]);
		delay_ds(100);
}

//主函数	
void main()
{
    u8  a[16+sizeof(str)+16];          
     //为数组a定义空间,前16位与后十六位均为空字符,中间为要显示的字符串
     //这里不能用strlen,sizeof为运算符,strlen为函数
    

	u8 i,j,index;
	i=j=index=0;
	
	InitLcd1602();                          //lcd1602初始化
	
	for(i=0;i<16;i++)                       //前16位与后十六位均为空字符,中间为要显示的字符串
		a[i]= ' ';
	for(i=0;i<(sizeof(str)-1);i++)
	   a[16+i]=str[i];
	for(i=(16+sizeof(str)-1);i<sizeof(a);i++)
		a[i]= ' ';
	
	
	while(1)
	{ 

	    
        
        LcdShowStr(6,1,"Happy");               //从CGROM中选中相应字符显示
		user_xie(0,1,0,user[0]);            //自定义图形函数
		user_xie(1,1,1,user[1]);
		user_xie(2,1,2,user[2]);

			
		if(j==0)                                 //开机画面
		{
			
			LcdShowStr(0,0,"Made By LuDeYue!");
			user_xie(14,1,5,xiao[0]);
		    user_xie(15,1,6,xiao[4]);
	        delay_ds(450);
		}
		j-=1;
	
	
		LcdShowStr_Shift(0,0,a+index,16);        
		   /*滚动显示函数,lcd的列数为16,所以每次只能选取16位字符进行显示
		a+index类似指针(a为初地址,index为偏移量),指向所偏移的地址后向后取15个(从指向地址处算共16个)字符出来显示*/
		
		index++;//显示一次后指向下一处地址,同理可更改为向右滚动
		if(index>=(16+sizeof(str)-1))//如果字符串已全部左移的话(显示后16个空字符)置零,重新开始
		{
			index=0;
		}
	

		xiao_xz();                               //笑脸旋转+延时
   
		
		

    }
}




LCD1602.h代码:

#include <reg52.h>
#include <intrins.h>

#define LCD1602_DB P0

#define u8 unsigned char
#define u16 unsigned int
#define s16 signed int


 
	 
   sbit LCD1602_RW=P2^5;
   sbit LCD1602_RS=P2^6;
   sbit LCD1602_E=P2^7;

	 
//lcd1602忙闲状态判断
void LcdWaitReady()
{
    u8 sta;
	LCD1602_DB=0xFF;
	LCD1602_RS=0;
	LCD1602_RW=1;
	do{
	     LCD1602_E=1;
		 sta=LCD1602_DB;
		 LCD1602_E=0;
	}while(sta&0x80);
	
}

//写命令
void LcdWriteCmd(u8 cmd)
{
	LcdWaitReady();
	LCD1602_RS=0;
	LCD1602_RW=0;
	LCD1602_DB=cmd;
    LCD1602_E=1;
	LCD1602_E=0;
	
}


//写数据(1602字符输入(CGROM固定字库))
void LcdWriteData(u8 dat)
{
	LcdWaitReady();
	LCD1602_RS=1;
	LCD1602_RW=0;
	LCD1602_DB=dat;
    LCD1602_E=1;
	LCD1602_E=0;
}


//lcd1602初始化
void InitLcd1602()
{
	LcdWriteCmd(0x38);   //功能设置命令 
	LcdWriteCmd(0x38);   //有时候LCD1602不听话,只显示一行,那就在说几次 
	LcdWriteCmd(0x0C);   //显示开/关及光标设置      、
	LcdWriteCmd(0x06);   //显示模式设置
	LcdWriteCmd(0x01);   //清屏指令
		
}


//显示的位置设置
void LcdSetCursor(u8 x,u8 y)//x为列,y为行
{
	u8 addr;
	if(y==0)
		addr=0x80+x;//第一行
	else
		addr=0xC0+x;//第二行
	LcdWriteCmd(addr);

}


//显示
void LcdShowStr(u8 x,u8 y,u8 *str)
{
	LcdSetCursor(x,y);
	while(*str!='\0')
	{
		LcdWriteData(*str++);
	}
	
}

//滚动的显示
void LcdShowStr_Shift(u8 x,u8 y,u8 *str,u8 len)
{
		
	LcdSetCursor(x,y);
	while(len--)
	{
		LcdWriteData(*str++);
	}
}






  • 11
    点赞
  • 84
    收藏
    觉得还不错? 一键收藏
  • 8
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值