标题:
51单片机12864滚动显示源码
[打印本页]
作者:
鲍勃
时间:
2021-1-2 21:05
标题:
51单片机12864滚动显示源码
用了一个星期的时间写的12864自下而上滚动显示
#include "csb.h"
#define uchar unsigned char
#define uint unsigned int
uchar code SJ[]={"蒹葭苍苍,白露为霜需谨慎再创造出来的历程都快来吃多了,段时间看好大好大很好的克拉克拉 "};
/*12864端口定义*/
#define LCD_data P0 //数据口
sbit RS = P3^5; //寄存器选择输入
sbit RW = P3^6; //液晶读/写控制
sbit EN = P3^4; //液晶使能控制
sbit PSB = P3^1; //串/并方式控制
sbit DU =P2^6;
sbit WE = P2^7;
void delay5us()//5us延时
{;;}
/*void delay20() //20us
{
unsigned char a;
for(a=109;a>0;a--);
}*/
void delay(uint z) //毫秒延时程序
{
unsigned char a,b;
uint c;
for(c=z+7;c>0;c--)
for(b=197;b>0;b--)
for(a=2;a>0;a--);
}
void check_busy()//判忙
{
uchar busy;
P0=0xff;
RS=0;
RW=1;
do
{
EN=1;
busy=P0;
EN=0;
}while(busy&0x80);
EN=0;
}
void lcdw_dat(uchar dat)//写入数据
{
check_busy();
RS=1;
RW=0;
EN=0;
delay5us();
P0=dat;
delay5us();
EN=1;
delay5us();
EN=0;
}
void lcdw_cmd(uchar cmd)//写入指令
{
check_busy();
RS=0;
RW=0;
EN=0;
delay5us();
P0=cmd;
delay5us();
EN=1;
delay5us();
EN=0;
}
void lcdinit()
{
DU=0;
WE=0;
PSB = 1; //并口方式
lcdw_cmd(0x34); //扩充指令操作
delay(5);
lcdw_cmd(0x30); //基本指令操作
delay(5);
lcdw_cmd(0x0C); //显示开,关光标
delay(5);
lcdw_cmd(0x01); //清除LCD的显示内容
delay(5);
}
/**************************************************************************************
//函数功能:任意位置显示汉字
//形式参数:uchar hang,uchar lie,uchar dat
//行参说明:hang(0~3) lie(0~7)
//************************************************************************************/
/*void lcd_display(uchar hang,lie,uchar *str)//行(0~3),列(0~7)一行最多显示8个 汉字
{//字符可以显示8行,16列
if(hang==0) hang=0x80;
else if(hang==1) hang=0x90;
else if(hang==2) hang=0x88;
else if(hang==3) hang=0x98;
lcdw_cmd(hang+lie);
while(*str!='\0')
{
lcdw_dat(*str++);
}
}*/
//图片(128*64)显示程序
/*void lcd_imp(uchar code *imp)//code定义ROM区的指针,不可更改
{
uchar i,j,k;
j=0x80;
lcdw_cmd(0x34);
for(i=0;i<32;i++)//上半屏
{
lcdw_cmd(j++);//列地址
//lcdw_cmd(0x80);//行地址
for(k=0;k<16;k++)
{
lcdw_dat(*imp++);
}
}
for(i=0;i<32;i++)
{
lcdw_cmd(j++);//列地址
lcdw_cmd(0x88);//行地址
for(k=0;k<16;k++)
{
lcdw_dat(*imp++);
}
}
lcdw_cmd(0x36); //打开绘图显示
lcdw_cmd(0x30); //回到基本指令集
}*/
/**************************************************************************************
//函数功能:任意位置显示字符,可以变化,不可以显示汉字
//形式参数:uchar hang,uchar lie,uchar dat
//行参说明:hang(0~3) lie(0~7) 注意:1个汉字位显示两个字符
//************************************************************************************/
/*void lcd_write(uchar hang,lie,uchar dat)//12864显示变量
{
if(hang==0) hang=0x80;
else if(hang==1) hang=0x90;
else if(hang==2) hang=0x88;
else if(hang==3) hang=0x98;
lcdw_cmd(hang+lie);
lcdw_dat(0x30|dat/10);//取十位
lcdw_dat(0x30|dat%10);//取个位
}*/
/**************************************************************************************
//函数功能:任意位置显示字符,可以变化,不可以显示汉字
//形式参数:uchar hang,uchar lie,uchar dat
//行参说明:hang(0~3) lie(0~7) 注意:1个汉字位显示两个字符
//************************************************************************************/
/*void lcd_display_dat(uchar hang,lie,uchar dat)//12864显示变量
{
if(hang==0) hang=0x80;
else if(hang==1) hang=0x90;
else if(hang==2) hang=0x88;
else if(hang==3) hang=0x98;
lcdw_cmd(hang+lie);
lcdw_dat(dat);
}*/
/**************************************/
//反白函数,或用于非全屏绘图时,其它地方写入0
//X,Y需要反白的起始地址,如第一行,X=0x80,Y=0x80,第二行X=0x90,Y=0x90
//X1需要反白多少列,如反白第一行,则X1=16
//Y1为需要反白那行中的几个字(每行最多8个字),清除一整行,则Y1=8
//dat=0xff,反白 dat=0x0,清除
/******************************************************************************/
/*void lcd_white(uchar X,Y,X1,Y1,dat )//
{
uchar i,j;
for(i=0;i<X1;i++)
{
for(j=0;j<Y1;j++)
{
lcdw_cmd(0x34);//打开扩展功能 ,关绘图
lcdw_cmd(Y+i);
lcdw_cmd(X+j);
lcdw_dat(dat);//D15~D8
lcdw_dat(dat);//D7~D0
}
}
lcdw_cmd(0x36);//打开扩展功能
lcdw_cmd(0x30); //回到基本指令集
}
*/
void main()
{
unsigned char i,addr;
unsigned char flag,hang,over;
unsigned char *ptdat;
lcdinit();
//addr用于存储写入地址
//flag存储卷动地址,名字没取好!
//hang存储下一行要写入数据的行号(1~4)
//over记录写入的空字符数
//ptdat存储字符串的指针
delay(1);
ptdat = &SJ[0];
over = 0; //写入空字符数
//这里先把前面DDRAM中的前3行的字符数据写入
//如果字符不足<=4行,那么不卷动,之后字符>4行才卷动
//一直到末行显示完毕则停止卷动
lcdw_cmd(0x80); //写屏幕第一行字符
for(i = 0; i < 16; i++)
{
if(*ptdat != '\0')
{
lcdw_dat(*ptdat++);
}
else
{
lcdw_dat(0x20);
over++;
}
}
lcdw_cmd(0x90); //写屏幕第二行字符
for(i = 0; i < 16; i++){
if(*ptdat != '\0'){
lcdw_dat(*ptdat++);
}else{
lcdw_dat(0x20);
over++;
}
}
lcdw_cmd(0x88);//写屏幕第三行字符
for(i = 0; i < 16; i++){
if(*ptdat != '\0'){
lcdw_dat(*ptdat++);
}else{
lcdw_dat(0x20);
over++;
}
}
lcdw_cmd(0x98);//写屏幕第四行字符
for(i = 0; i < 16; i++){
if(*ptdat != '\0'){
lcdw_dat(*ptdat++);
}else{
lcdw_dat(0x20);
over++;
}
}
ptdat = ptdat - 32;
lcdw_cmd(0xa0); //写DDRAM第3行数据
for(i = 0; i < 16; i++){
if(*ptdat != '\0'){
lcdw_dat(*ptdat++);
}else{
lcdw_dat(0x20);
over++;
}
}
ptdat = ptdat + 16;
for(i = 0; i < 16; i++){
if(*ptdat != '\0'){
lcdw_dat(*ptdat++);
}else{
lcdw_dat(0x20);
over++;
}
}
//前面的代码是往DDRAM中写如下内容:
//第一行字符 第三行字符
//第二行字符 第四行字符
//第三行字符 第五行字符
//如果写第5行时全为空,说明字符刚好4行,不卷动。
//此时第5行写入16个0x20空字符,over用于记录空字符个数。
//如果不足4行,则前面也将会写入空字符,此时写完了3行DDRAM后
//over的值必大于16,而只要over>15,就不卷动
lcdw_cmd(0x0c); //开显示
if(over > 15){;} //显示字符不足4行,不卷动
else //显示字符大于4行,开启卷动
{
hang = 4; //接下来要写DDRAM第4行数据
flag = 0x01; //初始卷动地址为1
while(1){
switch(hang){ //设置写入DDRAM的地址
case 1: addr = 0x80; break; //往地址变量中写第一行首地址
case 2: addr = 0x90; break; //往地址变量中写第二行首地址
case 3: addr = 0xa0; break; //往地址变量中写第三行首地址
case 4: addr = 0xb0; break; //往地址变量中写第四行首地址
}
switch(hang){ //指出下一次要写的行地址
case 1: hang = 2; break;//第1行写完了,下一行要写第2行
case 2: hang = 3; break;//第2行写完了,下一行要写第3行
case 3: hang = 4; break;//第3行写完了,下一行要写第4行
case 4: hang = 1; break;//第4行写完了,下一行要写第1行
}
//后续代码为往每一行写数据,卷动一次写一个字。
ptdat = ptdat - 32;
for(i = 0; i < 8; i++)
{ //写一行中的前8个字符
lcdw_cmd(0x34); //打开扩展指令
lcdw_cmd(0x03); //允许输入卷动地址
lcdw_cmd(0x40 + flag++); //设置卷动地址
lcdw_cmd(0x30); //回到基本指令
lcdw_cmd(addr + i);
delay(100);
if(*ptdat != '\0')
{
lcdw_dat(*ptdat++); //写入高字节
}
else
{
lcdw_dat(0x20); //字符串结束则写入空字符
}
if(*ptdat != '\0')
{
lcdw_dat(*ptdat++); //写入低字节
}
else
{
lcdw_dat(0x20); //字符串结束则写入空字符
}
}
ptdat = ptdat + 16;
for(i = 8; i < 16; i++)
{ //写一行中的后8个字符
lcdw_cmd(0x34); //打开扩展指令
lcdw_cmd(0x03); //允许输入卷动地址
if(flag == 64)
{
flag = 0;
}
lcdw_cmd(0x40 + flag); //设置卷动地址
flag++;
lcdw_cmd(0x30); //回到基本指令
lcdw_cmd(addr + i);
delay(100);
if(*ptdat != '\0')
{
lcdw_dat(*ptdat++); //写入高字节
}
else
{
over++; //写完最后一行字符,需要再卷动16次才能显示出来。
lcdw_dat(0x20); //字符串结束则写入空字符
}
if(*ptdat != '\0')
{
lcdw_dat(*ptdat++); //写入低字节
}
else
{
lcdw_dat(0x20); //字符串结束则写入空字符
}
}
if(over < 8){;}
else {break;}
}
}
}
复制代码
源码下载,大家多多指教,如果有错误,欢迎批评指正:
12864滚动显示.rar.rar
(38.83 KB, 下载次数: 71)
2021-1-2 21:04 上传
点击文件名下载附件
下载积分: 黑币 -5
作者:
chjchj816
时间:
2021-1-3 11:10
学学练练 涨点水平
作者:
1518419198
时间:
2021-1-3 16:50
第106行注释错了,应该是4行8列
作者:
掉毛的兔子
时间:
2024-1-31 09:19
很好,内部不错
欢迎光临 (http://www.51hei.com/bbs/)
Powered by Discuz! X3.1