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

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 2756|回復: 4
收起左側

單片機LCD12864全是翱,拿手碰一下才會正常顯示

[復制鏈接]
ID:658517 發表于 2019-12-18 17:50 | 顯示全部樓層 |閱讀模式
寫的程序前幾天運行都是正確的,今天運行就全是翱字,拿手碰一下才會正常顯示
#include "msp430f149.h"
typedef unsigned char uchar;   //給個新名字代替,這里不涉及struct
typedef unsigned int  uint;    //在有指針的場合,typedef要比#define好,無符號類型能保存2倍于有符號類型的正整數數據
//DS18B20端口設置
#define DQ1    P2OUT|=BIT4        //DQ置位
#define DQ0    P2OUT&=~BIT4       //DQ復位
#define DQ_in  P2DIR&=~BIT4       //設DQ為輸入
#define DQ_out P2DIR|=BIT4        //設DQ為輸出
#define DQ_val (P2IN&BIT4)        //讀DQ電平
//通過定時器A實現精確的N個微秒的延時,因為DS18B20是one-wire類型,對時間的要求非常嚴格
void DelayNus(uint n)
{
    TACTL|=TASSEL_2+ID_3+MC_1;    //SMCLK,8分頻,增計數模式
    //CCTL0|=CCIE;                //中斷允許
    CCR0=n;                       //CCR0=1時捕捉的是1us(n/1M)
    while(!(TACTL&BIT0));         //等待定時Nus后置位中斷標志TAIFG  while(!TAIFG) 1即有中斷發生
    TACTL=TACLR;                  //停止計數,在于清除了計數器設置,TACLR=1
    TACTL&=~BIT0;                 //清除中斷標志TAIFG
}
//初始化DS18B20,等待DS18B20回復一個presence pulse,若在60-240us內讀到回復的脈沖信號,表示DS18B20存在
uchar Init_18B20(void)
{
            uchar flag;           //定義一標志信號,1失敗,0成功,
            DQ_out;               //設置DQ為輸出,可不要
            DQ0;                  //拉低總線
            DelayNus(500);        //延時500us,產生復位脈沖(480-960)
            DQ1;                  //釋放總線
            DelayNus(65);         //等待15-60us,且要在60-240us內讀到返回的脈沖信號,計算后得到延時時間最好要在60-75us
            DQ_in;                //DQ設置為輸入狀態,以讀取DS18B20存在狀態,必須要有
            DelayNus(5);          //短暫延時一下確保讀取成功
            if(DQ_val)            //若讀到高電平則無DS18b20
            {
              flag=1;             //初始化失敗
            }
            else
            {
              flag=0;             //初始化成功
            }
            DQ_out;               //設置DQ為輸出,必須要有
            DQ1;                  //釋放總線
            DelayNus(400);        //>=480us
            return flag;          //返回標志信號
}
//單片機向DS18B20寫入一個字節的數據,內部具體包括寫0、1
void Write_18B20(uchar wdata)
{
    uchar i;
    for(i=0x01;i!=0;i<<=1)     //一個字共有8位,讀寫都從低位開始
    {
        DQ0;                   //拉低總線,
        DelayNus(5);           //延時5us,至少1us
        if((wdata&i)==0)       //滿足則末尾是0,即寫入的是0
           DQ0;                //寫0單片機輸出低電平
        else                   //不滿足就是末尾為1,即寫入1
           DQ1;                //寫1單片機輸出高電平
        DelayNus(50);          //15-60us
        DQ1;                   //釋放總線,等待總線恢復
        DelayNus(10);          //延時10us
    }
}
//單片機從DS18B20讀取一個字節(8bit)的數據
uchar Read_18B20(void)
{
    uchar i;                  //當作檢測信號
    uchar temp;               //temp用于存儲從DS18B20讀取出來的8位數據
    for(i=0x01;i!=0;i<<=1)
    {
        DQ0;                   //拉低總線,產生讀信號
        DelayNus(5);           //延時5us,至少1us
        DQ1;                   //釋放總線,準備讀數據
        DelayNus(5);           //延時5us
        DQ_in;                 //設置為輸入狀態,以讀取數據
        _NOP();                //必須在15us內讀取DS18B20發送的數據位
        if(DQ_val)
        {
                temp=temp|i;       //讀1就寫1
        }
        else
        {
                temp=temp&(~i);    //讀0就寫0
        }
        DelayNus(45);          //延時45us
        DQ_out;                //設置端口為輸出
        DQ1;                   //釋放總線
        DelayNus(10);
    }
    return temp;               //返回從DS18B20讀出的8位數據
}
//讓DS18B20開始轉換溫度
void ChangeTemp(void)
{
    uchar i;
        Init_18B20();
        Write_18B20(0xcc);     //跳過ROM配置(skip rom),單線直接這樣設置
        Write_18B20(0x44);     //啟動溫度轉換(默認值+85),有了這句話才會開始測量溫度
    for(i=20;i>0;i--)
    DelayNus(60000);       //延時800ms以上,若是一直刷著,就不用這個延時
                           //一分鐘延時就可以一分鐘檢測一次
}
//發送讀取溫度命令
void ReadTempCom(void)
{
        Init_18B20();
    Write_18B20(0xcc);     //都需要3步(1.初始化2.rom設置3.寫字節)
    Write_18B20(0xbe);     //發送讀ScratchPad命令
}
//從DS18B20的ScratchPad讀取溫度轉換結果
uint Do1Convert(void)
{
    uchar i;
    uchar temp_l;               //char是8bit,先存放低位
    uint realtemp;              //int是16bit
    do
    {
       i=Init_18B20();          //把flag的值賦給I,判斷是否初始換成功
    }
    while(i);                   //0成功跳出
        ChangeTemp();                   //先寫轉換命令
        ReadTempCom();                  //然后等待轉換完后發送讀取溫度命令
        temp_l=Read_18B20();            //讀取溫度值共16位,必須先讀低字節
        realtemp=Read_18B20();          //讀高位
        realtemp=(realtemp<<8)|temp_l;  //高8位先左移8位后再與低位相或得16位的溫度值
        return realtemp;                //返回讀取的溫度值
}


#include "msp430f149.h"
typedef unsigned char uchar;
typedef unsigned int  uint;
//LCD12864端口配置
#define LCD_RS_H      P3OUT|=BIT0      //數據
#define LCD_RS_L      P3OUT&=~BIT0     //指令
#define LCD_RW_H      P3OUT|=BIT1      //讀
#define LCD_RW_L      P3OUT&=~BIT1     //寫
#define LCD_EN_H      P3OUT|=BIT2      //使能開
#define LCD_EN_L      P3OUT&=~BIT2     //使能關
#define LCD_DataIn    P4DIR=0x00       //數據口方向設置為輸入
#define LCD_DataOut   P4DIR=0xff       //數據口方向設置為輸出
#define LCD2MCU_Data  P4IN             //LCD向單片機輸入數據
#define MCU2LCD_Data  P4OUT            //單片機向LCD輸出數據
#define LCD_CMDOut    P3DIR|=0x07      //P3口的低三位(RS,RW,EN)設置為輸出
#define LCD_PSB_H     P3OUT|=BIT3      //并行
#define LCD_PSB_L     P3OUT&=~BIT3     //串行
#define LCD_RST_L     P3OUT&=~BIT4     //復位  低電平有效
//延時約1ms程序
void Delay_1ms(void)
{
        uchar i;
        for(i=150;i>0;i--);
    _NOP();               //延時幾us,自帶函數,用于短暫延時
}
//延時N個1ms的時間
void Delay_Nms(uint n)
{
    uint i;
    for(i=n;i>0;i--)
    Delay_1ms();
}
//判忙
void Check_Busy(void)
{
    uchar lcdtemp = 0;
    LCD_CMDOut;             //P3口的低三位設置為輸出
    LCD_RS_L;               //命令
    LCD_RW_H;               //讀
    LCD_DataIn;             //P4端口設置為輸出
    do                      //判忙判斷的是最高位數據
    {
       LCD_EN_H;
       _NOP();
       lcdtemp = LCD2MCU_Data;  //讀取LCD忙碌狀態
       LCD_EN_L;
    }
    while(lcdtemp&0x80);        //若為0表示不忙,一直等到LCD不忙(即最高位是0)才跳出函數
}
//寫命令
void Write_Cmd(uchar cmd)
{
    Check_Busy();           //判忙
    LCD_DataOut;
    LCD_RS_L;               //命令
    LCD_RW_L;               //寫
    MCU2LCD_Data=cmd;       //將命令寫入端口
    LCD_EN_H;
    _NOP();
    LCD_EN_L;
}
//寫數據
void  Write_Data(uchar dat)
{
    Check_Busy();
    LCD_DataOut;
    LCD_RS_H;
    LCD_RW_L;
    MCU2LCD_Data=dat;
    LCD_EN_H;
    _NOP();
    LCD_EN_L;
}
void Disp_HZ(uchar addr,const uchar * pt,uchar num)
{
    uchar i;

    Write_Cmd(addr);
           for(i = 0;i < (num*2);i++)
        Write_Data(*(pt++));
}
/*****讀數據
uchar Read_Data(void)
{
  uchar RData;
  LCD_DataIn;
  Check_Busy();
  LCD_RS_H;
  LCD_RW_H;
  LCD_EN_L;
  LCD_EN_H;
  RData=LCD2MCU_Data;    //寄存數據
  LCD_EN_L;
  return RData;          //返回讀到的數據
}
*****/
//初始化液晶顯示屏
void Init_Lcd(void)
{
        //LCD_RST_L;          //復位
        LCD_PSB_H;          //并行
    LCD_CMDOut;         //液晶控制端口設置為輸出
    Delay_Nms(500);
    Write_Cmd(0x30);    //基本指令集
    Delay_1ms();
    Write_Cmd(0x02);    // 地址歸位
    Delay_1ms();
        Write_Cmd(0x0c);    //整體顯示打開,游標關閉
    Delay_1ms();
        Write_Cmd(0x01);    //清除顯示
    Delay_1ms();
        Write_Cmd(0x06);    //游標右移
    Delay_1ms();
        Write_Cmd(0x80);    //設定顯示的起始地址
}
/*****
//在坐標(x,y)處連續顯示一個字符串,共x*y=8*4=32處位置。
void Lcd_Print(uchar x,uchar y,uchar *adata)
{
      uchar address;
      uchar i=0;
          if(0==y)      //y=0表示第一行,x表示第幾列,共8列
          {
             address=0x80+x;       //一行x列
          }
          else if(1==y)
          {
                  address=0x90+x;
          }
          else if(2==y)
          {
                  address=0x88+x;
          }
          else if(3==y)
          {
                  address=0x98+x;
          }
          else
          {
                  return;
          }
      Write_Cmd(address);       //先寫地址
      while(*(adata+i))        //字符串數組末尾有一個'/0',用i自加讓他每位都取到并判斷是否自加到末尾
      {
        Write_Data(*(adata+i));
        i++;
      }
}
*****/


#include <msp430f149.h>
#include "LCD12864.h"                 //聲明所有調用函數庫
#include "DS18B20.h"
uchar line1[]={"檢測的溫度值為:"};       //先定義要顯示的漢字
uchar *str1=line1;                    //str表示指針,可以存放地址,這句話的意思就是把"檢"的地址賦給指針變量str1,所以*str1的值就是"檢"
uchar dN[6];                          //存放轉換完成的溫度
void Disp_Numb(uint realtemp);        //先聲明后面要用到的函數
void main(void)
{
    uchar i;
    WDTCTL=0x5A80;
    //430中,一個時鐘周期=MCLK晶振的倒數,如MCLK是8M,則時鐘周期為1/8us
    BCSCTL1&=~XT2OFF;          //打開XT2高頻晶體振蕩器,選擇系統主時鐘為8MHz
    do
    {
       IFG1&=~OFIFG;           //清除晶振失敗標志
       for(i=0xFF;i>0;i--);    //等待8MHz晶體起振,穩定時間
    }
    while((IFG1&OFIFG));       //若晶振失效標志仍存在
    BCSCTL2|=SELM_2+SELS;      //選擇MCLK和SMCLK為XT2
    TACTL|=TASSEL_2+ID_3;      //計數時鐘選擇SMLK=8MHz,8分頻
    Init_Lcd();                //液晶初始化
    while(1)                   //循環進行溫度數值轉換
    {
      Disp_Numb(Do1Convert());     //將十一位的溫度值轉換成六位整數
      Disp_HZ(0x80,line1,8);
      //在12864顯示溫度值
      //0x30 表示字符‘0’,所有數字都加‘0’表示將十進制的數轉換成相應數字的字符對應的ASCII值
      Write_Cmd(0x90);             //第二行
      Write_Data(dN[5]+0x30);      //十位
      Write_Data(dN[4]+0x30);      //個位
      Write_Data('.');             //小數點
      Write_Data(dN[3]+0x30);      //十分位
      Write_Data(dN[2]+0x30);      //百分位
      Write_Data(dN[1]+0x30);      //千分位
      Write_Data(dN[0]+0x30);      //萬分位
    }
}
//將從DS18B20讀取的溫度數據轉換成六位整數,并存儲在字符數組dN【6】中
//順序是 5 4 . 3 2 1 0,依次是十位,個位,十分位···
//因為是數字體溫計,常理來說不存在負溫度,若是負溫度,則需要取反加1
void Disp_Numb(uint realtemp)
{
    uchar i;
    for(i=6;i>0;i--)    //6次
    dN=0;            //先置0
    //數值轉換算法,將十一位二進制溫度值轉換成六位整型數據
    if(realtemp&BIT0)      //滿足就是最低位(2的-4次方)為1
    {
        dN[0]=5;           //1/(2*2*2*2)=0.0625
        dN[1]=2;
        dN[2]=6;
    }
    if(realtemp&BIT1)      //2的-3次方
    {
        dN[1]+=5;          //1/2*2*2=0.125
        dN[2]+=2;
        dN[3]+=1;
    }
    if(realtemp&BIT2)      //2的-2次方
    {
        dN[2]+=5;          //1/2*2=0.25
        dN[3]+=2;
        if(dN[2]>=10)      //判斷是否需要進位
        {                  //百分位是6+2+5級滿足條件
           dN[2]-=10;      //百分位-1
           dN[3]+=1;       //十分位+1
        }
    }
    if(realtemp&BIT3)      //后面的都是如此
    {
        dN[3]+=5;
    }
    if(realtemp&BIT4)
    {
        dN[4]+=1;
    }
    if(realtemp&BIT5)
    {
        dN[4]+=2;
    }
    if(realtemp&BIT6)
    {
        dN[4]+=4;
    }
    if(realtemp&BIT7)
    {
        dN[4]+=8;
        if(dN[4]>=10)
        {
           dN[4]-=10;
           dN[5]+=1;
        }
    }
    if(realtemp&BIT8)
    {
        dN[4]+=6;
        dN[5]+=1;
        if(dN[4]>=10)
        {
           dN[4]-=10;
           dN[5]+=1;
        }
    }
    if(realtemp&BIT9)
    {
        dN[4]+=2;
        dN[5]+=3;
        if(dN[4]>=10)
        {
           dN[4]-=10;
           dN[5]+=1;
        }
    }
    if(realtemp&BITA)
    {
        dN[4]+=4;
        dN[5]+=6;
        if(dN[4]>=10)
        {
           dN[4]-=10;
           dN[5]+=1;
        }
        if(dN[5]>=10)
        {
           dN[5]-=10;
        }
    }
}




回復

使用道具 舉報

ID:667739 發表于 2019-12-18 20:26 | 顯示全部樓層
延時出錯了
回復

使用道具 舉報

ID:631951 發表于 2019-12-19 08:06 | 顯示全部樓層
我也有過這樣的經歷,就是前幾天,但是12864帶漢字庫的,也是整個屏幕都是翔,我當時xy坐標的事,調了調xy坐標就好了
回復

使用道具 舉報

ID:524818 發表于 2019-12-19 12:14 | 顯示全部樓層
既然之前程序運行正常,并且用手碰一下就正常,是不是考慮一下硬件電路或者電源供電及靜電引起的?
回復

使用道具 舉報

ID:662518 發表于 2019-12-19 14:14 | 顯示全部樓層
手碰一下就成了!嗯。。。。查硬件
回復

使用道具 舉報

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

本版積分規則

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

Powered by 單片機教程網

快速回復 返回頂部 返回列表
主站蜘蛛池模板: 日日操av| 欧美一区二区三 | 91社区视频 | 蜜臀网 | 91在线影院 | 日韩中文字幕免费在线观看 | 欧美亚洲另类在线 | 欧美男人亚洲天堂 | 精品一区二区久久久久久久网精 | 成人久久久久久久久 | 国产精品久久久乱弄 | 日韩欧美精品一区 | 99精品视频一区二区三区 | 一区二区三区国产好的精 | 一级毛片大全免费播放 | 日韩毛片在线免费观看 | 日日射夜夜骑 | 高清一区二区视频 | 一区二区免费 | 国产精品久久久久久久久久久久冷 | 国产精品一区二区在线观看 | 国产精品精品视频一区二区三区 | 精品国产第一区二区三区 | 亚洲一区二区三区桃乃木香奈 | 天天操天天干天天曰 | 日韩在线中文字幕 | 成人欧美一区二区三区在线观看 | 久久久无码精品亚洲日韩按摩 | 99精品国自产在线 | 天天干天天插 | 美女视频一区二区三区 | 国产在线精品一区二区 | 国产欧美日韩在线 | 欧美一区二区三区国产 | 国产精品久久久久久久久久久免费看 | 亚洲九色| 久久精品色欧美aⅴ一区二区 | 国产中文视频 | 久久国产一区二区 | 久久精品视频免费观看 | 欧美日韩一区二区在线观看 |