FPGA - 单总线协议(one-wire)

news2024/7/6 19:49:55

1,简介

单总线(one-wire)是美国 DALLAS 公司推出的外围串行扩展总线技术,与 SPI、I2C 等串行数据通信方式不同,它采用单根信号线,既传输时钟又传输数据,而且数据传输是双向的。它具有节省 I/O口线资源、结构简单、成本低廉、便于总线扩展和维护等诸多优点。

单总线英文名 1-Wire,传输速率一般是 15.3Kbit/s,最大可达 142Kbit/s,通常采用 100Kbit/s 以下的速率传输数据。

2,硬件结构

单总线(one-wire)只有一根数据线,系统中的数据交换、控制都由这根线完成。设备(主机或从机)通过一个漏极开路或三态端口连至该数据线,以允许设备在不发送数据时能够释放总线,而让其它设备使用总线,其内部等效电路如图所示。

单总线通常要求外接一个约为4.7kΩ的上拉电阻,这样,当总线闲置时,其状态为高电平。主机和从机之间的通信可通过3个步骤完成,分别为初始化1-wire器件、识别1-wire器件和交换数据。由于它们是主从结构,只有主机呼叫从机时,从机才能应答,因此主机访问1-wire器件都必须严格遵循单总线命令序列,即初始化、ROM、命令功能命令。如果出现序列混乱,1-wire器件将不响应主机。

3,通信时序分析

由于DS18B20温度传感器在使用中与主机通讯是单总线(one-wire)通信,所以在这使用FPGA驱动DS18B20温度传感器测量温度来学习单总线(one-wire)。

3.1 FPGA 如何驱动 gxs18b20 并测量温度?

首先 FPGA 向温度传感器写入一些数据,数据按照一个字节一个字节发送,温度传感器接收到这些字节数据,会自动采集外界温度数据并保存在内部寄存器里面。然后 FPGA 向传感器写入读温 度数据指令,便可读取传感器里面的温度数据。

3.2 FPGA 与传感器通信过程

通过单总线访问 GX18B20 的执行序列如下:

        步骤 1:初始化。

        步骤 2:ROM 操作指令

        步骤 3:GX18B20 功能指令。

每一次 GX18B20 的操作都必须满足以上步骤,若是缺少步骤或是顺序混乱,器件将不会有返回值。

3.2.1 初始化

        通过单总线的所有执行操作都从一个初始化程序序列开始。初始化序列包含一个由总线控制器 发出的复位脉冲和其后由从机发出的存在脉冲。存在脉冲让总线控制器知道 Gx18B20 在总线上且 已经准备好操作。

        所有和 Gx18B20 间的通信都以初始化序列开始,初始化序列如图所示。一个复位脉冲跟着一个存在脉冲表明Gx18B20 已经准备好发送和接收数据。 在初始化序列期间,总线控制器拉低总线并保持 480us 以发出(TX)一个复位脉冲信号,然后释放总线,进入接收状态(RX)。当总线被释放后,5kΩ的上拉电阻将总线拉到高电平。当 GX18B20 检测到 IO 引脚上的上升沿后,等待 15-60us,然后发出一个由 60-240us 低电平信号构成的存在脉冲。

Bus master puling low : 主机拉低总线,主机向从机写 0

Gx18b20 pulling low : Gxs18b20 拉低总线,从机向主机发 0

Resistor pullup:从机的电阻上拉,期间从机可以接收主机写入的数据。

one_wire 端口是一个双向的端口,也即该端口可以发送数据,也可以接收数据。 主机有一个双向端口与从机连接,从机对应的端口的也是双向端口。 双向端口虽然可以发送和接收数据,但是发送数据时候,不能接收数据;也就是发送和接收数据必须分开进行。

各种手册里面经常出现“主机释放总线”,“从机释放总线”,这两个概念不是一个意思。同理“主机拉低总线”和“从机拉低总线”也不是一个意思。

主机释放总线:主机释放总线期间,主机可以接收来自从机的数据。注意, 如果主机要接收从机传来的数据。主机必须释放总线。

主机拉低总线:主机向从机写入逻辑 0

从机释放总线:从机释放总线、从机电阻上拉差不多是一个意思,代表着此时从机可以接收数据。

3.2.2 ROM 操作指令

在这里我们选择跳过ROM操作指令

SKIP ROM [CCh]

        这条命令允许总线控制器不用提供 64 位 ROM 编码就使用功能指令。例如,总线控制器可以先发出一条忽略 ROM 指令,然后发出温度转换指令[44h],从而完成温度转换操作。

3.2.3 GXS18B20 功能指令

GXS18B20 功能指令允许总线控制器读写 GX18B20 的寄存器,发起温度转换和识别电源模式。

下表是GXS18B20的功能指令表

其中我们只使用温度转换指令CONVERT T [44h]读取温度指令READ SCRATCHPAD [BEh]

CONVERT T [44h]

        这条命令时用于启动一次温度转换。温度转换指令被执行后,产生的温度转换结果数据以 2 个字节的形式被存储在温度寄存器中,而后 GX18B20 保持低功耗的等待状态。如果在寄生供电模 式下发出该指令,在温度转换期间(tCONV),必须在 10us(最多)内给单总线一个强上拉,见 GX18B20 供电节。如果 GX18B20 以外部电源供电,总线控制器在发出该命令后跟着发出读时序, GX18B20 如处于转换中,则总线返回 0,若温度转换完成,则返回 1。在寄生供电模式下,总线 被强上拉拉高前这样的通信方式不会被使用。

READ SCRATCHPAD [BEh]

        这条命令时主机读取寄存器命令。读取将从字节 0 的最低有效位开始,一直进行下去,直到 第 9 字节(字节 8,CRC)读完,如果不想读完所有字节,控制器可以在任何时候发出复位命令 来中止读取。

3.3 读写时序

读/写时序 GX18B20 的数据读写是通过时序处理来进行信息交换的,每个时序传输 1 位数据。

写时序

        GX18B20 有两种写时序:写 1 时序和写 0 时序。总线控制器通过写 1 时序来写逻辑 1;通过 写 0 时序来写逻辑 0。写时序必须最少持续 60us,包括两个写周期之间至少 1us 的恢复时间。当 总线控制器把数据线从逻辑高电平拉低到低电平的时候,写时序开始。 总线控制器要写产生一个写时序,必须把数据线拉到低电平然后释放,且需在 15us 内释放总 线。当总线被释放后,上拉电阻将总线拉高。总线控制器要生成写 0 时序,必须把数据线拉到低 电平且继续保持至少 60us。 总线控制器初始化写时序后,GX18B20 在一个 15us 到 60us 的窗口内对信号线进行采用。如果线上是高电平,就是写 1。反之,如果线上是低电平,就是写 0。

读时序

        总线控制器发起读时序时,GX18B20 仅被用来传输数据给控制器。因此,总线控制器在发出 读寄存器指令[BEh]或读电源模式指令[B4h]后必须立刻开始读时序,以便 GX18B20 提供请求的数 据。

         所有读时序必须最少 60us,包括两个读周期间至少 1us 的恢复时间。当总线控制把数据线从 高电平拉低到低电平时,读时序开始,数据线必须至少保持 1us,然后总线被释放。 在总线控制器发出读时序后,GX18B20 通过拉高或拉低总线上来传输 1 或 0。当传输 0 结束后, 总线将被释放,通过上拉电阻回到高电平空闲状态。从 GX18B20 输出的数据在读时序的下降沿出 现后 15us 内有效。因此,总线控制器在读时序开始 15us 内释放总线然后采样总线状态,以读取数据线的状态。

        图 1 标识 TINIT, TRC, 和 TSAMPLE 之和必须小于 15us。

        图 2 指出,系统时间可以通过以下方法达到最大:TINIT 和 TRC 保持时间尽可能短,并且把控制器采样时间放到 15us 周期的最后。

4,FPGA驱动gxs18b20

4.1 编写代码思路

1,根据FPGA 与温度传感器的通信过程分析:

   FPGA对传感器进行初始化操作;     ------> 分配一个字节时间 byte = 0
   向传感器写入  0xcc;                       ------> 分配一个字节时间 byte = 1
   向传感器写入  0x44;                       ------> 分配一个字节时间 byte = 2
   等待一段时间;                                 ------> 分配一个字节时间 byte = 3
   初始化操作;                                     ------> 分配一个字节时间 byte = 4
   向传感器写入  0xcc;                        ------> 分配一个字节时间 byte = 5
   向传感器写入  0xbe;                        ------> 分配一个字节时间 byte = 6
   读取传感器温度,读取两个字节;     ------> 分配两个字节时间 byte = 7/8

2,代码编写思路

,定义一个us的计数器,计数器计数时间为100us;
        cnt 100_000/20 = 5000 --> 0-4999 
        90us时就是计数到4499
        10us时就是计数到499

,定义一个位计数器bit_cnt 在cnt==4999时加1,在bit_cnt == 7 && cnt==4999时清0
,字节计数器 byte_cnt 在位计数器bit_cnt == 7 && cnt == 4999时加1,在bit_cnt == 7 && cnt == 4999 && byte==8时清0

,在如何设计连续写1或者写0

定义一个[7:0]wr_data ,其中 bit_cnt是从0计数到7 
wr_data在cnt计数到最大值时候,向右移位,通过判断wr_data[0]最低位,判断写0还是写1

4.2 代码编写

根据以上思路分析,编写代码如下:

`timescale 1ns / 1ps

module ds18b20_driver(
	input            clk       ,
	input            reset     ,
	input            dq        ,
 
	output reg       temp_sign ,
	output reg [7:0] temp_data
    );
	localparam CNT_MAX = 4999  ;
	localparam SKIP    = 8'hCC ;
	localparam CONVERT = 8'h44 ;
	localparam READ    = 8'hBE ;

	wire              dqout    ;
	reg               dqout_en ;

	reg [12:0]        cnt      ;
	reg [2 :0]        bit_cnt  ;
	reg [3 :0]        byte_cnt ;
	reg [7 :0]        wr_data  ;
	reg [16:0]        rd_data  ;
	reg               init_err ;


	//三态门
	assign dq = dqout_en == 1 ? dqout: 1'bz;
	assign dqout = 0;

	//计数器
	always @(posedge clk ) begin
		if (reset) begin
			cnt <= 0;
		end
		else if (cnt == CNT_MAX) begin
			cnt <= 0;		
		end
		else begin
			cnt <= cnt + 1;
		end
	end
	
	always @(posedge clk ) begin
		if (reset) begin
			bit_cnt <= 0;
		end
		else if (cnt == CNT_MAX && bit_cnt == 7) begin
			bit_cnt <= 0;		
		end
		else if (cnt == CNT_MAX)begin
			bit_cnt <= bit_cnt + 1;
		end
	end

	always @(posedge clk ) begin
		if (reset) begin
			byte_cnt <= 0;
		end
		else if (cnt == CNT_MAX && bit_cnt == 7 && byte_cnt == 8) begin
			byte_cnt <= 0;		
		end
		else if (cnt == CNT_MAX && bit_cnt == 7)begin
			byte_cnt <= byte_cnt + 1;
		end
	end

	

	always @(posedge clk ) begin
		if ((byte_cnt == 0 || byte_cnt == 4) && bit_cnt == 7 &&  cnt == CNT_MAX) begin
			wr_data <= SKIP;
		end
		else if(bit_cnt == 7 && byte_cnt == 1 && cnt == CNT_MAX) begin
			wr_data <= CONVERT;
		end
		else if(bit_cnt == 7 && byte_cnt == 5 && cnt == CNT_MAX) begin
			wr_data <= READ;
		end
		else if (cnt == CNT_MAX) begin
			wr_data <= wr_data >> 1;
		end
	end


	always @(posedge clk) begin
		if (reset) begin
			dqout_en <= 0;
		end
		else if(byte_cnt == 0 || byte_cnt == 4)begin //初始化
			dqout_en <= bit_cnt <= 4 ? 1'b1 : 1'b0;      	
		end 
		else if(byte_cnt == 3) //等待
			dqout_en <= 0; 
		else if (byte_cnt == 1 || byte_cnt == 2 || byte_cnt == 5 || byte_cnt == 6) 
            //向传感器写入字节
        begin                      
			dqout_en <= cnt == 0 ? 1'b1 : 
					(((cnt == 499 && wr_data[0]) || (cnt == 4599 && ~wr_data[0])) 
                    ? 1'b0 : dqout_en);
		end
		else if(byte_cnt == 7 || byte_cnt == 8)
			dqout_en  <= cnt <= 99 ? 1'b1 : 1'b0; //拉高2US 读取采样

	end 

	//主机采样
	always @(posedge clk ) begin 
		if(reset) begin
			rd_data <= 0;
		end else if((byte_cnt == 7 || byte_cnt == 8) && cnt == 649 ) //13us采样
		begin
			rd_data <= {dq,rd_data[15:1]};
		end
		else
			rd_data <= rd_data;
	end

	always @(posedge clk ) begin 
		if(byte_cnt == 8 && bit_cnt == 7 && cnt == 659 && ~rd_data[15]) begin
			temp_data <= rd_data[10:4];
			temp_sign <= rd_data[15]  ;
		end
		else if(byte_cnt == 8 && bit_cnt == 7 && cnt == 659 && rd_data[15]) begin
			temp_data <= ~rd_data[10:4] + 1 ;
			temp_sign <= rd_data[15]        ;
		end
	end	

	always @(posedge clk ) begin
		if((byte_cnt == 0 || byte_cnt == 4) && bit_cnt == 6 && cnt == CNT_MAX) //初始化采?
		begin
			if (dq == 0)
				init_err <= 0;
			else
				init_err <= 1;
		end 
	end


endmodule

在这里编写了一个顶层模块,其中定义了一个时钟管理单元 (PLL实现)来管理时钟和复位信号,

顶层模块如下:

`timescale 1ns / 1ps
module top(
	input	wire		clkin_50m,
	inout               dq 
    );

	wire reset;
	wire clk;
	wire       temp_sign;
	wire [7:0] temp_data;

	clock_and_reset clock_and_reset 
	(
		.clkin_50m (clkin_50m), 
		.clkout_50M(clk), 
		.reset     (reset)
	);

	ds18b20_driver ds18b20_driver
		(
			.clk       (clk),
			.reset     (reset),
			.dq        (dq),
			.temp_sign (temp_sign),
			.temp_data (temp_data)
		);

endmodule

 4.3 测试仿真

由于18b20温度传感器属于从机,所以仿真时较难,采用半仿真。我们定义一个仿真文件slave.v

其中让dq作为输出,使其输出0,然后将此模块例化到测试模块中

`timescale 1ns / 1ps
module slave(
	output dq
    );

	assign dq = 0;

endmodule

测试代码如下:

`timescale 1ns / 1ps


module tb_top();

	reg  clkin_50m ;
	wire dq        ;
	
    pullup(dq);  // pullup原语 模拟上拉电阻 可以让dq空闲状态处于高电平
    
	top top (
		.clkin_50m(clkin_50m), 
		.dq(dq)
		);

	slave slave (
		.dq(dq)
		);

	initial begin
		clkin_50m = 0;
		forever #(10) 
		clkin_50m = ~clkin_50m;
	end


endmodule

4.4 仿真波形

仿真波形如下

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1515046.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

idea Springboot 在线考试管理系统开发mysql数据库web结构java编程计算机网页

一、源码特点 springboot 在线考试管理系统是一套完善的完整信息系统&#xff0c;结合mvc框架和bootstrap完成本系统springboot spring mybatis &#xff0c;对理解JSP java编程开发语言有帮助系统采用springboot框架&#xff08;MVC模式开发&#xff09;&#xff0c;系统具有…

如何理解数据经济,数据要素,数据资源,数据资产入表、数据交易,数据经纪

引言 在数字经济时代&#xff0c;数据逐渐成为了新的财富。这不仅体现在企业层面&#xff0c;政府和个人也在积极地生成、收集和分析数据&#xff0c;以寻找商业价值和社会效益。数据财政模型的兴起&#xff0c;标志着从传统的以土地资源为核心的经济模型向以数据资产为核心的…

双链表(上)

1.结构 1.带头双向循环链表 注意&#xff1a;这里的“带头”跟前面我们说的“头节点”是两个概念&#xff0c;实际前面的在单链表阶段称呼不严 谨&#xff0c;但是为了同学们更好的理解就直接称为单链表的头节点。 带头链表里的头节点&#xff0c;实际为“哨兵位”&#xff0c…

【Web】浅聊XStream反序列化本源之恶意动态代理注入

目录 简介 原理 复现 具体分析之前 我们反序列化了个什么&#xff1f; XStream反序列化的朴素通识 具体分析 第一步&#xff1a;unmarshal解组 第二步&#xff1a;readClassType获取动态代理类的Class对象 第三步&#xff1a;调用convertAnother对动态代理类进行实例…

使用公式在Excel中指定列值的变化实现自动间隔着色(不是按照固定的行数)

如果你的文件很小&#xff0c;可以手工着色&#xff1b;但如果很大&#xff0c;就要借助公式来着色&#xff1b; 目的是什么&#xff0c;其中之一是&#xff1a;提升可读性。 一起往下看吧&#xff01;&#xff01; 如果你想要根据Excel某列中值的变化来间隔着色&#xff0c;…

LaTeX 目录标题取消(自定义)留白间距

默认的目录格式生成如下图&#xff0c;会发现“2 产品介绍”和“1.2 项目概述”中存在一段留白 通过在导言区定义以下代码即可自定义标题留白间距宽度 \usepackage[subfigure]{tocloft} \setlength{\cftbeforesecskip}{0.3em} 最终修改的效果如下

Games101笔记-变换

Scale Reflection Shear Rotate 没有额外提示默认绕原点旋转 线性变换 Transiation 不属于线性变换&#xff0c;仿射变换 齐次坐标 二维的点和向量增加一个维度 点加点等于两个点的中点 所有的仿射变换都可以写成齐次坐标的形式 在表示二维情况下的仿射变换时&#…

五.pandas常见操作

目录 五.pandas常见操作 1.pandas处理字符串 以上演示 1-大小写转换 2-去空格(两边) .str.strip() 3-切割 4-连接 .str.cat() 5-空格检测 .str.contains(" ") 6-替换 7-count()--返回元素出现次数 8-repeat() 2.查询操作 2.1 query(" ") 2.2…

mysql生成连续的日期

1.代码 例如&#xff1a;生成"2023-03-01"至"2023-03-10"之间的日期 WITH RECURSIVE date_range AS (SELECT "2023-03-01" AS date FROM dualUNION ALLSELECT DATE_ADD(date, INTERVAL 1 DAY) dateFROM date_rangeWHERE DATE_ADD(date, INTER…

【机器人控制 Robot Control】非线性控制(Non-linear Control)建模举例【新加坡南洋理工大学 NTU Singapore】

Non-linear Control Method Example: Non-linear Mechanical System Modelling of the System using Control Law Partitioning (Handwritten)

wordpress被恶意搜索攻击(网址/?s=****)解决方法。

源地址&#xff1a;https://www.ctvol.com/seoomethods/1413686.html 什么叫恶意搜索攻击&#xff1f; wordpress恶意搜索攻击并不是像病毒一样的攻击&#xff0c;而是一种seo分支黑帽手段&#xff0c;通过被攻击网站搜索功能中长尾关键词来实现攻击&#xff0c;通过网址不断…

数学问题难解?新研究提出MathScale方法,让AI更懂数学推理

引言&#xff1a;数学问题解决中的语言模型挑战 数学问题解决是一个复杂的认知过程&#xff0c;它要求参与者不仅要掌握数学知识&#xff0c;还要能够进行多步骤的逻辑推理。近年来&#xff0c;大语言模型&#xff08;LLMs&#xff09;在解决问题方面展现出了显著的能力&#…

环信ChatroomUIKit功能详解——超详细介绍

聊天室是当下泛娱乐社交应用中最经典的玩法&#xff0c;通过调用环信的 IM SDK 接口&#xff0c;可以快速创建聊天室。如果想根据自己业务需求对聊天室应用的 UI界面、弹幕消息、礼物打赏系统等进行自定义设计&#xff0c;最高效的方式则是使用环信的 ChatroomUIKit 。 文档地址…

2024年【安全生产监管人员】及安全生产监管人员模拟考试题库

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 2024年【安全生产监管人员】及安全生产监管人员模拟考试题库&#xff0c;包含安全生产监管人员答案和解析及安全生产监管人员模拟考试题库练习。安全生产模拟考试一点通结合国家安全生产监管人员考试最新大纲及安全生…

面试复盘记录(数据开发)

一、apple外包1.矩阵顺时针旋转遍历2.两表取差集 二、 一、apple外包 没问理论&#xff0c;就两个算法题。 1.矩阵顺时针旋转遍历 Given an m x n matrix, return all elements of the matrix in spiral order.Example 1:Input: matrix [[1,2,3],[4,5,6],[7,8,9]] Output: …

岩土工程渗流问题之有限单元法:理论、模块化编程实现、开源程序应用

有限单元法在岩土工程问题中应用非常广泛&#xff0c;很多商业软件如Plaxis/Abaqus/Comsol等都采用有限单元解法。尽管各类商业软件使用方便&#xff0c;但其使用对用户来说往往是一个“黑箱子”。相比而言&#xff0c;开源的有限元程序计算方法透明、计算过程可控&#xff0c;…

【NR 定位】3GPP NR Positioning 5G定位标准解读(八)- OTDOA定位

前言 3GPP NR Positioning 5G定位标准&#xff1a;3GPP TS 38.305 V18 3GPP 标准网址&#xff1a;Directory Listing /ftp/ 【NR 定位】3GPP NR Positioning 5G定位标准解读&#xff08;一&#xff09;-CSDN博客 【NR 定位】3GPP NR Positioning 5G定位标准解读&#xff08;…

redis在微服务领域的贡献,字节跳动只面试两轮

dubbo.registry.addressredis://127.0.0.1:6379 注册上来的数据是这样&#xff0c;类型是hash /dubbo/ s e r v i c e / {service}/ service/{category} 如 /dubbo/com.newboo.sample.api.DemoService/consumers /dubbo/com.newboo.sample.api.DemoService/providers has…

Apache Paimon系列之:主键表

Apache Paimon系列之&#xff1a;主键表 一、主键表1.Bucket2.LSM Trees3.Compaction 二、数据分布1.固定Bucket2.动态Bucket3.正常动态Bucket模式4.跨分区更新插入动态存储桶模式 三、Merge Engine1.Deduplicate2.部分更新3.序列组4.聚合部分更新5.聚合6.Retract7.First Row 四…

01-java入门了解--cmd命令、jdk、java的认识

cmd常用命令 java入门需要安装的环境 jdk。&#xff08;下载好jdk&#xff0c;并配置好环境&#xff09;idea。&#xff08;或者其他的编程工具&#xff09; jdk安装目录介绍 第一步&#xff1a;编写程序&#xff08;程序员写.java后缀的文件&#xff09; 第二步&#xff1a;…