zoukankan      html  css  js  c++  java
  • cyclone4驱动LM75A温湿度传感器学习

    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  
  • 相关阅读:
    数据库更改自增和主键
    修改MySQL的默认数据存储引擎
    tomcat密码的坑
    通过System.getProperties()获取系统参数
    Java语言开发的,直接解压即可使用软件
    一个javascript面试题
    为什么学习差
    IDEA设置
    java关键字
    IDEA快捷键
  • 原文地址:https://www.cnblogs.com/429512065qhq/p/8093270.html
Copyright © 2011-2022 走看看