再学通信协议---(One-Wire协议,以读取DS18B20数据为例)
即单线总线,又叫单总线。是由Dallas Semiconductor(现属于Maxim Integrated)开发的数据通信协议。2、它因仅需一根数据线(加上一条地线)即可实现数据通信而得名。3、它是一种半双工的通信机制,意味着数据可以在两个方向上传输,但在同一时间内只能进行单向传输。4、所有数据都在一条线上传输,因此单总线协议对时序要求非常严格以确保数据的完整性。5、One-Wire协议虽然在硬
目录
二、电源模式--One-Wire设备可以工作在两种电源模式下

One-Wire介绍与认识
一、单线通信
1、One-Wire,即单线总线,又叫单总线。是由Dallas Semiconductor(现属于Maxim Integrated)开发的数据通信协议。
2、它因仅需一根数据线(加上一条地线)即可实现数据通信而得名。
3、它是一种半双工的通信机制,意味着数据可以在两个方向上传输,但在同一时间内只能进行单向传输。
4、所有数据都在一条线上传输,因此单总线协议对时序要求非常严格以确保数据的完整性。
5、One-Wire协议虽然在硬件上较为简单,但在软件实现上可能较为复杂,需要精确控制数据线的时序。尽管如此,它仍然是一种非常经济且有效的通信解决方案,尤其适用于需要大量连接点的应用场景。
二、电源模式--One-Wire设备可以工作在两种电源模式下
该协议使用一根数据线同时传输数据和电源。设备通过电线上的数据脉冲获取电源,称为“寄生电源”(parasitic power),或者直接使用专门的电源线供电。
寄生电源模式(Parasitic Power):设备从数据线上获取能量,适用于能量需求较低的应用。
工作在寄生电源下的典型接法

外部供电模式(Normal Power):设备通过外部电源供电,适用于需要更多能量的应用。
外部供电下的典型接法

三、唯一的设备地址
1、每个One-Wire设备都拥有一个唯一的64位地址(通常称为ROM代码),包括一个8位的家族码、48位的序列号和一个8位的CRC校验码。
2、该地址在设备制造时烧录进去,并且是不可更改的。因此通信总线上的每个设备都可以被唯一标识。
3、这种特性允许多个设备共享同一条总线,主机可以通过地址识别并与单个从设备通信。
4、One-Wire协议采用主从结构,主机控制总线的通信流程。从设备只有在被主机选择之后才会响应数据请求。
四、通信速度
One-Wire协议采用主从结构,主机控制总线的通信流程。从设备只有在被主机选择之后才会响应数据请求。
One-Wire通信支持两种速度模式:
1. 标准模式:数据传输速率为15.3 kbps。
2.加速模式:数据传输速率为125 kbps,但并非所有设备都支持加速模式。
One-Wire通信的工作原理
一、初始化(Reset)
主机通过拉低数据线产生一个复位脉冲,然后释放总线,等待从机的应答脉冲。
从机在检测到复位脉冲后,会在一定时间后拉低数据线产生应答脉冲,表示它在线。

二、设备寻址--ROM操作指令
1、在检测到应答脉冲后,主机可以发出ROM(寻址)命令,主设备通过ROM读取操作读取每个设备的64位唯一地址,然后可以对特定设备发出命令,这些命令与从机设备的唯一ROM代码相关,允许主机指定操作某个从机设备。
2、忽略ROM指令(CCh):这条指令允许总线控制器不用提供64 位ROM 编码就使用功能指令。在单点总线情况下使用该命令,器件无需发回64 位ROM 编码,从而节省了时间。如果总线上有不止一只从机,若发出忽略ROM指令,由于多只从机同时传送信号,总线上就会发生数据冲突。
2、在发出ROM命令后,主机可以发出功能命令,例如读取或写入数据,启动温度转换等。
三、信号时序与数据读写
One-Wire协议比较简单,通常直接在硬件层次进行通信。主设备通过控制总线电压变化来进行数据读写,并通过时间间隔来确定数据的值。
1、单总线信号类型:复位脉冲、存在脉冲、写0、写1、读0、读1。
2、定义了严格的信号时序,包括复位脉冲、写0和写1的时隙,以及读时隙。这些时隙定义了数据的采样和传输时间。
3、 通过总线的拉低或释放来表示二进制的0和1,并通过特定的时序判断数据位。
4、写操作:主设备通过控制总线的高低电平以及时隙来写入数据,低电平表示“0”,高电平表示“1”。

5、读操作:主设备将总线拉低后释放,从设备根据要传送的数据位是否为1决定是否拉低总线。
详细时序图如下
读取DS18B20数据






DS18B20驱动代码
//DS18B20驱动代码
//IO方向设置
#define DS18B20_IO_IN() {GPIOA->CRH&=0XFFFF0FFF;GPIOA->CRH|=8<<12;}
#define DS18B20_IO_OUT() {GPIOA->CRH&=0XFFFF0FFF;GPIOA->CRH|=3<<12;}
//IO操作函数
#define DS18B20_DQ_OUT PAout(11) //数据端口 PA11
#define DS18B20_DQ_IN PAin(11) //数据端口 PA11
//复位DS18B20
void DS18B20_Rst(void)
{
DS18B20_IO_OUT(); //SET PA11 OUTPUT
DS18B20_DQ_OUT=0; //拉低DQ
delay_us(750); //拉低750us
DS18B20_DQ_OUT=1; //DQ=1
delay_us(15); //15US
}
//等待DS18B20的回应
//返回1:未检测到DS18B20的存在
//返回0:存在
u8 DS18B20_Check(void)
{
u8 retry=0;
DS18B20_IO_IN(); //SET PA11 INPUT
while (DS18B20_DQ_IN&&retry<200)
{
retry++;
delay_us(1);
};
if(retry>=200)return 1;
else retry=0;
while (!DS18B20_DQ_IN&&retry<240)
{
retry++;
delay_us(1);
};
if(retry>=240)return 1;
return 0;
}
//从DS18B20读取一个位
//返回值:1/0
u8 DS18B20_Read_Bit(void)
{
u8 data;
DS18B20_IO_OUT(); //SET PA11 OUTPUT
DS18B20_DQ_OUT=0;
delay_us(2);
DS18B20_DQ_OUT=1;
DS18B20_IO_IN(); //SET PA11 INPUT
delay_us(12);
if(DS18B20_DQ_IN)data=1;
else data=0;
delay_us(50);
return data;
}
//从DS18B20读取一个字节
//返回值:读到的数据
u8 DS18B20_Read_Byte(void)
{
u8 i,j,dat;
dat=0;
for (i=1;i<=8;i++)
{
j=DS18B20_Read_Bit();
dat=(j<<7)|(dat>>1);
}
return dat;
}
//写一个字节到DS18B20
//dat:要写入的字节
void DS18B20_Write_Byte(u8 dat)
{
u8 j;
u8 testb;
DS18B20_IO_OUT(); //SET PA11 OUTPUT;
for (j=1;j<=8;j++)
{
testb=dat&0x01;
dat=dat>>1;
if (testb)
{
DS18B20_DQ_OUT=0; // Write 1
delay_us(2);
DS18B20_DQ_OUT=1;
delay_us(60);
}
else
{
DS18B20_DQ_OUT=0; // Write 0
delay_us(60);
DS18B20_DQ_OUT=1;
delay_us(2);
}
}
}
//开始温度转换
void DS18B20_Start(void)
{
DS18B20_Rst();
DS18B20_Check();
DS18B20_Write_Byte(0xcc); // skip rom
DS18B20_Write_Byte(0x44); // convert
}
//初始化DS18B20的IO口 DQ 同时检测DS的存在
//返回1:不存在
//返回0:存在
u8 DS18B20_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //使能PORTA口时钟
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11; //PORTA.11 推挽输出
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_SetBits(GPIOA,GPIO_Pin_11); //输出1
DS18B20_Rst();
return DS18B20_Check();
}
//从ds18b20得到温度值
//精度:0.1C
//返回值:温度值 (-550~1250)
short DS18B20_Get_Temp(void)
{
u8 temp;
u8 TL,TH;
short tem;
DS18B20_Start (); // ds1820 start convert
DS18B20_Rst();
DS18B20_Check();
DS18B20_Write_Byte(0xcc); // skip rom
DS18B20_Write_Byte(0xbe); // convert
TL=DS18B20_Read_Byte(); // LSB
TH=DS18B20_Read_Byte(); // MSB
if(TH>7)
{
TH=~TH;
TL=~TL;
temp=0; //温度为负
}else temp=1; //温度为正
tem=TH; //获得高八位
tem<<=8;
tem+=TL; //获得底八位
tem=(float)tem*0.625; //转换
if(temp)return tem; //返回温度值
else return -tem;
}
读取DS18B20的数据
//读取DS18B20的数据
int main(void)
{
short temperature;
delay_init();
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
uart_init(115200); //串口初始化为 115200
while(DS18B20_Init()) //DS18B20初始化
{
delay_ms(200);
}
while(1)
{
temperature=DS18B20_Get_Temp();
printf("temperature=%d.%dC\r\n",temperature/10,temperature%10);
delay_ms(100);
}
}


DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。
更多推荐



所有评论(0)