STM32 单总线1-wire

概述

       1-wire总线是一个具有单总线主机和一个或者多个从机的系统,一般在任何情况下单总线设备(如18B20)都是从机设备,主机一般是一颗MCU。它采用单根信号线,既可传输时钟,又能传输数据,而且数据传输是双向的。

1、初始化(复位和应答)

       主机通过拉低单总线480 ~ 960 us产生复位脉冲,然后释放总线,进入接收模式。主机释放总线时,会产生低电平跳变为高电平的上升沿,单总线器件检测到上升沿之后,延时15 ~ 60 us,单总线器件拉低总线60 ~ 240 us来产生应答脉冲。主机接收到从机的应答脉冲说明单总线器件就绪,初始化过程完成。

                   

2、写信令(写0和写1)

       当数据线拉低后,在15 ~ 60 us的时间窗口内对数据线进行采样。如果数据线为低电平,就是写0,如果数据线为高电平,就是写1。主机要产生一个写1时间隙,就必须把数据线拉低,在写时间隙开始后的15 us内允许数据线拉高。主机要产生一个写0时间隙,就必须把数据线拉低并保持60 us。

                 

3、读信令(读0和读1)

读时序最少需要拉低总线1us,然后释放总线,从设备会在15-45us操作总线,主机进行采样读取数据。

                     

单总线代码示例(18B20):

扫描二维码关注公众号,回复: 3757155 查看本文章
bit Init_DS18B20(void)	
{    
  bit flag; //检测DS18B20是否存在的标志,flag=0,存在;flag=1,不存在
  DQ = 1; //先将数据线拉高
  for(time=0;time<2;time++); //略微延时约6微秒
  DQ = 0;           
  for(time=0;time<200;time++) ; //向DS18B20发出一持续480~960us的低电平复位脉冲
  DQ = 1; //释放数据线(将数据线拉高) 
  for(time=0;time<10;time++) ; //释放总线后需等待15~60us让DS18B20输出存在脉冲
  flag=DQ;  //让单片机检测是否输出了存在脉冲(DQ=0表示存在)    
  for(time=0;time<200;time++) ;  //延时足够长时间,等待存在脉冲输出完毕
  return (flag);    //返回检测成功标志
}
Void WriteOneChar(unsigned char dat)
{         
  unsigned char i=0;
  for (i=0; i<8; i++)
  {
	 DQ =1;  // 先将数据线拉高
	 _nop_();	 //等待一个机器周期	 
	 DQ=0;   //将数据线从高拉低时即启动写时序       
	 DQ=dat&0x01;  //与运算取出要写二进制数据,并将其送到数据线上等待DS18B20采样
	 for(time=0;time<10;time++);//DS18B20在拉低后的约15~45us期间从数据线上采样
         DQ=1;          //释放数据线		    
	 for(time=0;time<1;time++);//延时3us,两个写时序间至少需要1us的恢复期
	 dat>>=1;       //将dat中的各二进制位数据右移1位
  }
  for(time=0;time<4;time++); //稍作延时,给硬件一点反应时间,两个字节之间
}
unsigned char ReadOneChar(void)
{      
   unsigned char i=0;	
   unsigned char dat;  //储存读出的一个字节数据
   for (i=0;i<8;i++)
   {    
         DQ =1;       // 先将数据线拉高
	 _nop_();    //等待一个机器周期	 
	 DQ = 0;      //单片机从DS18B20读书据时,将数据线从高拉低即启动读时序
	 _nop_();     //等待一个机器周期		   
	 DQ = 1;      //将数据线"人为"拉高,为单片机检测DS18B20的输出电平作准备
	 for(time=0;time<2;time++) ;  //延时约6us,使主机在15us内采样
	 dat>>=1;
	 if(DQ==1)
            dat|=0x80;  //如果读到的数据是1,则将1存入dat
	 else
	    dat|=0x00;  //如果读到的数据是0,则将0存入dat 
	 for(time=0;time<8;time++);  //延时3us,两个读时序之间必须有大于1us的恢复期	
    }	                    
    return(dat);    //返回读出的十六进制数据
}

猜你喜欢

转载自blog.csdn.net/lly_3485390095/article/details/83410736