我在的定时器中断函数内写了一个500ms闪烁的指示灯(定时器定时是10ms),在主函数内调用lcd1602显示时间,程序下载后指示灯正常闪烁,时间也能正常显示,但当我在定时器中断函数内调用lcd1602显示函数,程序下载后屏幕上就只显示了个tete(定时器中断内lcd1602显示的内容),时间没有显示出来,随后我又重新试了几次,lcd屏幕要么显示错误的数据,要么就只显示tete,然后我又在main函数的while循环内调用串口发送函数来发送"ok",按理说串口应该会1ms接收一个数据(循环内加1ms延时函数),但实际上要1分多钟才能接收到一个数据!,而当我把中断内的lcd显示函数去掉后,串口就能正常接收了!!!有没有好心人说一下为什么呀
#include "public.h"
#include "lcd1602.h"
#include "ds1302.h"
#include"uart.h"
//uart.h,lcd1602.h内的代码都放在了最下面
sbit LED1=P2^4;
void lcd1602_showtime(void)
{
u8 gDS1302_YEARDAY_Change[11];//日,月,年
u8 gDS1302_TIME_Change[9];//秒,分,时
ds1302_read_time();
//BCD格式转为10进制
gDS1302_TIME_Change[8]='\0';//数组末尾添加结束符
gDS1302_TIME_Change[7]=(gDS1302_TIME[0]&0x0f)+0x30;//获取秒的低4位
gDS1302_TIME_Change[6]=(gDS1302_TIME[0]>>4)+0x30;//获取秒的高4位
gDS1302_TIME_Change[4]=(gDS1302_TIME[1]&0x0f)+0x30;//获取分的低4位
gDS1302_TIME_Change[3]=(gDS1302_TIME[1]>>4)+0x30;//获取分的高4位
gDS1302_TIME_Change[5]=':';
gDS1302_TIME_Change[1]=(gDS1302_TIME[2]&0x0f)+0x30;//获取时的低4位
gDS1302_TIME_Change[0]=(gDS1302_TIME[2]>>4)+0x30;//获取时的高4位
gDS1302_TIME_Change[2]=':';
gDS1302_YEARDAY_Change[10]='\0';////数组末尾添加结束符
gDS1302_YEARDAY_Change[9]=(gDS1302_TIME[3]&0x0f)+0x30;//获取日的低4位
gDS1302_YEARDAY_Change[8]=(gDS1302_TIME[3]>>4)+0x30;//获取日的高4位
gDS1302_YEARDAY_Change[6]=(gDS1302_TIME[4]&0x0f)+0x30;//获取月的低4位
gDS1302_YEARDAY_Change[5]=(gDS1302_TIME[4]>>4)+0x30;//获取月的高4位
gDS1302_YEARDAY_Change[7]='-';
gDS1302_YEARDAY_Change[1]='0';//赋值年的千位
gDS1302_YEARDAY_Change[0]='2';//赋值年的百位
gDS1302_YEARDAY_Change[3]=(gDS1302_TIME[6]&0x0f)+0x30;//获取年的低4位
gDS1302_YEARDAY_Change[2]=(gDS1302_TIME[6]>>4)+0x30;//获取年的高4位
gDS1302_YEARDAY_Change[4]='-';
lcd1602_show_string(0,0,gDS1302_YEARDAY_Change);
lcd1602_show_string(0,1,gDS1302_TIME_Change);
}
void time0_init(void)//定时器0初始化
{
TMOD|=0X01;//选择为定时器0模式,工作方式1
TH0=0XDC; //给定时器赋初值,定时10ms
TL0=0X00;
ET0=1;//打开定时器0中断允许
EA=1;//打开总中断
TR0=1;//打开定时器0
}
void main()
{
u8 temp=0;
lcd1602_init();
UART_Init();//串口初始化
lcd1602_clear();
time0_init();
ds1302_init();
while(1)
{
temp++;
uartsend_string("ok");//串口发送数据
if(temp>=10)
{
//LED1=~LED1;
}
delay_ms(1);
lcd1602_showtime();
}
}
void time0(void) interrupt 1 //定时器0中断函数
{
static u8 temp;
TH0=0XDC; //给定时器赋初值,定时10ms
TL0=0X00;
temp++;
if(temp==50)
{
temp=0;
LED1=~LED1;
}
lcd1602_show_string(12,0,"tete");
}
//uart.c
void UART_Init(void)//串口初始化。波特率:4800*2
{
SCON|=0X50; //设置为工作方式 1
TMOD|=0X20; //使用计时器1,工作方式 2(8位自动重装)
PCON=0X80; //波特率加倍
TH1=0xfa; //计数器初始值设置,对应4800波特率
TL1=0xfa;
//ES=1; //打开串口中断。注: 在只发送数据的情况下串口中断不要打开,不然发送会出问题!
EA=1; //打开总中断
TR1=1; //打开计数器1
TI=0;//发送标志清零
}
/*
函数功能:串口发送一个字节
dat :要发送的数据
*/
void uartsend_byte(u8 dat)
{
SBUF=dat;//数据存入SBUF
while(!TI);
TI=0;//发送标志清零,为下次发送做准备
}
/*
函数功能: 串口发送多个数据
dat :数据指针
len :数据长度
*/
void uartsend_string(u8 *pdat)
{
while(*pdat!='\0')
{
SBUF=*pdat;//数据存入SBUF
while(!TI);
TI=0;//发送标志清零,为下次发送做准备
pdat++;
}
}
//lcd1602.c
/*******************************************************************************
* 函 数 名 : lcd1602_write_cmd
* 函数功能 : LCD1602写命令
* 输 入 : cmd:指令
* 输 出 : 无
*******************************************************************************/
void lcd1602_write_cmd(u8 cmd)//8位lcd
{
LCD1602_RS=0;//选择命令,RS=1时为写命令,等于0时为写数据
LCD1602_RW=0;//选择写,RW=1为读,等于0位写
LCD1602_E=0;//使能脚
LCD1602_DATAPORT=cmd;//准备命令,8位并行数据口
delay_ms(1);
LCD1602_E=1;//使能脚E先上升沿写入
delay_ms(1);
LCD1602_E=0;//使能脚E后负跳变完成写入
}
/*******************************************************************************
* 函 数 名 : lcd1602_write_data
* 函数功能 : LCD1602写数据
* 输 入 : dat:数据
* 输 出 : 无
*******************************************************************************/
void lcd1602_write_data(u8 dat)
{
LCD1602_RS=1;//选择数据
LCD1602_RW=0;//选择写
LCD1602_E=0;
LCD1602_DATAPORT=dat;//准备数据
delay_ms(1);
LCD1602_E=1;//使能脚E先上升沿写入
delay_ms(1);
LCD1602_E=0;//使能脚E后负跳变完成写入
}
void lcd1602_init(void)//lcd1602初始化
{
// u8 i=0;
lcd1602_write_cmd(0x38);//数据总线8位,显示2行,5*7点阵/字符
// for(i=0;i<200;i++)
lcd1602_write_cmd(0x0c);//显示功能开,无光标,光标闪烁
lcd1602_write_cmd(0x06);//写入新数据后光标右移,显示屏不移动
lcd1602_write_cmd(0x01);//清屏
}
/*******************************************************************************
* 函 数 名 : lcd1602_show_string
* 函数功能 : LCD1602显示字符串
* 输 入 : x,y:显示坐标,x=0~15,y=0~1;
str:显示字符串
* 输 出 : 无
*******************************************************************************/
void lcd1602_show_string(u8 x,u8 y,u8 *str)
{
u8 i=0;
if(y>1||x>15)return;//行列参数不对则强制退出
if(y<1) //第1行显示
{
while(*str!='\0')//字符串是以'\0'结尾,只要前面有内容就显示
{
if(i<16-x)//如果字符长度超过第一行显示范围,则在第二行继续显示
{
lcd1602_write_cmd(0x80+i+x);//第一行显示地址设置
}
else
{
lcd1602_write_cmd(0x40+0x80+i+x-16);//第二行显示地址设置
}
lcd1602_write_data(*str);//显示内容
str++;//指针递增
i++;
}
}
else //第2行显示
{
while(*str!='\0')
{
if(i<16-x) //如果字符长度超过第二行显示范围,则在第一行继续显示
{
lcd1602_write_cmd(0x80+0x40+i+x);
}
else
{
lcd1602_write_cmd(0x80+i+x-16);
}
lcd1602_write_data(*str);
str++;
i++;
}
}
}
/*******************************************************************************
* 函 数 名 : lcd1602_show_char
* 函数功能 : LCD1602显示字符
* 输 入 : x,y:显示坐标,x=0~15,y=0~1;
str:显示字符
* 输 出 : 无
*******************************************************************************/
void lcd1602_show_char(u8 x,u8 y,u8 chr)
{
if(y>1||x>15)return;//行列参数不对则强制退出
if(y<1) //第1行显示
{
lcd1602_write_cmd(0x80+x);//第一行显示地址设置
lcd1602_write_data(chr);//显示内容
}
else //第2行显示
{
lcd1602_write_cmd(0x80+0x40+x);
lcd1602_write_data(chr);
}
}
void lcd1602_clear(void)
{
lcd1602_write_cmd(0x01);
}
|