我在的定時器中斷函數內寫了一個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);
}
|