单片机LCD1602错误显示

单片机LCD1602错误显示,第1张

在每输入数据之前,你得先确定当前的Address Counter(AC)记录的是不是你所想的,也就是第一个字符的DDRAM是不是对的,之后每输入一个数据,AC是自加1的。

建议你下载HD44780的资料仔细看一遍,它是LCD的驱动IC,比直接看1602的资料在原理上会更清楚一些。

void delay_1ms(uint x)//延时

{ uchar j; //加一变量 uchar i,j;

while((x--)!=0) //改为for(i=0;i<x;i++)

{ for(j=0;j<125;j++) ;

}

}

//检查LCD忙状态

bit lcd_busy() //其实大多数都delayms(5)代替的,尤其是仿真时不能用此函数

{

bit result;

rs=0;

rw=0;

e = 1;

delay_1ms(1);

result = (bit)(data&0x80); //不知data是不是已经#define了

e = 0;

return(result);

}

//写指令数据到LCD

void write1602_com(uchar com)

{while(lcd_busy());

rs = 0;

rw = 0;

e = 0;

delay_1ms(1);

data= com;

delay_1ms(1);

e = 1;

delay_1ms(1);

e = 0;

}

//写显示数据到LCD

void write1602_data(uchar dat)

{while(lcd_busy());

rs = 1;

rw = 0;

e = 0;

data = dat;

delay_1ms(1);

e = 1;

delay_1ms(1);

e = 0;

}

void start(void) //LCD初始化

{delay_1ms(15);

write1602_com(0x38);

delay_1ms(5);

write1602_com(0x38);

delay_1ms(5);

write1602_com(0x38);

delay_1ms(5);

write1602_com(0x0F);//显示开,关光标

delay_1ms(5);

write1602_com(0x06);//移动光标

delay_1ms(5);

write1602_com(0x01);//清除LCD的显示内容

delay_1ms(5);

}

/ 设定显示位置 /

/

void lcd_data(uchar dat) //1602两行地址不是连续的,第二行是0xC0开始的

{

write1602_com(dat|0x80); //数据指针=80+地址变量

}

/

void lcd_data(uchar dat)

{

unsigned char p;

if (pos>=0x10)

p=pos+0xb0;

else

p=pos+0x80;

write1602_com(p);

write1602_data(c);

}

void main()

{

start();

delay_1ms(10);

write1602_com(0x01); //已经清屏,不知道这句的意义

delay_1ms(10);

delay_1ms(5);

lcd_data(0x00);

delay_1ms(5);

for(i=0;i<12;i++)

{

if(i==13){ //建议这句话加上大括号,放到后边,放在这影响不好

while(1);}

write1602_data(table2[i]);//应先写地址再写数据,而你这地址是不变的,最终导致数组数据在

//一个地址上陆续显示,不知道会是啥效果,并且希望你的数组不是const的。

//可以写个连续显示的函数,加指针的

delay_1ms(1);

}

}

我这1602的程序及仿真还有很多,可以向我联系的

51单片机对lcd1602一些基础程序

#include <intrinsh>

#define dataport P1

sbit RS=P2^ 6;

sbit RW=P2^5;

sbit EN=P2^4;

//========================

//=========================

void waitfor() //检测忙信号函数

{

dataport=0xff;

RS=0;RW=1;_nop_(); //选择指令寄存器 读 *** 作

EN=1;_nop_(); //使能 *** 作

while(dataport&0x80); //如果最高位是1 表示1602正忙 原地踏步 忙完后芯片会将高位拉低

EN=0;

}

//======================

void writedata(unsigned char dataw) //写数据到lcm

{

waitfor(); //测忙

RS=1;RW=0;_nop_(); //选择数据寄存器 写 *** 作

dataport=dataw;_nop_(); //将数据送到数据口

EN=1;_nop_();_nop_();EN=0; //使能

}

//==========================

void writecmd(unsigned char cmd) //写命令到lcm

{

waitfor();

RS=0;RW=0;_nop_();

dataport=cmd;_nop_();

EN=1;_nop_();_nop_();EN=0;

}

//===========================

void init(void) // 初始化函数

{

writecmd(0x38); //功能设定 8位数据传输 双行显示

writecmd(0x0c);//显示器开关

writecmd(0x01);//清屏

writecmd(0x06);//字符进入模式 每进入一个字符光标向右移动一格 原有字符不动

//我在刚开始学的时候不知道下一个字符显示在哪 是和AC值有关还是和光标位置有关

//最后摸索出来是只和光标定位有关 现在还是不知道Ac值有什么用

}

//=========================

void location(unsigned char x,unsigned char y) //确实坐标函数

{

unsigned char temp;

temp=x&0x0f; //只要x数据的后四位

if(y){temp=temp|0x40;} //第一行为0 第二行为1 如果y=1则地址加0x40

temp|=0x80; //DDRAM地址的命令DB7为一

writecmd(temp);

}

//==============================

void displyonechar(unsigned char x,unsigned char y,unsigned char dataw) //显示一个字符函数

{

location(x,y);

writedata(dataw);

}

//=======================================

void displylistchar(unsigned char x,unsigned char y,unsigned char p) //显示字符串

{

while(p) //当一个字符型数组读完时P指的为零

{

displyonechar(x,y,(p++));

x++;

}

}

//=====================================================

void writecgram(unsigned char address,unsigned char p) //写CGRAM的数据

{

unsigned char i=8;

writecmd(address); //CGRAM里的地址 初始值0x40 每次加0x80

while(i--)

{

writedata(p);

p++;

}

}

//=====================================================

void displyonecharacter(unsigned char x,unsigned char y,unsigned char address,unsigned char p) //显示一个自定义字符

{

unsigned char i=8;

writecmd(address); //CGRAM里的地址 初始值0x40 每次加0x08

while(i--)

{

writedata(p);

p++;

}

//============================================================

location(x,y); //设定要显示的位置

writedata((address&=0x3f)/0x08); //要从CGRAM中读出数据在1602上显示 搞了半天发现CGRAM里的地址

} //和DDRAM里的地址有上面的转换关系

//========================================================

void displynumber(unsigned char x,unsigned char y,unsigned long num) //显示一个整数

{

unsigned int number[8];

int k,gh;

for(k=0;;k++)

{

(number+k)=(unsigned int)(num%10);//强制类型转换

num=num/10;

if(num==0)break;

}

for(gh=k;gh>=0;gh--)

{

displyonechar(x,y,((number+gh)+48));

x++;

}

}

//字型码

uchar code nin[]={0x08,0x0f,0x12,0x0f,0,0x1f,0x02,0x02};// "年"

uchar code yue[]={0x0f,0x09,0x0f,0x09,0x0f,0x09,0x0b,0x11};// "月"

uchar code ri[]={0x1f,0x11,0x11,0x1f,0x11,0x11,0x11,0x1f};// "日"

显示汉字

displyonecharacter(0,0,0x40,nin);

displyonecharacter(1,0,0x80,yue);

displyonecharacter(1,0,0xc0,ri);

这个是经过编译成功的程序,看看什么样:

#include "1602h"

#include "defh"

/端口定义/

#define uchar unsigned char

#define uint unsigned int

unsigned char code String1[] ="The first alarm ";

unsigned char code String2[] ="The second alarm";

unsigned char code String3[] ="The third alarm ";

void main(void)

{

LCD_init();

TMOD |= 0X01;

TH0 = (65535 - 50000) / 256;

TL0 = (65535 - 50000) % 256;

ET0 = 1;

EA = 1;

while(1) {

if(Ctr1 == 0 || Ctr2 == 0 || Ctr3 ==0) {

if(Ctr1 == 0) {

LCD_string(0, String1);

LED = ON;

BEEP = ON;

TR0 = 1;

}

if(Ctr2 == 0) {

LCD_string(0, String2);

LED = ON;

BEEP = ON;

TR0 =1;

}

if(Ctr3 == 0) {

LCD_string(0, String3);

LED = ON;

BEEP = ON;

TR0 = 1;

}

}

}

}

void timer0() interrupt 1

{

uchar tt;

TH0 = (65535 - 50000) / 256;

TL0 = (65535 - 50000) % 256;

tt++;

if(tt == 20) {

tt = 0;

LED = OFF;

BEEP = OFF;

TR0 = 0;

}

}

我给你推荐一款,是我自己用的这款,比较好,开发时自己的机子要有并口,价格是168rmb,免邮

2008-7-7--------2008-9-1 为暑期促销特价期 原价168元 现特价150元!! 配置不变 锐志电子单片机普及计划 让学习者花最少的钱 学到最多的知识

此款是有并口电脑所用的配置利用并口ISP线烧写程序

(没有并口的电脑 但是有串口的可以采用STC89C52芯片 利用串口下载程序 购买时请说明 我们会配STC89C52芯片)

本实验板是锐志电子开发的一款多功能51综合学习实验板。 是经过研究和分析市面上的多种实验板后, 取其所长,弊其所短短 研发而成。 所以对于学习者来说, 性价比是很高的。 花最少的钱, 学到最多的知识, 这就是锐志电子单片机普及计划的宗旨。

本实验板是集单片机编程、 仿真(须配仿真芯片)、 实验、下载线 多种功能为一体, 该51单片机学习实验板除了支持ATmel公司的AT89S所有系列之外,还支持STC的所有系列增强型51单片机和SST系列的增强型51单片机的实验、编程与仿真功能,支持的被编程芯片数量达100之多;是一款真正具有物超所值的51单片机多功能板。

功能特点

编程器、仿真器、实验板、ISP下载线四合一

直接支持Atmel 89系列,AVR AT90S8515,Atmega8515系列单片机的烧写,

提供丰富的实验例程,附带C源代码和少量汇编源码,并且附带详细的注解说明(C语言是未来的趋势 所以我们提倡使用C开发 附带汇编源码较少)

编程与实验共享唯一的锁紧插座,串行下载与仿真共享同一串口, *** 作方便

内置完善的过载、短路保护功能

直接使用计算机USB接口供电,也可以接电源适配器供电板载7805稳压IC 保证其他电源供电时 实验板工作的稳定。

带有电源开关实验更加方便 再也不用频繁拔实验板电源线了 轻轻一按 即可通断。

直接将器件放在开发系统锁紧座上进行编程,可单独作编程器使用

直接在锁紧座上放上仿真芯片连上串口 稍作设置 即可进行仿真。

板载丰富的实验硬件资源,P0 P1 P2 P3 四个IO口 全部可扩展设计 真正的满足学习者的需要通过自己连接IO口线路 可以完成任何复杂的51单片机实验

配有ISP下载口 配合本实验板标配的89S52单片机 就可不用任何编程器 也不用将芯片取下就可直接完成烧写编程工作 十分方便, 烧写完毕即可自动演示。实验过程中无需拔插任何电缆和芯片,也无需切换电源,可轻松地将编绎好的代码下载到实验板上进行验证或演示,整个过程只需利用鼠标 *** 作即可,方便快捷。

实验板资源配置如下:

1、此款采用并口ISP下载线,配AT89S52单片机,可以很方便的下载程序到单片机。下载后不用插拔线缆, 下载好后自动直接运行程序。

2、USB供电系统,直接插接到电脑USB口即可提供电源,不需另接直流电源。

3、8位数码管(可做数码管的静态扫描以及动态扫描显示实验 不如 0-999 计数器实验 18B20温度检测实验 遥控解码实验等都可以用数码管显

示)。

4、8位LED发光二极管(做 跑马灯实验 交通灯实验 )。

5、一路继电器控制(通过继电器可以控制其他电器设备的工作低压控制高压等实验 不过为了安全 建议不要控制电压超过30V的设备)

6、蜂鸣器(做单片机发声实验 播放音乐实验 报警实验等声响实验)

7、DS18B20温度传感器,(初步掌握单片机 *** 作后即可亲自编写程序获知当时的温度 可以配合本站原创的PC与单片机双向温度控制程序 将温

度实时显示在电脑上)

8、AT24C08外部EEPROM存储芯片(IIC总线元件实验)

9、SPI串行实时时钟 DS1302(熟悉SPI总线 用DS1302可以做一个万年历电子时钟 比定时器做的精确很多哦)

10、 板上集成一体化红外接收头(方便学习红外遥控接收 解码实验 还可以通过遥控控制电脑 本站原创的红外遥控解码控制电脑音乐播放实例可以让学习者 学习 体验用遥控器控制电脑的乐趣)

11、MAX232芯片RS232通讯接口(可以做为与计算机通迅的接口同时也可做为STC单片机下载程序的接口及仿真调试的接口)

12、字符液晶1602LCD接口 采用接插件方式方便插拔(可显示两行 每行16个 共计32任意 ASCII码字符 它的功能应用比数码管丰富很多 显示

的信息量更大 我们已经随板附赠了1602LCD 方便学习者开发1602LCD显示的程序)

13、图形点阵液晶12864接口 采用接插件方式方便插拔(可显示任意汉字和图形 是目前单片机 图文显示最常用的显示器件 我们实验板支持带字库的12864液晶 开发程序更方便 12864液晶不随板附赠 需单独购买 我们成本价70元提供带字库的支持对比度调节12864液晶)

14、44矩阵键盘(熟悉矩阵键盘编码、解码扫描原理 可作为人机输入接口 编写按键输入程序)

15、4个独立键盘(可做普通独立按键检测试验 本实验板4个独立按键采用跳线设计 考虑周全 可以通过跳线连接任意P口 方便学习者做 外中

断INT0 INT1 外定时器T0 T1 实验)。

16、单片机32个IO口全部引出 端口扩展设计采用双排跳线帽设置,如果跳线帽拔掉,完全可以做最小系统,真正发挥你的开发才能 便于你今后的开发。

17、为方便大家更换晶体振荡器(单片机“超频”)特别采用了镀金晶体插座,做实验时需要不同晶振频率时 可很方便的插拔更换(我们随板赠送三个不同频率的晶振 110592MHZ、12MHZ、24MHZ各一个 最大程度上满足了学习者的需要)

18、本实验板带有51单片机 和AVR单片机的切换开关通过开关轻轻波动一下直接就可以使用ATMEGA8515等AVR系列单片机做AVR实验,真正做到物尽其用。为51学习者将来学习AVR单片机节省了再次购买AVR实验板的成本,所以我们的实验板非常超值。

19、ISP下载接口(用并口ISP下载线或者其他的兼容ISP下载线 可以对AT89S51 S52 ATMEGA8515 AT90S8515单片机直接编程。)

20、本实验板采用40PIN锁紧座安放单片机芯片,非常方便单片机芯片的取放。

21、本实验板 板上带有外接电源接口 方便使用外接电源为单片机供电。

22、实验板 带有 +5V 和地线扩展口 方便用户扩展其他外围电路时取电

本实验板附带的试验程序:

产品规格:长X宽X高 = 120x100x20(mm)

产品装箱清单:

RZ-51/AVR实验板一台

USB取电线一条

串口通讯电缆一条

AT89S52单片机一片

1602LCD字符液晶模块一块

并口ISP下载线一条

12M 110592M 24M 晶振各一个

10根杜邦连接线

10个备用跳线帽

700MB的51学习资料光盘一张(光盘中含本实验板所有例程 每个例程里都有实验指导文档,方便学习者做实验。实验板PDF格式原理图,实验板使用说明文件、STC单片机程序下载软件,ISP下载线软件 大量KEIL51学习资料及教程 串口调试软件 还有本站原创的串口控制单片机 双向通讯的智能温控报警系统 上位机程序源码 和单片机程序源码)

我们所有器件都采用防静电袋包装 外包装采用泡沫防震包装 邮政标准7#箱 包装专业 避免运输过程出现损坏

发货前每项功能均已严格测试 保证质量 请放心购买。

我们长期从事单片机程序开发 和PC程序开发 可为客户提供很好的技术支持。

每天早上8:00到晚上12:00都会在线 随时为客户提供专业的技术支持。

部分实验:

本站原创 单片机温控+VB上位机温度检测实验VB上位机

(可设定报警温度 并有实时温度曲线图 附赠全部源码。有很大的应用价值)

本站原创 单片机S52 控制上位机VB 制作成的 VB红外遥控电脑播放器 上位机

(可自定义遥控器的键值 支持市面上大部分遥控器 可进行 磁盘选择 目录选择 歌曲选择 音量调节 播放/暂停 静音 还有播放视频时全屏等 *** 作 可以说是一个完整的功能强大的红外遥控播放器 和遥控DVD 没什么区别 非常实用。全部源码 均在光盘中赠送。。)

自定义遥控键值

近一个月销售记录 众多买家的选择证明 我们的实验板非常超值。。

这是一个时钟显示程序,里面有1602的 *** 作程序,比较完整绝对能运行

RS=P20 RW=P21 E=P22 DB0---DB7接P0口

//

#include<reg51h>

#include<intrinsh>

#define uchar unsigned char

#define uint unsigned int

sbit LCD_RS = P2^0;

sbit LCD_RW = P2^1;

sbit LCD_EN = P2^2;

sbit LCD_LED = P2^6;

bit flag=1,hour=0,min=0,sec=0;

bit year=0,month=0,day=0,week=0;

bit alarm_flag=0;

uchar timecount=0,count=0;

uchar str1[]=" - - Week: ";

uchar str2[]="Time: ";

uchar str3[]="Alarm: ";

uchar init [] ={0x00,0x00,0x00,0x00,0x00,0x00,0x00}; //

uchar init1[] ={0x00,0x00};

uchar init2[] ={0x00,0x59,0x23,0x01,0x05,0x01,0x06}; //

//秒, 分, 时, 日, 月,星期,年

uchar bj_time[] ={0x00,0x00,0x00};

//秒, 分, 时

uchar code mytab[8] = {0x01,0x1b,0x1d,0x19,0x1d,0x1b,0x01,0x00};//小喇叭

#define delayNOP(); {_nop_();_nop_();_nop_();_nop_();};

void Set_place(uchar row,uchar col);

void Play_nowtime();

void key_set(uchar num,uchar row,uchar col );

void alarm_time();

void Play_alarmtime();

void Time_compare();

//

//

void delay1(int ms)

{

unsigned char y;

while(ms--)

{

for(y = 0; y<250; y++)

{

_nop_();

_nop_();

_nop_();

_nop_();

}

}

}

//

/ /

/检查LCD忙状态 /

/lcd_busy为1时,忙,等待。lcd-busy为0时,闲,可写指令与数据。 /

/ /

//

bit lcd_busy()

{

bit result;

LCD_RS = 0;

LCD_RW = 1;

LCD_EN = 1;

delayNOP();

result = (bit)(P0&0x80);

LCD_EN = 0;

return(result);

}

//

/ /

/写指令数据到LCD /

/RS=L,RW=L,E=高脉冲,D0-D7=指令码。 /

/ /

//

void lcd_wcmd(uchar cmd)

{

while(lcd_busy());

LCD_RS = 0;

LCD_RW = 0;

LCD_EN = 0;

_nop_();

_nop_();

P0 = cmd;

delayNOP();

LCD_EN = 1;

delayNOP();

LCD_EN = 0;

}

//

/ /

/写显示数据到LCD /

/RS=H,RW=L,E=高脉冲,D0-D7=数据。 /

/ /

//

void lcd_wdat(uchar dat)

{

while(lcd_busy());

LCD_RS = 1;

LCD_RW = 0;

LCD_EN = 0;

P0 = dat;

delayNOP();

LCD_EN = 1;

delayNOP();

LCD_EN = 0;

}

//

/ /

/ LCD初始化设定 /

/ /

//

void init_lcd()

{

delay1(15);

lcd_wcmd(0x01); //清除LCD的显示内容

lcd_wcmd(0x38); //162显示,57点阵,8位数据

delay1(5);

lcd_wcmd(0x38);

delay1(5);

lcd_wcmd(0x38);

delay1(5);

lcd_wcmd(0x0c); //显示开,关光标

delay1(5);

lcd_wcmd(0x06); //移动光标

delay1(5);

lcd_wcmd(0x01); //清除LCD的显示内容

delay1(5);

}

//

//

//

void delay()

{

uchar j;

for(j=250;j>0;j--);

}

//

/ /

/ 写字符串函数 /

/ /

//

void write_str(uchar addr,uchar p)

{

uchar i=0;

lcd_wcmd(addr);

while(p[i]!='\0')

{

lcd_wdat(p[i]);

i++;

}

}

//

/ /

/ 设定显示位置 /

/ /

//

void write_position(uchar row,uchar col)

{

uchar place;

if(row==1)

{

place=0x80+col-1;

lcd_wcmd(place);

}

else

{

place=0xc0+col-1;

lcd_wcmd(place);

}

}

//

/ /

/自定义字符写入CGRAM /

/ /

//

void writetab()

{

unsigned char i;

lcd_wcmd(0x40); //写CGRAM

for (i = 0; i< 8; i++)

lcd_wdat(mytab[i]);

}

//

//

//

void write_byte(uchar inbyte)

{

uchar i;

for(i=0;i<8;i++)

{

sclk=0; //写的时候低电平改变数据

if(inbyte&0x01)

io=1;

else

io=0;

sclk=1; //写的时候高电平,把数据写入ds1302

_nop_();

inbyte=inbyte>>1;

}

}

//

//

uchar read_byte() //sclk的下跳沿读数据

{

uchar i,temp=0;

io=1; //设置为输入口

for(i=0;i<7;i++)

{

sclk=0;

if(io==1)

temp=temp|0x80;

else

temp=temp&0x7f;

sclk=1; //产生下跳沿

temp=temp>>1;

}

return (temp);

}

//

// 往ds1302的某个地址写入数据

//

void write_ds1302(uchar cmd,uchar indata)

{

sclk=0;

reset=1;

write_byte(cmd);

write_byte(indata);

sclk=0;

reset=0;

}

//

// 读ds1302某地址的的数据

//

uchar read_ds1302(uchar addr)

{

uchar backdata;

sclk=0;

reset=1;

write_byte(addr); //先写地址

backdata=read_byte(); //然后读数据

sclk=0;

reset=0;

return (backdata);

}

//

// 设置初始时间

//

void set_ds1302(uchar addr,uchar p,uchar n) //写入n个数据

{

write_ds1302(0x8e,0x00); //写控制字,允许写 *** 作

for(;n>0;n--)

{

write_ds1302(addr,p);

p++;

addr=addr+2;

}

write_ds1302(0x8e,0x80); //写保护,不允许写

}

//

// 读取当前时间

//

void read_nowtime(uchar addr,uchar p,uchar n)

{

for(;n>0;n--)

{

p=read_ds1302(addr);

p++;

addr=addr+2;

}

}

//

// 初始化DS1302

//

void init_ds1302()

{

reset=0;

sclk=0;

write_ds1302(0x80,0x00);

write_ds1302(0x90,0xa6); //一个二极管+4K电阻充电

write_ds1302(0x8e,0x80); //写保护控制字,禁止写

}

//

/ /

/ 蜂鸣器响一声 /

/ /

//

void beep()

{

unsigned char y;

for (y=0;y<100;y++)

{

delay();

BEEP=!BEEP; //BEEP取反

}

BEEP=1; //关闭蜂鸣器

delay1(50);

}

//

/ /

/ :闪动函数 /

/ /

//

void flash()

{

if(flag)

{

write_position(2,9);

lcd_wdat(':');

write_position(2,12);

lcd_wdat(':');

}

else

{

write_position(2,9);

lcd_wdat(0x20);

write_position(2,12);

lcd_wdat(0x20);

}

}

//

// 主函数

//

void main()

{

LCD_LED=0;

P1=0xff;

TMOD=0x01;

TH0=0x4c; //50ms定时

TL0=0x00;

EA=1;

ET0=1;

TR0=1;

init_lcd(); //初始化LCD

write_str(0x80,str1); //液晶显示提示信息

write_str(0xc0,str2); //液晶显示提示信息

init_ds1302(); //初始化ds1302

writetab(); //自定义字符写入CGRAM

// delay1(5);

// write_position(2,16);

// lcd_wdat(0x00); //显示自定义字符小喇叭

while(1)

{

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

if(!K1)

{

if(!K2)

{

set_ds1302(0x80,init2,7); //设置初始时间,日期,年月

beep();

}

if(!K3)

{

write_str(0xc0,str3); //显示报警信息

if(alarm_flag) //alarm_flag=1,开定时

{

write_position(2,16);

lcd_wdat(0x00); //显示自定义字符小喇叭

}

Play_alarmtime(); //查看报警时间

beep();

delay1(700);

write_str(0xc0,str2); //显示时间信息

if(alarm_flag) //alarm_flag=1,开定时

{

write_position(2,16);

lcd_wdat(0x00); //显示自定义字符小喇叭

}

}

if(!K4)

{

alarm_time(); //K4键设定报警时间

if(alarm_flag) //alarm_flag=1,开定时

{

write_position(2,16);

lcd_wdat(0x00); //显示自定义字符小喇叭

}

}

}

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

if(!K4)

{

beep();

alarm_flag=~alarm_flag;

if(alarm_flag) //alarm_flag=1,开定时

{

write_position(2,16);

lcd_wdat(0x00); //显示自定义字符小喇叭

}

else

{

write_position(2,16);

lcd_wdat(0x20); //显示自定义字符小喇叭

}

}

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

if(!K3&flag) //开始设定时间

{

write_ds1302(0x8e,0x00); //写保护控制字,允许写

write_ds1302(0x80,0x80); //停止时钟运行

write_ds1302(0x8e,0x80); //写保护控制字,禁止写

beep();

year=1;

count=((init[6]&0xf0)>>4)10+(init[6]&0x0f); //读当前年数据

}

while(year) //设定年

{

key_set(99,1,1);

if(!K3)

{

Set_W1302(0x8c);

Set_place(1,1);

year=0;

month=1;

count=((init[4]&0xf0)>>4)10+(init[4]&0x0f); //读当前月数据

}

}

while(month) //设定月

{

key_set(12,1,4);

if(!K3)

{

Set_W1302(0x88);

Set_place(1,4);

month=0;

day=1;

count=((init[3]&0xf0)>>4)10+(init[3]&0x0f); //读当前日数据

}

}

while(day) //设定日

{

key_set(31,1,7);

if(!K3)

{

Set_W1302(0x86);

Set_place(1,7);

day=0;

week=1;

count=init[5]&0x0f; //读当前星期数据

}

}

while(week) //设定星期

{

if(!K2)

{

beep();

if(count!=7)

count++;

else count=1;

}

if(!K1)

{

beep();

if(count!=1)

count--;

else count=7;

}

init1[1]=count%10;

if(flag)

{

write_position(1,15);

lcd_wdat(init1[1]+0x30);

}

else

{

write_position(1,15);

lcd_wdat(0x20);

}

if(!K3)

{

Set_W1302(0x8a);

write_position(1,15);

lcd_wdat(init1[1]+0x30);

week=0;

hour=1;

count=((init[2]&0xf0)>>4)10+(init[2]&0x0f); //读当前时数据

}

}

while(hour) //设定时

{

key_set(23,2,7);

if(!K3)

{

Set_W1302(0x84);

Set_place(2,7);

hour=0;

min=1;

count=((init[1]&0xf0)>>4)10+(init[1]&0x0f); //读当前分数据

}

}

while(min) //设定分

{

key_set(59,2,10);

if(!K3)

{

Set_W1302(0x82);

Set_place(2,10);

min=0;

sec=1;

count=((init[0]&0xf0)>>4)10+(init[0]&0x0f); //读当前秒数据

}

}

while(sec) //设定秒

{

key_set(59,2,13);

if(!K3)

{

Set_W1302(0x80);

Set_place(2,13);

sec=0;

count=0;

}

}

Play_nowtime();

Time_compare();

}

}

//

// Time0中断函数

//

void Time0(void) interrupt 1 using 0

{

TH0=0x4c; //50ms定时

TL0=0x00;

timecount++;

if(timecount>9)

{

timecount=0;

flag=~flag;

}

}

//

// 设定值写入DS1302

//

void Set_W1302(uchar addr)

{

uchar temp;

write_ds1302(0x8e,0x00);

temp=(init1[0]<<4)+init1[1];

write_ds1302(addr,temp);

write_ds1302(0x8e,0x80);

beep();

}

//

// 被设置数据闪动

//

void Set_Flash(uchar row,uchar col )

{

init1[0]=count/10;

init1[1]=count%10;

if(flag)

{ //显示

write_position(row,col);

lcd_wdat(init1[0]+0x30);

write_position(row,col+1);

lcd_wdat(init1[1]+0x30);

}

else

{ //清屏

write_position(row,col);

lcd_wdat(0x20);

write_position(row,col+1);

lcd_wdat(0x20);

}

}

//

// 指定位置显示

//

void Set_place(uchar row,uchar col)

{

write_position(row,col);

lcd_wdat(init1[0]+0x30);

write_position(row,col+1);

lcd_wdat(init1[1]+0x30);

}

//

// 显示当前时间

//

void Play_nowtime()

{

read_nowtime(0x81,init,7); //读出当前时间,读出7个字节

write_position(2,7);

lcd_wdat(((init[2]&0xf0)>>4)+0x30);

write_position(2,8);

lcd_wdat('0'+(init[2]&0x0f)); //读小时

// write_position(2,9);

// lcd_wdat(':');

write_position(2,10);

lcd_wdat('0'+((init[1]&0xf0)>>4));

write_position(2,11);

lcd_wdat('0'+(init[1]&0x0f)); //读分钟

// write_position(2,12);

// lcd_wdat(':');

write_position(2,13);

lcd_wdat('0'+((init[0]&0xf0)>>4));

write_position(2,14);

lcd_wdat('0'+(init[0]&0x0f)); //读秒

write_position(1,1);

lcd_wdat('0'+((init[6]&0xf0)>>4));

write_position(1,2);

lcd_wdat('0'+(init[6]&0x0f)); //读年

// write_position(1,3);

// lcd_wdat('/');

write_position(1,4);

lcd_wdat('0'+((init[4]&0xf0)>>4));

write_position(1,5);

lcd_wdat('0'+(init[4]&0x0f)); //读月

// write_position(1,6);

// lcd_wdat('/');

write_position(1,7);

lcd_wdat('0'+((init[3]&0xf0)>>4));

write_position(1,8);

lcd_wdat('0'+(init[3]&0x0f)); //读日

write_position(1,15);

lcd_wdat('0'+(init[5]&0x0f)); //读周

flash();

}

//

// 键设定函数

//

void key_set(uchar num,uchar row,uchar col )

{

if(!K2)

{

beep();

if(count!=num)

count++;

else count=0;

}

if(!K1)

{

beep();

if(count!=0)

count--;

else count=num;

}

Set_Flash(row,col);

}

//

// 报警时间设定

//

void alarm_time()

{

// if(!K4&flag) //开始设定报警时间

{

write_str(0xc0,str3); //液晶显示提示信息

Play_alarmtime();

beep();

hour=1;

count=((bj_time[2]&0xf0)>>4)10+(bj_time[2]&0x0f); //读当前时报警数据

while(hour) //设定时

{

key_set(23,2,7);

if(!K4)

{

Set_place(2,7);

bj_time[2]=((init1[0]<<4)|init1[1]);

beep();

hour=0;

min=1;

count=((bj_time[1]&0xf0)>>4)10+(bj_time[1]&0x0f); //读当前分报警数据

}

}

while(min) //设定分

{

key_set(59,2,10);

if(!K4)

{

Set_place(2,10);

bj_time[1]=((init1[0]<<4)|init1[1]);

beep();

min=0;

sec=0;

count=((bj_time[0]&0xf0)>>4)10+(bj_time[0]&0x0f); //读当前秒报警数据

write_str(0xc0,str2); //液晶显示提示信息

}

}

/

while(sec) //设定秒

{

key_set(59,2,13);

if(!K4)

{

Set_place(2,13);

bj_time[0]=((init1[0]<<4)|init1[1]);

beep();

min=0;

sec=0;

count=0;

write_str(0xc0,str2); //液晶显示提示信息

}

}/

}

}

//

// 报警时间显示

//

void Play_alarmtime()

{

write_position(2,7);

lcd_wdat(((bj_time[2]&0xf0)>>4)+0x30);

write_position(2,8);

lcd_wdat('0'+(bj_time[2]&0x0f)); //读小时

write_position(2,9);

lcd_wdat(':');

write_position(2,10);

lcd_wdat('0'+((bj_time[1]&0xf0)>>4));

write_position(2,11);

lcd_wdat('0'+(bj_time[1]&0x0f)); //读分钟

write_position(2,12);

lcd_wdat(':');

write_position(2,13);

lcd_wdat('0'+((bj_time[0]&0xf0)>>4));

write_position(2,14);

lcd_wdat('0'+(bj_time[0]&0x0f)); //读秒

}

//

// 时间比较

//

void Time_compare()

{

if(alarm_flag)

{

if(init[2]==bj_time[2])

{

if(init[1]==bj_time[1])

beep();

}

}

}

//

0x38命令字代表:8位数据总线,2行57点阵显示

02H命令字代表:<1> 把光标撤回到显示器的左上方; <2> 把地址计数器(AC)的值设置为0; <3> 保持DDRAM的内容不变。

这里所谓的回车就是光标。

以上就是关于单片机LCD1602错误显示全部的内容,包括:单片机LCD1602错误显示、大家帮忙看看这个1602的显示程序有什么问题void delay_1ms(uint x)//延时 { uchar j; while((x--)!=0) {、给个单片机液晶1602显示汉字的程序,谢谢等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zz/10134629.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-05
下一篇 2023-05-05

发表评论

登录后才能评论

评论列表(0条)

保存