cyclone4驱动LM75A温湿度传感器学习

news/2024/11/21 1:33:03/

1. LM75A第一次使用,I2C接口,8脚

2. 打开quartus工程,下面只要是看看代码结构,问题在于多个always语句,逻辑上不太好分清楚,主要看状态机

  1 module I2C_READ(
  2        clk,
  3 rst_n,
  4 scl,sda,data
  5               );
  6  
  7 input clk;//总线时钟 50MHz  
  8 input rst_n;//异步复位,低电平有效  
  9   
 10 output scl;//SCL 时钟  
 11 inout  sda;// SDA 数据总线  
 12 output [15:0] data;//温度数据  
 13   
 14 reg [15:0]data_r;//温度数据寄存器  
 15 reg scl;//SCL 总线寄存器  
 16 reg sda_r;//SDA 总线寄存器  
 17 reg sda_link;//SDA 总线数据方向标志  
 18 reg [7:0]scl_cnt;//SCL 时钟产生计数器  
 19 reg [2:0]cnt;//用来标记SCL时钟计数器  
 20 reg [25:0]timer_cnt;//定时器,每隔2s 读取一次温度数据  
 21 reg [3:0]data_cnt;//数据串并转换寄存器  
 22 reg [7:0]address_reg;//器件地址寄存器  
 23 reg [8:0]state;//状态寄存器  
 24 //  
 25 //进程1、2、3:产生SCL 总线时钟  
 26 always@(posedge clk or negedge rst_n)  
 27     begin  
 28         if(!rst_n)  
 29             scl_cnt <= 8'd0;  
 30         else if(scl_cnt == 8'd199)  
 31             scl_cnt <= 8'd0;  
 32         else  
 33             scl_cnt <= scl_cnt + 1'b1;  
 34     end  
 35 always@(posedge clk or negedge rst_n)  
 36     begin  
 37         if(!rst_n)  
 38             cnt <= 3'd5;  
 39         else   
 40             case(scl_cnt)  
 41                 8'd49: cnt <= 3'd1;//高电平中间  
 42                 8'd99: cnt <= 3'd2;//下降沿  
 43                 8'd149:cnt <= 3'd3;//低电平中间  
 44                 8'd199:cnt <= 3'd0;//上升沿  
 45                default: cnt <= 3'd5;  
 46             endcase  
 47     end  
 48 `define SCL_HIG (cnt == 3'd1)  
 49 `define SCL_NEG (cnt == 3'd2)  
 50 `define SCL_LOW (cnt == 3'd3)  
 51 `define SCL_POS (cnt == 3'd0)  
 52 always@(posedge clk or negedge rst_n)  
 53     begin  
 54         if(!rst_n)  
 55             scl <= 1'b0;  
 56         else if(`SCL_POS)  
 57             scl <= 1'b1;  
 58         else if(`SCL_NEG)  
 59             scl <= 1'b0;  
 60     end  
 61 //  
 62 //进程4:定时器,每隔1s 读取一次温度数据  
 63 always@(posedge clk or negedge rst_n)  
 64     begin  
 65         if(!rst_n)  
 66             timer_cnt <= 26'd0;  
 67         else if(timer_cnt == 26'd49999999)  
 68             timer_cnt <= 26'd0;  
 69         else   
 70             timer_cnt <= timer_cnt + 1'b1;  
 71     end  
 72 //  
 73 //状态机定义  
 74 parameter IDLE  = 9'b0_0000_0000,  
 75              START  = 9'b0_0000_0010,  
 76              ADDRESS    = 9'b0_0000_0100,  
 77              ACK1       = 9'b0_0000_1000,  
 78              READ1  = 9'b0_0001_0000,  
 79              ACK2       = 9'b0_0010_0000,  
 80              READ2  = 9'b0_0100_0000,  
 81              NACK       = 9'b0_1000_0000,  
 82              STOP       = 9'b1_0000_0000;  
 83 `define DEVICE_ADDRESS 8'b1001_0001//器件地址,读操作  
 84 //  
 85 //进程5:状态机描述  
 86 always@(posedge clk or negedge rst_n)  
 87     begin  
 88         if(!rst_n)  
 89             begin  
 90                 data_r  <= 16'd0;  
 91                 sda_r       <= 1'b1;  
 92                 sda_link    <= 1'b1;  
 93                 state       <= IDLE;  
 94                 address_reg <= 15'd0;  
 95                 data_cnt    <= 4'd0;  
 96             end  
 97         else   
 98             case(state)  
 99                 IDLE:  
100                     begin  
101                         sda_r   <= 1'b1;  
102                         sda_link <= 1'b1;  
103                         if(timer_cnt == 26'd49999999)  
104                             state <= START;  
105                         else  
106                             state <= IDLE;  
107                     end  
108                 START://产生起始信号  
109                     begin  
110                         if(`SCL_HIG)  
111                             begin  
112                                 sda_r       <= 1'b0;  
113                                 sda_link    <= 1'b1;  
114                                 address_reg <= `DEVICE_ADDRESS;  
115                                 state           <= ADDRESS;  
116                                 data_cnt        <= 4'd0;  
117                             end  
118                         else  
119                             state <= START;  
120                     end  
121                 ADDRESS://主机对器件进行寻址  
122                     begin  
123                         if(`SCL_LOW)  
124                             begin  
125                                 if(data_cnt == 4'd8)//寻址完成,SDA改变方向,器件准备输出应答讯号  
126                                     begin  
127                                         state   <= ACK1;  
128                                         data_cnt <=  4'd0;  
129                                         sda_r       <= 1'b1;  
130                                         sda_link    <= 1'b0;  
131                                     end  
132                                 else//寻址过程中,SDA对器件作为输入  
133                                     begin  
134                                         state   <= ADDRESS;  
135                                         data_cnt <= data_cnt + 1'b1;  
136                                         case(data_cnt)  
137                                             4'd0: sda_r <= address_reg[7];  
138                                             4'd0: sda_r <= address_reg[7];  
139                                             4'd1: sda_r <= address_reg[6];  
140                                             4'd2: sda_r <= address_reg[5];  
141                                             4'd3: sda_r <= address_reg[4];  
142                                             4'd4: sda_r <= address_reg[3];  
143                                             4'd5: sda_r <= address_reg[2];  
144                                             4'd6: sda_r <= address_reg[1];  
145                                             4'd7: sda_r <= address_reg[0];  
146                                             default: ;  
147                                         endcase  
148                                     end  
149                             end  
150                         else  
151                             state <= ADDRESS;  
152                     end  
153                 ACK1://器件输出应答信号  
154                     begin  
155                         if(!sda && (`SCL_HIG))  
156                             state <= READ1;  
157                         else if(`SCL_NEG)  
158                             state <= READ1;  
159                         else  
160                             state <= ACK1;  
161                     end  
162                 READ1://读器件数据,高字节  
163                     begin  
164                         if((`SCL_LOW) && (data_cnt == 4'd8))//读高字节数据完成,SDA改变方向,主机准备输出应答讯号  
165                             begin  
166                                 state   <= ACK2;  
167                                 data_cnt <= 4'd0;  
168                                 sda_r       <= 1'b1;  
169                                 sda_link    <= 1'b1;  
170                             end  
171                         else if(`SCL_HIG)//读数据过程中,器件作为输出,这里有疑问,不是应该的等SCL一个时钟吗?SCL_HIG
172                             begin  
173                                 data_cnt <= data_cnt + 1'b1;  
174                                 case(data_cnt)  
175                                     4'd0: data_r[15] <= sda;  
176                                     4'd1: data_r[14] <= sda;  
177                                     4'd2: data_r[13] <= sda;  
178                                     4'd3: data_r[12] <= sda;  
179                                     4'd4: data_r[11] <= sda;  
180                                     4'd5: data_r[10] <= sda;  
181                                     4'd6: data_r[9]  <= sda;  
182                                     4'd7: data_r[8]  <= sda;  
183                                     default: ;  
184                                 endcase  
185                             end  
186                         else  
187                             state <= READ1;  
188                     end  
189                 ACK2://主机输出应答讯号  
190                     begin     
191                         if(`SCL_LOW)  
192                             sda_r <= 1'b0;  
193                         else if(`SCL_NEG)  
194                             begin  
195                                 sda_r   <= 1'b1;  
196                                 sda_link    <= 1'b0;  
197                                 state       <= READ2;  
198                             end  
199                         else  
200                             state <= ACK2;  
201                     end  
202                 READ2://读低字节数据  
203                     begin  
204                         if((`SCL_LOW) && (data_cnt == 4'd8))  
205                             begin  
206                                 state   <= NACK;  
207                                 data_cnt <= 4'd0;  
208                                 sda_r       <= 1'b1;  
209                                 sda_link    <= 1'b1;  
210                             end  
211                         else if(`SCL_HIG)  
212                             begin  
213                                 data_cnt <= data_cnt + 1'b1;  
214                                 case(data_cnt)  
215                                     4'd0: data_r[7] <= sda;  
216                                     4'd1: data_r[6] <= sda;  
217                                     4'd2: data_r[5] <= sda;  
218                                     4'd3: data_r[4] <= sda;  
219                                     4'd4: data_r[3] <= sda;  
220                                     4'd5: data_r[2] <= sda;  
221                                     4'd6: data_r[1]  <= sda;  
222                                     4'd7: data_r[0]  <= sda;  
223                                     default: ;  
224                                 endcase  
225                             end  
226                         else  
227                             state <= READ2;  
228                     end  
229                 NACK://主机非应答  
230                     begin  
231                         if(`SCL_LOW)  
232                             begin  
233                                 state <= STOP;  
234                                 sda_r   <= 1'b0;  
235                             end  
236                         else  
237                             state <= NACK;  
238                     end  
239                 STOP:  
240                     begin  
241                         if(`SCL_HIG)  
242                             begin  
243                                 state <= IDLE;  
244                                 sda_r <= 1'b1;  
245                             end  
246                         else  
247                             state <= STOP;  
248                     end  
249                 default: state <= IDLE;  
250             endcase  
251     end  
252 assign sda   = sda_link ? sda_r: 1'bz;  
253 assign data  = data_r;  
254 endmodule

3. 这个代码需要好好研究下,有疑问的地方,data_cnt <= data_cnt + 1'b1;每次读一位的时候,SCL应该有一个时钟,按照这个时钟去读的,为啥代码使用data_cnt这个变量,感觉不对啊?这里不是很明白

 1  begin  
 2 134                                         state   <= ADDRESS;  
 3 135                                         data_cnt <= data_cnt + 1'b1;  
 4 136                                         case(data_cnt)  
 5 137                                             4'd0: sda_r <= address_reg[7];  
 6 138                                             4'd0: sda_r <= address_reg[7];  
 7 139                                             4'd1: sda_r <= address_reg[6];  
 8 140                                             4'd2: sda_r <= address_reg[5];  
 9 141                                             4'd3: sda_r <= address_reg[4];  
10 142                                             4'd4: sda_r <= address_reg[3];  
11 143                                             4'd5: sda_r <= address_reg[2];  
12 144                                             4'd6: sda_r <= address_reg[1];  
13 145                                             4'd7: sda_r <= address_reg[0];  
14 146                                             default: ;  
15 147                                         endcase  
16 148                                     end  

转载于:https://www.cnblogs.com/429512065qhq/p/8093270.html


http://www.ppmy.cn/news/650913.html

相关文章

应用PIC16F1938中IIC读取LM75A温度

一&#xff0e;概述 LM75A是一个高精度温度传感器&#xff0c;精度高达0.125℃&#xff0c;可以采集的温度范围是-55℃~125℃。PIC16F1938可以通过IIC通信方式对LM75A里面的温度寄存器直接读取&#xff0c;并可设置相关的配置寄存器。每个LM75A的地址信号前四位是一样的&#…

基于Stm32f103硬件iic驱动LM75A温度传感器

这是LM75A温度传感器的概述&#xff0c;本文主要介绍基于Stm32f103的硬件iic驱动LM75A温度传感器。 这是我所使用的硬件电路&#xff0c;很简单。 对于该传感器的使用&#xff0c;主要是读取温度值&#xff0c;查看数据手册我们知道需要利用iic通讯读取。 首先我们要知道什么是…

zigbee网关 cc2530裸机驱动温度传感器LM75A

LM75A&#xff0c;数字温度传感器&#xff0c;IIC接口&#xff0c;读取简单&#xff0c;只需要读取2个寄存机的值就可计算出来温度 手里里有个贴片的LM75A&#xff0c;在一块废弃的pcb板上利用0805电阻脚把lm75a的sda和scl脚焊好&#xff0c;其它的引脚用插针焊好 现在lm75a对外…

USB TO I2C(上海同旺电子)调试器调试LM75A--TI

所需设备&#xff1a; 1、USB TO I2C(上海同旺电子)&#xff1b; 2、LM75A 1℃精度、12位数字温度传感器 可以参考 “USB TO I2C(上海同旺电子)调试器调试ADT75” Pin to Pin 兼容 TI 的 LM75A 引脚如下&#xff1a; ADI 的 ADT75 引脚如下&#xff1a; USB TO I2C(上…

lm75b 读取温度 c语言,STC单片机读取LM75A温度的代码,以及ADC读取电压。给大家分享一下把...

#include"main.h" char xdata temp_[3]; // char xdata test[15]; bit temp_flag; void Delay_us(int i) //iic延时 {int j; for(j=0;j } void IIC_init(void) //iic初始化 {SCL = 1; Delay_us(5); SDA = 1; Delay_us(5); } void iic_start(void) …

stm32软件模拟i2c通讯读取lm75a温度

很久以前&#xff0c;写过基于51单片机的i2c通信&#xff0c;具体是读写EEPROM。但是当时没能好好总结&#xff0c;只是记录了些代码&#xff0c;现回头去来看&#xff0c;真是一件头疼的事情。 对于stm32&#xff0c;其硬件i2c有着一些bug&#xff0c;此外对于i2c这种通用的串…

基于Stm32f103利用模拟iic驱动LM75A温度传感器

这两天一直在搞模拟iic&#xff0c;模拟iic相较于硬件iic的优势在于更稳定&#xff0c;io口的选择更灵活。 这次编写模拟iic驱动程序还是有点坎坷&#xff0c;其中模拟iic的时序不是难点&#xff0c;直接说我遇到的问题1.io口模式的选择&#xff08;一开始我是使用固定的io口模…

LM75A移植

参考&#xff1a;基于FS_S5PC100的LM75温度传感器驱动程序添加与测试 LM75A是嵌入式中常用的温度传感器&#xff0c;常用来监测板上温度。 LM75A的接口是i2c接口&#xff0c;i2c的设备地址一般为48&#xff08;要根据原理图来定&#xff09;&#xff0c;温度采集范围是-55C-125…