久久久久久久999_99精品久久精品一区二区爱城_成人欧美一区二区三区在线播放_国产精品日本一区二区不卡视频_国产午夜视频_欧美精品在线观看免费

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 1010|回復: 5
收起左側

51單片機定時器0內調用lcd1602顯示函數就會出問題

[復制鏈接]
回帖獎勵 1 黑幣 回復本帖可獲得 1 黑幣獎勵! 每人限 1 次
ID:1081007 發表于 2024-6-18 20:25 | 顯示全部樓層 |閱讀模式
我在的定時器中斷函數內寫了一個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);        
}


回復

使用道具 舉報

ID:1080935 發表于 2024-6-19 08:37 | 顯示全部樓層
為什么要在中斷中調用顯示函數,顯示函數運行時間長,可能已經影響了你的定時時間,導致不正常(程序運行時間大于中斷定時時間,中斷程序剛執行完,馬上又進入中斷,也就是 基本在執行中斷程序)。
回復

使用道具 舉報

ID:161164 發表于 2024-6-19 09:34 | 顯示全部樓層
因為你寫1602顯示函數延時太長了,
根本用不了1ms,40us就夠了
清屏后才需要2ms延時

  1. void Delay40us(void)        //@11.0592MHz
  2. {
  3.         unsigned char data i;

  4.         i = 15;
  5.         while (--i);
  6. }

  7. //lcd1602.c
  8. /*******************************************************************************
  9. * 函 數 名       : lcd1602_write_cmd
  10. * 函數功能                 : LCD1602寫命令
  11. * 輸    入       : cmd:指令
  12. * 輸    出             : 無
  13. *******************************************************************************/
  14. void lcd1602_write_cmd(u8 cmd)//8位lcd
  15. {
  16.         LCD1602_RS=0;//選擇命令,RS=1時為寫命令,等于0時為寫數據
  17.         LCD1602_RW=0;//選擇寫,RW=1為讀,等于0位寫
  18.         LCD1602_E=0;//使能腳
  19.         LCD1602_DATAPORT=cmd;//準備命令,8位并行數據口
  20.         LCD1602_E=1;//使能腳E先上升沿寫入
  21.         LCD1602_E=0;//使能腳E后負跳變完成寫入
  22.                 Delay40us();//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  23. }

  24. /*******************************************************************************
  25. * 函 數 名       : lcd1602_write_data
  26. * 函數功能                 : LCD1602寫數據
  27. * 輸    入       : dat:數據
  28. * 輸    出             : 無
  29. *******************************************************************************/
  30. void lcd1602_write_data(u8 dat)
  31. {
  32.         LCD1602_RS=1;//選擇數據
  33.         LCD1602_RW=0;//選擇寫
  34.         LCD1602_E=0;
  35.         LCD1602_DATAPORT=dat;//準備數據
  36.         LCD1602_E=1;//使能腳E先上升沿寫入
  37.         LCD1602_E=0;//使能腳E后負跳變完成寫入
  38.                 Delay40us();//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<            
  39. }


  40. void lcd1602_init(void)//lcd1602初始化
  41. {
  42. //        u8 i=0;
  43.         lcd1602_write_cmd(0x38);//數據總線8位,顯示2行,5*7點陣/字符
  44. //        for(i=0;i<200;i++)
  45.                 lcd1602_write_cmd(0x0c);//顯示功能開,無光標,光標閃爍

  46.         lcd1602_write_cmd(0x06);//寫入新數據后光標右移,顯示屏不移動
  47.         lcd1602_write_cmd(0x01);//清屏   
  48.         delay_ms(2);//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<         
  49. }
復制代碼
回復

使用道具 舉報

ID:123289 發表于 2024-6-20 20:23 | 顯示全部樓層
T0的優先級比較高,當它進行服務程序后,其它低級的中斷就無法立即響應了,可以會丟失中斷。
回復

使用道具 舉報

ID:675287 發表于 2024-6-21 11:47 | 顯示全部樓層
這個顯示函數沒必要在中斷里面調用,運行時間大于中斷的間隔時間就會出問題了
回復

使用道具 舉報

ID:313517 發表于 2024-6-21 23:07 | 顯示全部樓層
中斷時間夠不夠,程序運行時間太長了,中斷時間太短了
回復

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規則

手機版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術交流QQ群281945664

Powered by 單片機教程網

快速回復 返回頂部 返回列表
主站蜘蛛池模板: 成人不卡 | 欧美国产视频 | 成人亚洲网站 | 亚洲女人天堂成人av在线 | 日韩一区二区在线视频 | 国产精品激情 | 亚洲色图图片 | 日本一区二区三区四区 | 夜夜爽99久久国产综合精品女不卡 | 久久久99精品免费观看 | 亚洲一区 | 免费天天干 | 国产精品视频在线观看 | 久久免费高清视频 | 亚洲狠狠丁香婷婷综合久久久 | 日韩欧美国产精品综合嫩v 一区中文字幕 | 911精品国产 | 三级黄色片在线播放 | 中文字幕精品视频在线观看 | 成人av免费播放 | 夜色www国产精品资源站 | 天天干天天爱天天 | 欧美一区二区免费电影 | 狠狠干夜夜草 | 亚洲一区国产 | 日韩三级电影一区二区 | 久久久av一区 | 国产成人一区 | 免费一级做a爰片久久毛片潮喷 | 国产一区久久久 | 日韩欧美在线观看 | 国产成人精品免费视频大全最热 | 精品久久久久久亚洲精品 | 视频1区2区| 天天影视色综合 | 毛片网站在线观看视频 | 久久精品99| 久久性色 | 在线观看亚洲欧美 | 成人久久一区 | 国产小视频在线观看 |