DS18B20 温度传感器 Verilog HDL 代码实现 - 初始化、ID 读取、温度转换、CRC 校验
以下是使用 Verilog HDL 语言实现 DS18B20 初始化工作、读取 48 位 ID 号、启动温度转换、读取温度转换结果以及 CRC 校验码计算的代码:
module ds18b20(
input clk,
input reset,
input [7:0] cmd,
output reg [47:0] id,
output reg [11:0] temp_data
);
// 状态定义
parameter RESET1 = 2'b00;
parameter CMD33 = 2'b01;
parameter GET_ID = 2'b10;
parameter RESET2 = 2'b11;
parameter CMDCC = 2'b00;
parameter CMD44 = 2'b01;
parameter RESET3 = 2'b10;
parameter CMDCC2 = 2'b11;
parameter GET_TEMP = 2'b00;
parameter DELAY = 2'b01;
parameter WRITE_BIT = 2'b10;
parameter READ_BIT = 2'b11;
// 内部信号定义
reg [7:0] data;
reg [7:0] crc;
reg [2:0] state;
reg [3:0] bit_count;
reg [47:0] shift_reg;
// 初始化
initial begin
state = RESET1;
bit_count = 0;
end
// 状态机逻辑
always @(posedge clk) begin
if (reset) begin
state <= RESET1;
bit_count <= 0;
shift_reg <= 48'b0;
id <= 48'b0;
temp_data <= 12'b0;
end else begin
case (state)
// 复位1,等待800μs
RESET1: begin
state <= CMD33;
#800;
end
// 发送0x33命令读取ID号
CMD33: begin
data <= 8'h33;
state <= WRITE_BIT;
end
// 读取ID号
GET_ID: begin
id <= shift_reg;
state <= RESET2;
end
// 复位2,等待800μs
RESET2: begin
state <= CMDCC;
#800;
end
// 发送忽略ROM命令
CMDCC: begin
data <= 8'hCC;
state <= WRITE_BIT;
end
// 发送0x44命令启动温度转换,等待900ms
CMD44: begin
data <= 8'h44;
state <= WRITE_BIT;
#900000;
end
// 复位3
RESET3: begin
state <= CMDCC2;
end
// 发送忽略ROM命令
CMDCC2: begin
data <= 8'hCC;
state <= WRITE_BIT;
end
// 读取温度转换结果
GET_TEMP: begin
temp_data <= shift_reg[11:0];
state <= DELAY;
end
// 等待800μs
DELAY: begin
state <= READ_BIT;
#800;
end
// 写入数据位
WRITE_BIT: begin
shift_reg[bit_count] <= data[0];
crc <= crc ^ shift_reg[bit_count];
data <= {1'b1, data[7:1]};
bit_count <= bit_count + 1;
if (bit_count == 47) begin
state <= GET_ID;
end else begin
state <= READ_BIT;
end
end
// 读取数据位并进行CRC校验计算
READ_BIT: begin
data <= {data[6:0], 1'b0};
shift_reg[bit_count] <= data[0];
crc <= crc ^ shift_reg[bit_count];
bit_count <= bit_count + 1;
if (bit_count == 47) begin
state <= GET_TEMP;
end else begin
state <= WRITE_BIT;
end
end
endcase
end
end
// CRC校验模块
always @(posedge clk) begin
if (reset) begin
crc <= 8'h0;
end else begin
case (state)
// 写入数据位时清空CRC校验码
WRITE_BIT: begin
crc <= 8'h0;
end
// 读取数据位时进行CRC校验计算
READ_BIT: begin
if (crc[7]) begin
crc <= (crc << 1) ^ 8'h18;
end else begin
crc <= crc << 1;
end
end
endcase
end
end
endmodule
状态说明:
- RESET1: 对 DS18B20 温度传感器进行第一次复位操作,并进入等待状态,等待 800μs 后自动进入下一个状态。
- CMD33: 向 DS18B20 温度传感器发出 0x33 的命令,用以读取 48 位 ID 值。
- GET_ID: 从 DS18B20 温度传感器中读取 48 位 ID 值。
- RESET2: 对 DS18B20 温度传感器进行第二次复位操作,并进入等待状态,等待 800μs 后,开始进入 CMDCC 状态。
- CMDCC: 向 DS18B20 温度传感器发出一个忽略 ROM 的命令,用来为进入下一个状态作准备。
- CMD44: 向 DS18B20 温度传感器发出一个启动温度转换的命令,然后自动进入等待状态,停留 900ms 后进入下一个状态。
- RESET3: 对 DS18B20 温度传感器进行第三次的复位操作。
- CMDCC2: 向 DS18B20 温度传感器发出一个忽略 ROM 的命令,此操作是为了进入下一个状态作准备。
- GET_TEMP: 从 DS18B20 温度传感器当中读取传输的温度测量数值。
- DELAY: 进入等待状态。
- WRITE_BIT: 向 DS18B20 温度传感器当中写入数据位的状态。
- READ_BIT: 从 DS18B20 温度传感器当中读取数据位的状态。在此状态当中每当完成读取 1 位数据的时候,都会同时完成对该数据位的 CRC 校验计算操作。
CRC 校验:
在所有数据都完成读取操作之后,还需要读取最后的 8 位 CRC 校验位。这 8 位校验位也是经过 CRC 校验计算得出的,如果在通信过程当中没有出现错误,则总的 CRC 校验结果应该是得出 0 的结果。这时便可以既将通信传输正确的数据保存到名为 id 和 temp_data 寄存器当中。
代码使用说明:
- clk:时钟信号输入
- reset:复位信号输入
- cmd:控制命令输入
- id:读取到的 48 位 ID 值输出
- temp_data:读取到的温度值输出
该代码可以作为参考,根据实际需求进行修改和扩展。
原文地址: https://www.cveoy.top/t/topic/nYr4 著作权归作者所有。请勿转载和采集!