DS2433应用笔记

作者: 孟德思维 | 来源:发表于2018-01-24 16:14 被阅读14次

    最近调试 ds2433 芯片,由于第一次接触1-wire总线,遇到了许多问题,但相关 ds2433中文资料 并不多,故作笔记总结,方便你我他。

    调试环境:keil5

    硬件环境:stm32F103C8T6 + ds2433

    引脚分配:

                    stm32<--->ds2433
    
                      PB11<--->data
    
                      GND<--->GND
    

    DS2433主要特性

    4096位(512字节)EEPROM。

    唯一的64位注册号。

    1-wire总线通信。

    先看主函数:

    程序结构比较简单,初始化各个模块后,写入一组随机数值到ds2433,再从ds2433中读出全部数据。当串口接收到任意字符后,通过串口将读取到的数据发送到上位机串口助手上。

    int main(void)
    {
      delay_init(); //延时函数初始化
      NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置中断优先级
      uart_init(115200); //串口初始化为 115200
       while(DS2433_Init()) { read_2433(RomCode); }
       for( i=0;i<512;i++) pagedata[i] =rand()%256;
       write_test(pagedata,Oid);//将pagedata写入ds2433.
       read_2433(RomCode);//读取注册码
       for( i=0;i<512;i++) read_test[i] = 0x00;//将读缓存数据初始化0x00
       read_2433_alldata(read_test); //可以读取512个完整数据
       read_2433(RomCode);
       while(1)
       {
        uart_recv(buf,len);
        if(len!=0)
          uart_send(read_test,512);
      }
    }
    

    ds2433初始化

    //初始化DS2433的IO口 DQ 同时检测DS的存在
    //返回1:不存在
    //返回0:存在   
    u8 DS2433_Init(void)
    {
      GPIO_InitTypeDef  GPIO_InitStructure;
      RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); //使能PORTB口时钟
      GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11; //PORTB.15 推挽输出
      GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;  
      GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
      GPIO_Init(GPIOB, &GPIO_InitStructure);
      GPIO_SetBits(GPIOB,GPIO_Pin_11);    //输出1
      DS2433_Rst();//复位
      return DS2433_Check();
    }
    

    ds2433复位

    //复位DS2433
    void DS2433_Rst(void)  
    {               
        DS2433_IO_OUT(); //SET PG11 OUTPUT
        DS2433_DQ_OUT=0; //拉低DQ
        delay_us(750);    //拉低750us
        DS2433_DQ_OUT=1; //DQ=1
        delay_us(15);    //15US
    }
    

    等待ds2433响应

    //等待DS2433的回应
    //返回1:未检测到DS2433的存在
    //返回0:存在
    u8 DS2433_Check(void)  
    { 
      u8 retry=0;
      DS2433_IO_IN(); //SET PG11 INPUT
      while (DS2433_DQ_IN&&retry<200)
      {
      retry++;
      delay_us(1);
      };
      if(retry>=200)return 1;
      else retry=0;
      while (!DS2433_DQ_IN&&retry<240)
      {
        retry++;
        delay_us(1);
      };
      if(retry>=240)return 1;    
      return 0;
    }
    

    ds2433复位及在线监测

    int OWTouchReset(void)
    { 
        int result;
        DS2433_Rst();//复位
        result=DS2433_Check();
        return result;
    }
    

    1-wire写1byte数据

    // Write 1-Wire data byte
    void OWWriteByte(int data)
    {
      int loop;
      // Loop to write each bit in the byte, LS-bit first
      for (loop = 0; loop < 8; loop++)
      {
        OWWriteBit(data & 0x01);
        // shift the data byte for the next bit
        data >>= 1;
      }
    }
    

    1-wire总线写1比特数据

    // Send a 1-Wire write bit. Provide 10us recovery time.
    //
    void OWWriteBit(int bit)
    {
      DS2433_IO_OUT(); //SET PG11 OUTPUT
      if (bit)
      {
        // Write '1' bit
        GPIO_ResetBits(GPIOB,GPIO_Pin_11);// Drives DQ low
        delay_us(6);
        GPIO_SetBits(GPIOB, GPIO_Pin_11);// Releases the bus
        delay_us(60); // Complete the time slot and 10us recovery
      }
      else
      {
        // Write '0' bit
        GPIO_ResetBits(GPIOB,GPIO_Pin_11);// Drives DQ low
        delay_us(60);
        GPIO_SetBits(GPIOB, GPIO_Pin_11);// Releases the bus
        delay_us(10);
      }
    }
    

    1-wire读取一字节数据

    // Read 1-Wire data byte and return it
    //
    int OWReadByte(void)
    {
      int loop, result=0;
      for (loop = 0; loop < 8; loop++)
      {
        // shift the result to get it ready for the next bit
        result >>= 1;
        // if result is one, then set MS bit
        if (OWReadBit())
          result |= 0x80;
      }
      return result;
    }
    

    1-wire读取1比特数据

    // Read a bit from the 1-Wire bus and return it. Provide 10us recovery time.
    //
    int OWReadBit(void)
    {
      int result;
      DS2433_IO_OUT(); //SET PG11 OUTPUT
      GPIO_ResetBits(GPIOB,GPIO_Pin_11);// Drives DQ low
      delay_us(6);
      GPIO_SetBits(GPIOB, GPIO_Pin_11);// Releases the bus
      delay_us(9);
      DS2433_IO_IN(); //SET PG11 INPUT
      result = GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_11)& 0x01;// Sample the bit value from the slave
      delay_us(55); // Complete the time slot and 10us recovery
      return result;
    }
    

    读取ds2433中全部数据

    void read_2433_alldata(u8 *page_data) //所有存储空间512字节全部读出
    {
      u16 page=0;
      u8 i,j;
      for(page=0;page<64;page++)
      {
      // select the device
      if (OWTouchReset()) // Reset the 1-Wire bus
      {
        return ; // Return if no devices found
      }
      OWWriteByte(0xCC); // Send Skip ROM command to select single device
      OWWriteByte(0xf0); // Read Authentication command
      OWWriteByte(((page << 3)) & 0xFF); //TA1地址低8位,左移位数与每次读取长度相关
     OWWriteByte(page>>5); // TA2 地址高八位
      for (i = 0; i < 8; i++)  //每起始地址,连续读8字节
        page_data[page*8+i] = OWReadByte();
      if (OWTouchReset()) // Reset the 1-Wire bus
      {
        return ; // Return if no devices found
      }
     }
    

    向ds2433中写入512字节数据

    void write_test(unsigned char *page_data,u8 *Oid)
    {
      int i,page,j;
      unsigned char TA1,TA2,E_S;
      for(j=0;j<64;j++)
      {
        if(OWTouchReset()) // Reset the 1-Wire bus
        {
          return ; // Return if no devices found
        }
        OWWriteByte(0xCC); // Send Skip ROM command to select single device
        OWWriteByte(0x0F); // Read Authentication command
        OWWriteByte((j<<3)&0xFF);   //TA1
        OWWriteByte((j>>5)&0xFF);   //TA2
        for (i = 0; i < 8; i++)
        {
          OWWriteByte(page_data[j*8+i]);
        }
        // select the device
        if (OWTouchReset()) // Reset the 1-Wire bus
        {
          return; // Return if no devices found
        }
        OWWriteByte(0xCC); // Send Skip ROM command to select single device
        OWWriteByte(0xAA);
        TA1 = OWReadByte();
        TA2 = OWReadByte();
        E_S = OWReadByte();
        delay_us(10);
        for(i=0;i<8;i++)
        {
          Oid[i]=OWReadByte();
        }
        // select the device
        if (OWTouchReset()) // Reset the 1-Wire bus
        {
          return; // Return if no devices found
        }
        OWWriteByte(0xCC); // Send Skip ROM command to select single device
        OWWriteByte(0x55); // Read Authentication command
        OWWriteByte(TA1 & 0xFF );
        OWWriteByte(TA2); // TA2
        OWWriteByte(E_S);
        delay_us(5000);
        // select the device
        if (OWTouchReset()) // Reset the 1-Wire bus
        {
          return; // Return if no devices found
        }
      }
    }
    

    读DS2433注册码

    //read 2433 product code
    u8 read_2433(u8 *RomCode)
    {
      int i;
      // select the device
      if (OWTouchReset()) // Reset the 1-Wire bus
        return 0; // Return if no devices found
      OWWriteByte(0x33); // Send Read ROM command to select single device
      // read the page data
      delay_us(60);
      for (i = 0; i < 8; i++)
        RomCode[i] = OWReadByte();
      if ( dscrcCheck(RomCode,8) )
      {
        return 0;
      }
      else
      {
        return 1;
      }
    }
    

    CRC检查

    ///CRC check
    u8 dscrcCheck(u8* p,u8 len)
    {
      uint8_t bit0,cbit,i,j,byte,temp;
      temp=0;
      for(j=0;j<len;j++)
      {
        byte=p[j];
        for(i=0;i<8;i++)
        {
          cbit = temp & 0x01;
          bit0 = byte & 0x01;
          temp=temp>>1;
          if( (cbit^bit0) ) temp^=0x8c;
          byte>>=1;
        }
      }
      return temp;
    }
    

    以上即是ds2433的驱动的核心源码,主要依据数据手册相关时序与指令完成。

    需要注意的小问题是,手册中关于ds2433的存储地址存在笔误,末page页面地址应为0x01FE-0x01FF,而文档中为0x1FE0-0x01FF。

    在调试成功后发现其实很简单,但在调试时遇到许多坑,但主要集中在对文档的不够熟悉,特别是地址和偏移量的换算。使用随机变量读写ds2433,便于检查写入与读出的数据是否一致,据此判断读取函数是否出现了问题。

    详细使用可根据以上驱动函数灵活组合,实现具体应用。

    相关文章

      网友评论

        本文标题:DS2433应用笔记

        本文链接:https://www.haomeiwen.com/subject/jwpuaxtx.html