单片机学习程序员

DS2433应用笔记

2018-01-24  本文已影响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,便于检查写入与读出的数据是否一致,据此判断读取函数是否出现了问题。

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

上一篇下一篇

猜你喜欢

热点阅读