IIC协议及其工程【FPGA】

2023-05-16

IIC协议及其工程【FPGA】

    • 一、IIC协议
      • 1、IIC简介
      • 2、IIC中相关的术语
        • 1、应答信号(ACK)
        • 2、无应答信号(NOACK)
        • 3、虚写
        • 3、IIC的时序
    • 二、EEPROM
      • 1、时钟频率
      • 2、起始位和停止位
      • 3、总线时序
      • 4、控制信号bit分配
      • 5、写操作
        • 1、字节写
        • 2、页写
      • 6、读操作
        • 1、随机读
        • 2、顺序读
    • 三、工程
      • 读写控制
      • IIC接口
      • 其它模块
    • 四、参考
    • 五、源码

一、IIC协议

1、IIC简介

同步半双工、飞利浦公司设计。

2、IIC中相关的术语

1、应答信号(ACK)

IIC总线上的所有数据都是以字节传输的,发送端每次发送一个字节,就必须在第9个脉冲周期释放SDA,等待接收端反馈一个应答信号。应答信号为低电平,称为有效应答位(ACK)。
通信双方的回应信号,在时钟高电平期间,数据引脚为低电平。

2、无应答信号(NOACK)

应答信号为高电平时,称为非应答位(NACK)。
通常用于主机发送给从机的信号,在时钟高电平期间,数据引脚为高电平。

3、虚写

使从机内的存储单元地址指针指向我们想要读取的存储单元地址处,首先发送了一次Dummy Write也就是虚写操作,只所以称为虚写,是因为我们并不是真的要写数据,而是通过这种虚写操作使地址指针指向虚写操作中字地址的位置,等从机应答后,就可以以当前地址读的方式读数据了

3、IIC的时序

sda在时钟低电平期间更新数据
在时钟高电平期间采集数据

二、EEPROM

1、时钟频率

支持最大400K的频率,跟芯片的供电电压相关,电压越大,支持的时钟频率也就越大

2、起始位和停止位

起始位分为高电平持续时间和低电平持续时间,两者的时间长度都为时钟周期的1/4。
在不同的工作电压下,需要维持的时间也是不同的。

停止位也是对应有不同的持续时间

3、总线时序

需要重点关注SDA引脚数据变化的位置,发生在时钟引脚SCL的低电平期间

4、控制信号bit分配

每个IIC设备的地址有一段地址是固定的,有一段是根据外围的引脚设置,最后一个bit(R/W)设置本次控制信号是读还是写,1表示读操作,0表示写操作。
发送控制字节的时候先发送地址的高位。
固定的地址信息“1010”,是IIC接口的EEPROM固定的地址头部信息。
摄像头的地址全都是固定的,没有引脚配置选项。

5、写操作

1、字节写

每次写入一个字节(8bit)的数据。
主机在数据信号发送完成之后,发送应答信号给从机,并且立即发送停止位信号。

2、页写

发送一次地址信息,一直传输数据存储数据,直到发送停止信号。

6、读操作

1、随机读

读取任意地址的数据,读取一次数据之后,主机发送无应答信号停止数据传输

2、顺序读

写入一个地址信号之后,连续获取该地址之后的数据,直到主机发送无应答信号(在随机读的基础上),从机才会停止发送数据。

三、工程

通过IIC协议完成对eeprom的读写

读写控制

`include "param.v"

module eeprom_rw #(parameter WR_LEN = 3,RD_LEN = 4)(
    input               clk     ,
    input               rst_n   ,
    
    input       [7:0]   din     ,
    input               din_vld ,
    input               rd_en   ,
    output      [7:0]   dout    ,//控制器输出数据
    output              dout_vld,
    input               busy    ,

    output              req     ,
    output      [3:0]   cmd     ,
    output      [7:0]   wr_data ,
    input       [7:0]   rd_data ,
    input               done     //传输完成标志
  
);


//状态机参数
    localparam      IDLE    = 6'b00_0001    ,
                    WR_REQ  = 6'b00_0010    ,//写传输 发送请求、命令、数据
                    WAIT_WR = 6'b00_0100    ,//等待一个字节传完
                    RD_REQ  = 6'b00_1000    ,//读传输 发送请求、命令、数据
                    WAIT_RD = 6'b01_0000    ,//等待一个自己传完
                    DONE    = 6'b10_0000    ;//一次读或写完成
//信号定义
    reg     [5:0]   state_c         ;
    reg     [5:0]   state_n         ;

    reg     [7:0]   cnt_byte        ;//数据传输 字节计数器
    wire            add_cnt_byte    ;
    wire            end_cnt_byte    ;

    reg             tx_req          ;//请求
    reg     [3:0]   tx_cmd          ;
    reg     [7:0]   tx_data         ;
    
    reg     [8:0]   wr_addr         ;//写eeprom地址
    reg     [8:0]   rd_addr         ;//读eeprom地址
    
    wire            wfifo_rd        ; 
    wire            wfifo_wr        ;
    wire            wfifo_empty     ;
    wire            wfifo_full      ;
    wire    [7:0]   wfifo_qout      ;
    wire    [5:0]   wfifo_usedw     ;
   
    wire            rfifo_rd        ;
    wire            rfifo_wr        ;
    wire            rfifo_empty     ;
    wire            rfifo_full      ;
    wire    [7:0]   rfifo_qout      ;
    wire    [5:0]   rfifo_usedw     ;

    reg             rd_flag         ;
    reg     [7:0]   user_data       ;
    reg             user_data_vld   ;

    wire            idle2wr_req     ; 
    wire            wr_req2wait_wr  ;
    wire            wait_wr2wr_req  ;
    wire            wait_wr2done    ;
    wire            idle2rd_req     ;
    wire            rd_req2wait_rd  ;
    wire            wait_rd2rd_req  ;
    wire            wait_rd2done    ;
    wire            done2idle       ;

//状态机设计
    always @(posedge clk or negedge rst_n) begin 
        if (rst_n==0) begin
            state_c <= IDLE ;
        end
        else begin
            state_c <= state_n;
       end
    end
    
    always @(*) begin 
        case(state_c)  
            IDLE :begin
                if(idle2wr_req)
                    state_n = WR_REQ ;
                else if(idle2rd_req)
                    state_n = RD_REQ ;
                else 
                    state_n = state_c ;
            end
            WR_REQ :begin
                if(wr_req2wait_wr)
                    state_n = WAIT_WR ;
                else 
                    state_n = state_c ;
            end
            WAIT_WR :begin
                if(wait_wr2wr_req)
                    state_n = WR_REQ ;
                else if(wait_wr2done)
                    state_n = DONE ;
                else 
                    state_n = state_c ;
            end
            RD_REQ :begin
                if(rd_req2wait_rd)
                    state_n = WAIT_RD ;
                else 
                    state_n = state_c ;
            end
            WAIT_RD :begin
                if(wait_rd2rd_req)
                    state_n = RD_REQ ;
                else if(wait_rd2done)
                    state_n = DONE ;
                else 
                    state_n = state_c ;
            end
            DONE :begin
                if(done2idle)
                    state_n = IDLE ;
                else 
                    state_n = state_c ;
            end
            default : state_n = IDLE ;
        endcase
    end
    
    assign idle2wr_req      = state_c==IDLE     && (wfifo_usedw > WR_LEN-2);
    assign wr_req2wait_wr   = state_c==WR_REQ   && (1'b1);
    assign wait_wr2wr_req   = state_c==WAIT_WR  && (done & cnt_byte < WR_LEN-1);
    assign wait_wr2done     = state_c==WAIT_WR  && (end_cnt_byte);
    assign idle2rd_req      = state_c==IDLE     && (rd_en);
    assign rd_req2wait_rd   = state_c==RD_REQ   && (1'b1);
    assign wait_rd2rd_req   = state_c==WAIT_RD  && (done & cnt_byte < RD_LEN-1);
    assign wait_rd2done     = state_c==WAIT_RD  && (end_cnt_byte);
    assign done2idle        = state_c==DONE     && (1'b1);
    
//cnt_byte  
    always @(posedge clk or negedge rst_n) begin 
        if (rst_n==0) begin
            cnt_byte <= 0; 
        end
        else if(add_cnt_byte) begin
            if(end_cnt_byte)
                cnt_byte <= 0; 
            else
                cnt_byte <= cnt_byte+1 ;
       end
    end
    assign add_cnt_byte = (state_c==WAIT_WR | state_c==WAIT_RD) & done;
    assign end_cnt_byte = add_cnt_byte  && cnt_byte == ((state_c==WAIT_WR)?
                                                        (WR_LEN-1):(RD_LEN-1));
//输出

    always  @(posedge clk or negedge rst_n)begin
        if(~rst_n)begin
            TX(1'b0,4'd0,8'd0);
        end
        else if(state_c==WR_REQ)begin
            case(cnt_byte)
                0           :TX(1'b1,{`CMD_START | `CMD_WRITE},{`I2C_ADR,wr_addr[8],`WR_BIT});//发起始位、写控制字
                1           :TX(1'b1,`CMD_WRITE,wr_addr[7:0]);   //发 写地址
                WR_LEN-1  :TX(1'b1,{`CMD_WRITE | `CMD_STOP},wfifo_qout);  //最后一个字节时 发数据、停止位
                default     :TX(1'b1,`CMD_WRITE,wfifo_qout);    //中间发数据(如果有)
            endcase 
        end
        else if(state_c==RD_REQ)begin
            case(cnt_byte)
                0           :TX(1'b1,{`CMD_START | `CMD_WRITE},{`I2C_ADR,rd_addr[8],`WR_BIT});//发起始位、写控制字
                1           :TX(1'b1,`CMD_WRITE,rd_addr[7:0]);   //发 读地址
                2           :TX(1'b1,{`CMD_START | `CMD_WRITE},{`I2C_ADR,rd_addr[8],`RD_BIT});//发起始位、读控制字
                RD_LEN-1    :TX(1'b1,{`CMD_READ | `CMD_STOP},0);  //最后一个字节时 读数据、发停止位
                default     :TX(1'b1,`CMD_READ,0);    //中间读数据(如果有)
            endcase 
        end
        else begin 
             TX(1'b0,tx_cmd,tx_data);
        end 
    end
//用task发送请求、命令、数据(地址+数据)
    task TX;   
        input                   req     ;
        input       [3:0]       command ;
        input       [7:0]       data    ;
        begin 
            tx_req  = req;
            tx_cmd  = command;
            tx_data = data;
        end 
    endtask 

//wr_addr   rd_addr
    always  @(posedge clk or negedge rst_n)begin
        if(~rst_n)begin
            wr_addr <= 0;
        end
        else if(wait_wr2done)begin
            wr_addr <= wr_addr + WR_LEN-2;
        end
    end
    
    always  @(posedge clk or negedge rst_n)begin
        if(~rst_n)begin
            rd_addr <= 0;
        end
        else if(wait_rd2done)begin
            rd_addr <= rd_addr + RD_LEN - 3;
        end
    end

//rd_flag
    always  @(posedge clk or negedge rst_n)begin
        if(~rst_n)begin
            rd_flag <= 1'b0;
        end
        else if(~rfifo_empty)begin
            rd_flag <= 1'b1;
        end
        else begin 
            rd_flag <= 1'b0;
        end 
    end

//user_data user_data_vld
    always  @(posedge clk or negedge rst_n)begin
        if(~rst_n)begin
            user_data <= 0;
            user_data_vld <= 0;
        end
        else begin
            user_data <= rfifo_qout;
            user_data_vld <= rfifo_rd;
        end
    end

  
//输出

    assign req     = tx_req ; 
    assign cmd     = tx_cmd ; 
    assign wr_data = tx_data; 

    assign dout    = user_data;//控制器输出数据
    assign dout_vld= user_data_vld;

//fifo例化

wrfifo	u_wrfifo (
	.aclr   (~rst_n     ),
	.clock  (clk        ),
	.data   (din        ),
	.rdreq  (wfifo_rd   ),
	.wrreq  (wfifo_wr   ),
	.empty  (wfifo_empty),
	.full   (wfifo_full ),
	.q      (wfifo_qout ),
	.usedw  (wfifo_usedw)
	);

    assign wfifo_rd = state_c==WAIT_WR && done && cnt_byte > 1;
    assign wfifo_wr = ~wfifo_full & din_vld;

rdfifo	u_rdfifo (
	.aclr   (~rst_n     ),
	.clock  (clk        ),
	.data   (rd_data    ),
	.rdreq  (rfifo_rd   ),
	.wrreq  (rfifo_wr   ),
	.empty  (rfifo_empty),
	.full   (rfifo_full ),
	.q      (rfifo_qout ),
	.usedw  (rfifo_usedw)
	);

    assign rfifo_wr = ~rfifo_full && state_c==WAIT_RD && cnt_byte > 2 && done;
    assign rfifo_rd = rd_flag && ~busy;
endmodule

IIC接口

`include "param.v"

module i2c_master(
    input               clk         ,
    input               rst_n       ,

    input               req         ,
    input       [3:0]   cmd         ,
    input       [7:0]   din         ,

    output      [7:0]   dout        ,
    output              done        ,

    output              i2c_scl     ,
    input               i2c_sda_i   ,
    output              i2c_sda_o   ,
    output              i2c_sda_oe     
    );

//状态机参数定义

    localparam  IDLE  = 7'b000_0001,
                START = 7'b000_0010,
                WRITE = 7'b000_0100,
                RACK  = 7'b000_1000,
                READ  = 7'b001_0000,
                SACK  = 7'b010_0000,
                STOP  = 7'b100_0000;

//信号定义

    reg     [6:0]       state_c     ;
    reg     [6:0]       state_n     ;

    reg     [8:0]       cnt_scl     ;//产生i2c时钟
    wire                add_cnt_scl ;
    wire                end_cnt_scl ;
    reg     [3:0]       cnt_bit     ;//传输数据 bit计数器
    wire                add_cnt_bit ;
    wire                end_cnt_bit ;
    reg     [3:0]       bit_num     ;
    
    reg                 scl         ;//输出寄存器
    reg                 sda_out     ;
    reg                 sda_out_en  ;

    reg     [7:0]       rx_data     ;
    reg                 rx_ack      ;
    reg     [3:0]       command     ;
    reg     [7:0]       tx_data     ;//发送数据

    wire                idle2start  ; 
    wire                idle2write  ; 
    wire                idle2read   ; 
    wire                start2write ; 
    wire                start2read  ; 
    wire                write2rack  ; 
    wire                read2sack   ; 
    wire                rack2stop   ; 
    wire                sack2stop   ; 
    wire                rack2idle   ; 
    wire                sack2idle   ; 
    wire                stop2idle   ; 


//状态机
    always @(posedge clk or negedge rst_n) begin 
        if (rst_n==0) begin
            state_c <= IDLE ;
        end
        else begin
            state_c <= state_n;
       end
    end
    
    always @(*) begin 
        case(state_c)  
            IDLE :begin
                if(idle2start)
                    state_n = START ;
                else if(idle2write)
                    state_n = WRITE ;
                else if(idle2read)
                    state_n = READ ;
                else 
                    state_n = state_c ;
            end
            START :begin
                if(start2write)
                    state_n = WRITE ;
                else if(start2read)
                    state_n = READ ;
                else 
                    state_n = state_c ;
            end
            WRITE :begin
                if(write2rack)
                    state_n = RACK ;
                else 
                    state_n = state_c ;
            end
            RACK :begin
                if(rack2stop)
                    state_n = STOP ;
                else if(rack2idle)
                    state_n = IDLE ;
                else 
                    state_n = state_c ;
            end
            READ :begin
                if(read2sack)
                    state_n = SACK ;
                else 
                    state_n = state_c ;
            end
            SACK :begin
                if(sack2stop)
                    state_n = STOP ;
                else if(sack2idle)
                    state_n = IDLE ;
                else 
                    state_n = state_c ;
            end
            STOP :begin
                if(stop2idle)
                    state_n = IDLE ;
                else 
                    state_n = state_c ;
            end
            default : state_n = IDLE ;
        endcase
    end
    
    assign idle2start  = state_c==IDLE  && (req && (cmd&`CMD_START));
    assign idle2write  = state_c==IDLE  && (req && (cmd&`CMD_WRITE));
    assign idle2read   = state_c==IDLE  && (req && (cmd&`CMD_READ ));
    assign start2write = state_c==START && (end_cnt_bit && (command&`CMD_WRITE));
    assign start2read  = state_c==START && (end_cnt_bit && (command&`CMD_READ ));
    assign write2rack  = state_c==WRITE && (end_cnt_bit);
    assign read2sack   = state_c==READ  && (end_cnt_bit);
    assign rack2stop   = state_c==RACK  && (end_cnt_bit && ((command&`CMD_STOP ) || rx_ack));
    assign sack2stop   = state_c==SACK  && (end_cnt_bit && (command&`CMD_STOP ));
    assign rack2idle   = state_c==RACK  && (end_cnt_bit && ((command&`CMD_STOP ) == 0));
    assign sack2idle   = state_c==SACK  && (end_cnt_bit && (command&`CMD_STOP ) == 0);
    assign stop2idle   = state_c==STOP  && (end_cnt_bit);
    
//计数器
    always @(posedge clk or negedge rst_n) begin 
        if (rst_n==0) begin
            cnt_scl <= 0; 
        end
        else if(add_cnt_scl) begin
            if(end_cnt_scl)
                cnt_scl <= 0; 
            else
                cnt_scl <= cnt_scl+1 ;
       end
    end
    assign add_cnt_scl = (state_c != IDLE);
    assign end_cnt_scl = add_cnt_scl && cnt_scl == (`SCL_PERIOD)-1 ;

    always @(posedge clk or negedge rst_n) begin 
        if (rst_n==0) begin
            cnt_bit <= 0; 
        end
        else if(add_cnt_bit) begin
            if(end_cnt_bit)
                cnt_bit <= 0; 
            else
                cnt_bit <= cnt_bit+1 ;
       end
    end
    assign add_cnt_bit = (end_cnt_scl);
    assign end_cnt_bit = add_cnt_bit  && cnt_bit == (bit_num)-1 ;

    always  @(*)begin
        if(state_c == WRITE | state_c == READ) begin
            bit_num = 8;
        end
        else begin 
            bit_num = 1;
        end 
    end
//command
    always  @(posedge clk or negedge rst_n)begin
        if(~rst_n)begin
            command <= 0;
        end
        else if(req)begin
            command <= cmd;
        end
    end

//tx_data
    always  @(posedge clk or negedge rst_n)begin
        if(~rst_n)begin
            tx_data <= 0;
        end
        else if(req)begin
            tx_data <= din;
        end
    end

//scl
    always  @(posedge clk or negedge rst_n)begin
        if(~rst_n)begin
            scl <= 1'b1;
        end
        else if(idle2start | idle2write | idle2read)begin//开始发送时,拉低
            scl <= 1'b0;
        end
        else if(add_cnt_scl && cnt_scl == `SCL_HALF-1)begin//半个周期时拉低
            scl <= 1'b1;
        end 
        else if(end_cnt_scl && ~stop2idle)begin //若继续发送下一bit则继续拉低,否则保持高
            scl <= 1'b0;
        end 
    end

//sda_out
    always  @(posedge clk or negedge rst_n)begin
        if(~rst_n)begin
            sda_out <= 1'b1;
        end
        else if(state_c == START)begin          //发起始位
            if(cnt_scl == `LOW_HLAF)begin       //时钟低电平时拉高sda总线
                sda_out <= 1'b1;
            end
            else if(cnt_scl == `HIGH_HALF)begin    //时钟高电平时拉低sda总线 
                sda_out <= 1'b0;                //保证从机能检测到起始位
            end 
        end 
        else if(state_c == WRITE && cnt_scl == `LOW_HLAF)begin  //scl低电平时发送数据   并串转换
            sda_out <= tx_data[7-cnt_bit];      
        end 
        else if(state_c == SACK && cnt_scl == `LOW_HLAF)begin  //发应答位
            sda_out <= (command&`CMD_STOP)?1'b1:1'b0;
        end 
        else if(state_c == STOP)begin //发停止位
            if(cnt_scl == `LOW_HLAF)begin       //时钟低电平时拉低sda总线
                sda_out <= 1'b0;
            end
            else if(cnt_scl == `HIGH_HALF)begin    //时钟高电平时拉高sda总线 
                sda_out <= 1'b1;                //保证从机能检测到停止位
            end 
        end 
    end

//sda_out_en  总线输出数据使能
    always  @(posedge clk or negedge rst_n)begin
        if(~rst_n)begin
            sda_out_en <= 1'b0;
        end
        else if(idle2start | idle2write | read2sack | rack2stop)begin
            sda_out_en <= 1'b1;
        end
        else if(idle2read | start2read | write2rack | stop2idle)begin 
            sda_out_en <= 1'b0;
        end 
    end

//rx_data       接收读入的数据
    always  @(posedge clk or negedge rst_n)begin
        if(~rst_n)begin
            rx_data <= 0;
        end
        else if(state_c == READ && cnt_scl == `HIGH_HALF)begin
            rx_data[7-cnt_bit] <= i2c_sda_i;    //串并转换
        end
    end

//rx_ack
    always  @(posedge clk or negedge rst_n)begin
        if(~rst_n)begin
            rx_ack <= 1'b1;
        end
        else if(state_c == RACK && cnt_scl == `HIGH_HALF)begin
            rx_ack <= i2c_sda_i;
        end
    end

//输出信号

    assign i2c_scl    = scl         ;
    assign i2c_sda_o  = sda_out     ;
    assign i2c_sda_oe = sda_out_en  ;
   
    assign dout = rx_data;
    assign done = rack2idle | sack2idle | stop2idle;

endmodule

其它模块

按键消抖
串口

四、参考

【FPGA】FPGA基于i2c的eeprom读写

五、源码

https://github.com/IvanXiang/FPGA_IIC_EEPROM

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

IIC协议及其工程【FPGA】 的相关文章

  • Ublox-M8N GPS接收机UBX协议解析

    Ublox M8N GPS接收机UBX协议解析 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61
  • Java清空List方法

    1 用list clear 方法清空list xff1b 用此方法 xff0c 其它引用该list的值也会变成空 2 用list 61 null来清空list 3 new ArrayList 来清空list
  • fastjson用java转json时间的格式化

    一 项目中需求遇到需要接收其他应用数据 xff0c 通过 64 RequestBody注解接收参数后 xff0c 到本地利用fastJson把json格式化 需要注意一下几点 xff1a 需要在调用JSON toJSONString 的时候
  • 工具类里面调用service接口或者mapper接口

    我们在开发中经常会遇到需要将一些频繁进行的操作抽取封装到工具类中 xff0c springboot不支持注入静态属性 所以在工具类中使用 64 Autowired或者其他注解自动注入会失败 xff0c 才用如下方法这可以避免注入失败 spa
  • windows下停止【kill】nginx命令

    杀死nginx taskkill fi 34 imagename eq nginx EXE 34 f taskkill f t im nginx exe stop bat taskkill f t im nginx exe pause
  • 基本类型对应的缓冲池

    基本类型对应的缓冲池如下 xff1a boolean values true and false all byte values short values between 128 and 127 int values between 128
  • 记录JVM中Eden区、Survivor from区和Survivor to区及Minor GC和Major GC的理解

    仅做学习笔记 JVM中Eden区 Survivor from区和Survivor to区 本文主要根据 深入理解JVM 中内存回收策略 xff0c 主要关注如下五个方面 xff1a 1 xff1a Eden区分配 2 xff1a 大对象直接
  • ubuntu下修改python默认版本的方法

    Ubuntu安装之后会面临多个python版本共存的问题 xff08 python2和python3 xff09 xff0c 但是有时候安装其他库的时候会安装在默认的python版本环境下 xff08 比如 xff0c 通常默认版本是pyt
  • C++:C语言实现HTTP的GET和POST请求

    https www cnblogs com diligenceday p 6255788 html
  • Linux C/C++ UDP Socket 网络通信

    Python微信订餐小程序课程视频 https edu csdn net course detail 36074 Python实战量化交易理财系统 https edu csdn net course detail 35475 昨晚 Vv 让
  • Xcode工程创建多个target

    Xcode工程创建多个target 小菜本人有时候会在一个Xcode工程中新建多个包含main函数的 m文件用于用于学习Objective C xff0c 于是要用到target这个东西 target对应于一个可运行文件和一些编译配置 点击
  • JLINK简介

    一 什么是JLINK JLINK是一个兼容JTAG的仿真器 xff0c 作用是烧入程序和Debug 二 JLINK是如何处理数据的 xff1f 1 PC端应用程序将数据以某种协议格式 xff0c 通过USB接口发送给J Link 2 J L
  • 蓝桥杯单片机-DS1302时钟模块

    一 简介 1 采用SPI三线接口通信 xff08 SCK SDA RST xff09 上升沿数据被写入DS1302 xff0c 下降沿被读出 二 应用 1 在ds1302 c文件中定义三个数组 unsigned char code READ
  • 蓝桥杯单片机-定时器

    一 简介 有三个寄存器与定时器相关 xff08 TMOD xff0c TCON xff0c 数值设置寄存器TH TL xff09 1 定时器工作方式设置寄存器TMOD GATE 门控制位 GATE 61 0时 定时器 计数器启动与停止仅受T
  • 蓝桥杯单片机-NE555模块

    一 简介 1 NE555在开发板中用于输出频率可变 xff0c 占空比不变的方波 2 NE555是纯硬件的设计 xff0c 通过电位器RB3可改变其信号输出频率 不需要编程实现其功能 考点 xff1a 使用定时器的计数模式测量NE555输出
  • C语言学习笔记(基于单片机)

    目录 一 关键字部分 static code const extern bit sbit sft struct xff08 结构体 xff09 1 结构体的初始化 2 结构体的赋值 3 应用 data idata pdata xdata 与
  • 蓝桥杯单片机-赛前总结

    目录 一 省赛中开发平台涉及的模块 xff1a 1 IIC驱动 2 DS1302驱动 3 onewire驱动 4 定时器读取NE555频率 二 一些功能性操作 1 外部中断 2 矩阵按键 3 PWM输出 4 毫秒延时函数 三 需要注意的一些
  • 相互依赖的so库,在编译时如何解耦

    有时候 xff0c 我们写的程序 xff0c 会涉及到相互引用的问题 比如frameworks av media libstagefright下的这个libstagefright xff0c 被frameworks av media lib
  • boost库学习总结

    第一次使用boost库是因为网络编程 xff0c 由于时间比较紧 xff0c 没有时间每个库都学 xff0c 所以前期想找个专门的boost库网络教程 xff08 以前自己就用过socket写过 xff0c 但是为了跨平台 xff0c 而且
  • C51单片机判断点亮的是奇数位还是偶数位

    学单片机的时候想到一个问题 xff1a 如何判断单片机点亮的LED灯是奇数位还是偶数位 xff1f 在网上搜了一圈没找到 xff0c 于是打算自己写一个 单片机型号 xff1a AT89C52 xff0c LED为低电平有效接法 xff0c

随机推荐

  • Linux学习笔记——如何在交叉编译时使用共享库

    0 前言 在较为复杂的项目中会利用到交叉编译得到的共享库 xff08 so文件 xff09 在这种情况下便会产生以下疑问 xff0c 例如 xff1a 1 交叉编译时的共享库是否需要放置于目标板中 xff0c 如果需要放置在哪个目录中 2
  • 实例变量(instance var)与属性(@property)的关系

    实例变量 instance var 与属性 64 property 的关系 Objective C 2 0之后 xff0c 声明一个 64 property name自动产生一个实例变量 xff0c 名为 name xff0c 因此省去实例
  • VS+CUDA+Matlab环境配置经验 (达到用matlab使用nvcc进行gpu并行加速)

    前前后后配了一个多星期的环境 xff0c 终于完成了 xff0c 梳理一下我的经验给大家分享也留作以后参考 一 版本兼容性问题 一开始安装的时候我并不懂 xff0c 没有什么顺序和版本的概念 xff0c 所以各种组件不能相互支持 首先明确
  • 华为无线WiFi配置802.1x认证

    一 拓扑 xff1a 二 简介 xff1a 本篇主要介绍华为交换机设备配合Windows server 2019配置的802 1x 43 NPS协同做的有线网络认证 xff08 可跟做 xff09 现有的华为6605无线AC配置 xff1a
  • 寝室一伙计

    我们寝室一伙计 xff0c 昨天晚上睡觉的时候 xff0c 说梦话 xff0c 笑 xff0c 磨牙 xff0c 还有吃奶 xff0c 等等等等 xff0c 我服了
  • Qt学习笔记(五)重定向

    实时获取程序中qt所输出的信息 xff0c 并显示到QTextBrowser上 1 在main文件中添加以下内容 xx为你的界面类名 xx clk 61 NULL void myMessageOutput QtMsgType type co
  • 串口通信中接收数据时延迟处理与缓存处理的解决方案(C#)

    利用串口进行通信 xff0c 当发送方 xff08 A xff09 将数据写入串口后 xff0c 通过无线或有线方式将数据传送给接收方 xff08 B xff09 xff0c B通过调用串口读方法comm read 参数 即可将数据读出 原
  • robomaster电控究极学习教程(以哨兵为例)------一、串口dma和遥控器

    robomaster电控究极学习教程 xff08 以哨兵为例 xff09 一 串口dma和遥控器 文章目录 robomaster电控究极学习教程 xff08 以哨兵为例 xff09 一 串口dma和遥控器 一 串口DMA的作用二 步骤1 c
  • 无人机架构

    无人机架构 基本设计需求 xff0c 如 xff1a xff08 1 xff09 慎思规划和反应式行为 xff1b xff08 2 xff09 容许不确定性 xff1b xff08 3 xff09 考虑危险 xff1b xff08 4 xf
  • 第八课 C++中的__LINE__宏

    在C 43 43 编程中 xff0c 我们有时候需要知道当前源代码的行号 xff0c 这时候就可以使用 LINE 宏 本文将介绍如何使用 LINE 宏 xff0c 以及它的使用示例 LINE 宏简介 LINE 是C 43 43 中的一个预定
  • 介绍@dynamic的用法

    介绍 64 dynamic的用法 Objective C 2 0提供了属性 64 property xff0c 可以让编译器自动生成setter和getter方法 如果不想编译器自作主张生成这些setter和getter方法 xff0c 则
  • OkHttpUtils的使用

    OkHttpUtils是一个非常好的网络协议框架 xff0c 它是在OkHttp的基础上进行了二次封装 要使用这个类首先下载jar包 xff0c 如下 xff1a http download csdn net download xxdw19
  • 十进制整数转为十六进制整数(C++实现)

    一 代码功能 xff1a 输入一个十进制整数 xff0c 将其转化为十六进制整数并输出 二 源码 include lt iostream gt include lt cstring gt include lt cmath gt using
  • 我的四轴专用PID参数整定方法及原理---超长文慎入(转)

    给四轴调了好久的PID xff0c 总算是调好了 xff0c 现分享PID参数整定的心得给大家 xff0c 还请大家喷的时候手下留情 首先说明一下 xff0c 这篇文章的主旨并不是直接教你怎么调 xff0c 而是告诉你这么调有什么道理 xf
  • 简单的TCP客户端发包工具

    一 TCP介绍 先放这里有时间在写 xff0c 最近在写DuiLib相关的使用内容 xff0c 这部分大家凑活着看 二 程序截图 下载链接 链接 xff1a https pan baidu com s 1MzNUzwd7WwBat6vNMc
  • C++常用头文件汇总

    之前说过的头文件这就来了 1 首先是本人最喜欢也是最最方便的万能头文件 xff0c 顾名思义 xff0c 不管是天上飘的还是地下埋的 xff0c 只要不是不对的头文件它都包含 xff0c 除了本篇第14个头文件 xff1a include
  • 基于I2C/SPI的温湿度采集与OLED显示

    基于I2C SPI的温湿度采集与OLED显示 一 AHT20温湿度采集1 I2C2 温湿度采集代码效果 二 OLED显示1 显示学号姓名2 诗句显示 三 总结四 参考 一 AHT20温湿度采集 1 I2C 解释什么是 软件I2C 和 硬件I
  • 游戏客户端编程

    游戏客户端编程 1 代码实现服务器连接发送按钮 2 显示消息3 发送信息4 播放背景音乐5 变换游戏背景图片6 参考 1 代码实现 服务器连接 span class token keyword private span span class
  • 卷积神经网络实现表情识别

    卷积神经网络实现表情识别 CNN人脸表情识别图片预处理原本效果处理后效果 图片数据集效果 CNN人脸识别创建模型归一化与数据增强创建网络 摄像头人脸识别图片识别 参考 CNN人脸表情识别 图片预处理 span class token key
  • IIC协议及其工程【FPGA】

    IIC协议及其工程 FPGA 一 IIC协议1 IIC简介2 IIC中相关的术语1 应答信号 xff08 ACK xff09 2 无应答信号 xff08 NOACK xff09 3 虚写3 IIC的时序 二 EEPROM1 时钟频率2 起始