MSP430F149的DS18B20C语言程序

来源:互联网 发布:手机闪存测试软件 编辑:程序博客网 时间:2024/06/06 01:13
#include          "msp430x14x.h"            // Standard Equations 
//-------------------------I/O口定义------------------------------------ 
#define DS_DIR   P6DIR 
#define DS_OUT   P6OUT 
#define DS_IN    P6IN 
#define DS18B20  BIT4 
 
#define W18BUS_1 {DS_DIR |= DS18B20;DS_OUT |= DS18B20;_NOP();DS_DIR &= ~DS18B20;} 
 
                         //DS18B20总线写"1" 
#define W18BUS_0 {DS_DIR |= DS18B20;DS_OUT &= ~DS18B20;_NOP();} 
                         //DS18B20总线写"0" 
            
#define SF18BUS (DS_DIR &= ~DS18B20)         //释放DS18B20总线 
#define R18BUS  (DS_IN & DS18B20) 
 
 
#define FLAG_TEMP_RET  0x01             //DS18B20复位OK 
#define FLAG_TEMP_OK   0x02              //DS18B20 传感器OK 
#define FLAG_TEMP_OVER 0x04           //搜索DS18B20结束 
 
#define WDT_CLR (WDTCTL = WDTPW + WDTCNTCL + WDTSSEL + WDTIS0)    //看门狗清零 
//----------------------------------------------------------------------   
 void Delay(unsigned int x);        //延时程序   
 void Temp(void);   
//-----------------------全局变量定义------------------------------   
   
unsigned char ID[5][8];                     //ID[5][8]为检索到的地址   
unsigned char TEMP_NUMBER;                  //温度传感器数量   
unsigned int  TEMP[5];                      //温度值   
float    fT[5];   
   
//-----------------------软件标志定义------------------------------   
unsigned int FLAG;    //软件标志   
//FLAG.0--DS18B20复位OK  FLAG.1--温度传感器OK  FLAG.2--搜索温度结束   
   
//****************************************************************************   
//模块名:Init_DS18B20   
//描述:  初试化DS18B20子程序。   
//****************************************************************************   
void Init_DS18B20(void)   
  {   
    DS_DIR = DS18B20;   
    DS_OUT = 0;   
  }   
    
void main(void)   
  {   
    unsigned int iq0;   
    WDTCTL = WDTPW +WDTHOLD;     //停看门狗   
 //---------------------------系统时钟定义---------------------   
    BCSCTL1&=~XT2OFF;                       //打开XT2振荡器   
    do   
      {   
        IFG1 &= ~OFIFG;                     // 清除振荡器失效标志   
        for (iq0 = 0xFF; iq0 > 0; iq0--);   // 延时,等待XT2起振   
      }   
    while ((IFG1 & OFIFG) != 0);            // 判断XT2是否起振   
   
    BCSCTL2 =SELM_2+DIVS_0+SELS;            //选择MCLK、SMCLK为XT2   
    Init_DS18B20();                            
    _EINT();   
    while (1)   
      {   
        Temp();   
        for (iq0 = 5; iq0 != 0; iq0--)   
          {   
            fT[iq0-1] = 0.0625 * TEMP[iq0-1];   
          }   
        _NOP();   
      }    
  }   
   
//****************************************************************************   
//模块名:Rst_DS18B20     
//描述:  复位温度传感器DS18B20子程序。     
//****************************************************************************   
void Rst_DS18B20(void)   
  {   
    unsigned int I;   
    FLAG |= FLAG_TEMP_RET;      //预设ds18b20复位OK    
    W18BUS_0;                   //拉低总线   
    Delay(960);                  //延时480uS   
    SF18BUS;                    //释放总线   
    Delay(50);                  //延时15-60uS   
    I = 890;   
    while (/*(R18BUS) && */(I != 0)) I--;     //循环条件:ds18b20总线不为“0”   
                                       //并且延时总时间不够4mS   
    if (I != 0)   
      {   
        _NOP();   
        while(!(R18BUS));   
      }   
    else   
      {   
        FLAG &= ~FLAG_TEMP_RET;   
      }   
  }   
//****************************************************************************   
//模块名:Read_BUS_bit    
//描述:  从单总线读一位数据子程序。   
//功能:  DATA右移一位,从单总线读一位数据到DATA的最高位,   
//****************************************************************************   
unsigned char Read_BUS_bit (unsigned char DATA)   
  {   
    unsigned char I;   
    DATA >>= 1;   
    SF18BUS;                       //释放总线   
    I = 30;   
    while (I != 0) I--;   
    _DINT();   
    W18BUS_0;                      //拉低总线2uS   
    _NOP();   
    _NOP();   
    _NOP();   
    _NOP();   
    _NOP();   
    W18BUS_1;                      //拉高总线   
    I = 20;   
    while (I != 0) I--;   
    if (R18BUS != 0)   
      DATA |= 0X80;   
    _NOP();   
    _EINT();   
    I = 25;                         //延时45uS   
    while (I != 0) I--;   
    return (DATA);   
  }   
//****************************************************************************   
//模块名:Write_BUS_bit     
//描述:  向单总线写一位数据子程序。   
//功能:  把DATA的最低一位数据写到单总线上,DATA右移一位     
//****************************************************************************   
unsigned char Write_BUS_bit (unsigned char DATA)   
  {   
    unsigned char I;   
    _DINT();   
    W18BUS_1;   
    if (DATA&0X01)   
      {   
        DS_DIR |=  DS18B20;   
        DS_OUT &= ~DS18B20;   
        _NOP();   
        _NOP();   
        DS_OUT |=  DS18B20;   
      }   
    else   
      {   
        W18BUS_0;   
      }   
    _EINT();   
        I = 16;                         //延时15uS   
        while (I != 0) I--;   
    DATA >>= 1;   
    I = 80;   
    while (I != 0) I--;   
    W18BUS_1;   
    _NOP();   
    _NOP();   
    return (DATA);   
  }   
//****************************************************************************   
//模块名:Read_BUS_Byte     
//描述:  从单总线读一个字节数据子程序。   
//功能:  返回从单总线读出的一个字节数据,调用了Read_BUS_bit   
//****************************************************************************   
unsigned char Read_BUS_Byte (void)   
  {   
    unsigned char I;   
    unsigned char DATA;   
    for (I = 8;I != 0;I--)   
      {   
        DATA = Read_BUS_bit(DATA);   
      }   
    return (DATA);   
  }   
//****************************************************************************   
//模块名:Write_BUS_Byte     
//描述:  向单总线写一个字节数据子程序。   
//功能:  调用Write_BUS_bit,把DATA数据写到单总线上    
//****************************************************************************   
void Write_BUS_Byte (unsigned char DATA)   
  {   
    unsigned char I;   
    for (I = 8;I != 0;I--)   
      {   
        DATA = Write_BUS_bit(DATA);   
      }   
  }   
     
//****************************************************************************   
//模块名:Read_BUS_2bit     
//描述:  从单总线读2位数据子程序。   
//功能:  调用Read_BUS_bit,从单总线读2位数据到DATA高位,并返回DATA      
//****************************************************************************   
unsigned char Read_BUS_2bit (void)   
  {   
    unsigned char DATA;   
    DATA = 0;   
    DATA = Read_BUS_bit(DATA);   
    DATA = Read_BUS_bit(DATA);   
    return(DATA);   
  }   
     
//****************************************************************************   
//模块名:Right_Move_Temp    
//描述:  循环右移子程序。    
//****************************************************************************   
void Right_Move_Temp(unsigned char *PA,unsigned char *PB)   
  {   
    unsigned char DATA,I;   
    DATA = 0;   
    if (*PA & 0X01) DATA = 0X80;   
    PB = PB+7;   
    if (*PB & 0X01) DATA |= 0X01;   
    for (I=0; I<7; I++)   
      {   
        *PA >>= 1;   
        *PB >>= 1;   
        if (*(PA+1) & 0X01) *PA |= 0X80;   
        else *PA &= 0X7F;   
        if (*(PB-1) & 0X01) *PB |= 0X80;   
        else *PB &= 0X7F;   
        PA++;   
        PB--;   
      }   
    *PA >>= 1;   
    *PB >>= 1;   
    if (DATA & 0X80) *PA |= 0X80;   
    else *PA &= 0X7F;   
    if (DATA & 0X01) *PB |= 0X80;   
    else *PB &= 0X7F;   
  }   
//****************************************************************************   
//模块名:CRC_Verify   
//描述:  CRC校验子程序。    
//****************************************************************************   
const unsigned char CRC_H[16] =   
  {0x00,0x9d,0x23,0xbe,0x46,0xdb,0x65,0xf8,0x8c,0x11,0xaf,0x32,0xca,0x57,0xe9,0x74};   
const unsigned char CRC_L[16] =   
  {0x00,0x5e,0xbc,0xe2,0x61,0x3f,0xdd,0x83,0xc2,0x9c,0x7e,0x20,0xa3,0xfd,0x1f,0x41};   
   
unsigned char CRC_Verify(unsigned char * buf,unsigned char length)   
  {   
    unsigned char crc = 0x00;   
    do   
      {   
        crc ^= *buf;   
        crc = CRC_H[crc >> 4] ^ CRC_L[crc & 0x0f];   
        buf++;   
      }   
    while(--length);   
    return(crc);                   
  }   
//****************************************************************************   
//模块名:Search_ROM    
//描述:  搜索ds18b20的地址子程序。    
//****************************************************************************   
void Search_ROM (void)   
  {   
    unsigned char A[8],B[8];               //A[8]为已知ID中最大的ID值,B[8]节点表   
    unsigned char POINT0,POINT;            //POINT0指向上次检索的最后一个节点位置;   
                                        //POINT指向当前节点位置;   
    unsigned char I,J,K;                   //I,J为循环计数器;K为检索失败次数   
    unsigned char DATA,CRC;   
    unsigned char *PA,*PB;   
   
    PA = &A[0];   
    PB = &B[0];   
   
    J = 0xFF;   
    FLAG |= FLAG_TEMP_OK;                  //预设传感器正常   
    I = 5;                                 //   
    while ((I != 0) && ~(FLAG & FLAG_TEMP_RET))   
      {   
        Rst_DS18B20();            //传感器复位,复位成功或5次复位失败跳出循环   
        I--;   
      }   
    if (FLAG && FLAG_TEMP_RET)   
      {                                   //复位成功,开始搜索ds18b20的地址   
        for (I = 0 ; I <8 ; I++)   
          {   
            A[I] = 0;                        //已知ID中最大的ID值"0"   
            B[I] = 0;                        //所有节点都未处理   
          }   
        POINT0 = 63;   
        POINT = 0XFF;   
        K = 0;   
        for (J = 0 ; (J<5 && K<5 && POINT != 0) ; J++)   
          {   
            Rst_DS18B20();                      //传感器复位   
            Write_BUS_Byte (0XF0);            //写搜索ID命令   
            POINT = 0;   
            FLAG &= ~FLAG_TEMP_OVER;   
            for (I = 0 ; ((I  64) && ~(FLAG & FLAG_TEMP_OVER)) ; I++)   
              {   
                Right_Move_Temp(PA,PB);         //循环右移   
                DATA = Read_BUS_2bit();         //读ds18b20两位   
                switch (DATA &= 0XC0)   
                  {   
                    case 0:                       //读数为“0”,此位为一节点   
                      {   
                        if (B[0] & 0X80)   
                          {                           //本节点已处理   
                            DATA = 0XFF;   
                            A[7] |= 0X80;               //地址表写"1"   
                          }   
                        else   
                          {                           //本节点未处理   
                            if (I == POINT0)   
                              {                        //当前节点是最后的未处理节点   
                                DATA = 0XFF;   
                                A[7] |= 0X80;            //地址表写"1"   
                                B[0] |= 0X80;            //节点表写"1"   
                              }   
                            else   
                              {   
                                A[7] &= ~0X80;           //地址表写"0"   
                                POINT = I;               //设置节点指针   
                              }   
                          }   
                        DATA = Write_BUS_bit (DATA);  //选择方向   
                      }   
                    break;   
                    case 0X80:   
                      {   
                        DATA = 0X00;   
                        DATA = Write_BUS_bit (DATA);  //写"0"   
                        A[7] &= ~0X80;      
                      }   
                    break;   
                    case 0X40:   
                      {   
                        DATA = 0X0F;   
                        DATA = Write_BUS_bit (DATA);  //写"1"   
                        A[7] |= 0X80;    
                      }   
                    break;   
                    case 0XC0:   
                      {   
                        FLAG |= FLAG_TEMP_OVER;   
                      }   
                    break;   
                    default:   
                    break;    
                  }   
              }                                   //I循环结束   
            if(!(FLAG & FLAG_TEMP_OVER))   
              {   
                CRC = CRC_Verify(PA,7);   
                if (CRC == A[7])   
                  {   
                    for (I=0; I<8; I++) ID[J][I] = A[I];   
                    POINT0 = POINT;   
                    K = 0;   
                  }   
                else    
                  {   
                    J--;   
                    K++;   
                  }   
              }   
          }                                     //J循环结束   
        TEMP_NUMBER = J;   
      }   
    else   
      {                     //复位失败,置失败标志   
        FLAG &= FLAG_TEMP_OK;   
      }   
  }   
//****************************************************************************   
//模块名:Read_Temp     
//描述:  读温度子程序。     
//****************************************************************************   
void Read_Temp (void)   
  {   
    
    unsigned char I,J,DATA,CRC;   
    unsigned char ROM[9];   
    unsigned char *PA;   
    Rst_DS18B20();          //温度传感器复位   
    if ((TEMP_NUMBER > 0) && (FLAG && FLAG_TEMP_RET))   
      {                //温度传感器数量>0并且复位正常   
        Write_BUS_Byte (0xcc);      //写"跳过"命令   
        Write_BUS_Byte (0x44);      //写"读温度"命令   
        DATA = 0;   
        I = 0XFF;   
        while ((DATA != 0XFF) && (I>0))   
          {                    //循环等待温度转换结束   
            DATA = Read_BUS_Byte();   
            I--;   
          }   
        for (I=0; I<TEMP_NUMBER; I++)   
          {   
            PA = ROM;   
            Rst_DS18B20();   
            Write_BUS_Byte (0x55);   //写"匹配温度传感器"命令   
            for (J=0; J<8; J++)      //写温度传感器地址   
              {   
                Write_BUS_Byte (ID[I][J]);   
              }   
            Write_BUS_Byte (0xbe);  //写"读存储器"命令   
            for (J=0; J<9; J++)   
              {   
                ROM[J] = Read_BUS_Byte();   
              }   
            CRC = CRC_Verify(PA,8);   
            if (CRC == ROM[8])   
              {   
                PA =(unsigned char*)&TEMP[I];   
                *PA = ROM[0];   
                *(PA+1) = ROM[1];    
              }   
          }     //I循环结束   
      }   
  }   
   
//****************************************************************************   
//模块名:Temp   
//描述:  温度子程序。      
//****************************************************************************   
void Temp (void)   
  {   
    Rst_DS18B20 ();   
    Search_ROM ();   
    Read_Temp();   
    _NOP();   
  }   
//****************************************************************************   
//模块名:Delay     
//描述:  延时子程序。    
//****************************************************************************   
void Delay(unsigned int x)   
{   
    while(x !=0)x--;   
}  
       本程序是以MSP430F149单片机的DS18B20C语言程序,DS18B20的DQ脚连接MSP430单片机的P6.4,把读取到温度值,存放在float类型数组fT[]里面,如果你需要移值此文件显示在液晶或其它显示设备上,只要调用 fT[]数组即可。