I2C C 语言程序例子

/*研究I2C的兄弟们,想要C I2C的兄弟们!想学习24LC02 EEPROM的兄弟们!不要再累啦!我这里有一个我成功的程序,可以拿去做为你们的子程序,我相信我的写法,是比较容易理解和经典的,认可的朋友,请麻烦顶一下! */

/*******************************************************************
一、程序说明:
1, 24LC02器件地址是1010000R/W.
2, 数组写入24LC02采取页写方式.
3, 数组code从24LC02读出时采取自由读方式.
4, 采用4.00M晶体。
5,采用软件I2C。

二、硬件连接:
1, SDA------->23 pin.(当然你可以任意选择脚位)
2,  SCL------->18 Pin.(当然你可以任意选择脚位)
3, PORTD----->外接8个LED,显示读出的数据,在这里,读出的刚好是一个闪动的流水灯状态。

*******************************************************************/
#i nclude "pic.h"

#define uchar   unsigned char
#define nop()  asm("nop")
#define SCL  TRISC3
#define SDA  TRISC4

void start_i2c();
void stop_i2c();
void send_byte(uchar c);
uchar receive_byte();
void I_send_str(uchar sla,uchar suba,uchar *s,uchar no);
void delay_250ms();
void i2c_error ();

uchar code[]={0x00,0x01,0x03,0x07,0x0f,0x1f,0x3f,0x7f,0xff};
uchar no,ack,c,data;


void main(void)
{
  uchar i;
  TRISC=0Xff;     //C口设为输入 RC3为SCL线,RC4为SDA线。
  PORTC=0X00;    
  TRISD=0X00;     //D口为输出,显示IC24LC02中读出的内容
  PORTD=0X00;     //初始显示全亮

  I_send_str(0xa0,0x00,code,9); //页写入code数组到24LC02,器件地址为0Xa0,子地址为0X00,共9个数。
  
  delay_250ms();
  

  ///开始读出到D口进行显示,根据Random read时序图。
  while (1)
   {
     for (i=0x00;i<0x09;i++)
      {
       start_i2c();
       send_byte(0xa0);      //发送器件地址,即DEVICE ADDRESS。
         if (ack==0) i2c_error(); //如果24LC02无应答。则进入I2C ERROR错误指示。
       send_byte(i);         //发送字地址,即WORD ADDRESS。D口显示数组。
         if (ack==0) i2c_error();
       start_i2c();          //重新启动总线。
       send_byte(0xa1);      //发送读命令和器件地址DEVICE ADDRESS。
         if (ack==0) i2c_error();
       data=receive_byte();
       stop_i2c();
       PORTD=data;
       delay_250ms();
      }
   }
}


/*******************************************************************
起动总线函数
函数原型: void start_i2c();
Function: start on the I2C bus
*******************************************************************/
void start_i2c()
{
  SDA=1;       //发送启始条件的数据信号
  nop();
  SCL=1;
  nop();nop();nop();nop();nop(); //24LC02要求建立时间大于4,7S
  SDA=0;                      //发送起始信号
  nop();nop();nop();nop();nop();
  SCL=0;                      //钳住I2C总线,准备发送数据或接收数据
  nop();nop();
}


/*******************************************************************
停止总线函数
函数原型: void stop_i2c();
Function: stop the I2C bus
*******************************************************************/
void stop_i2c()
{
  
  SDA=0; //发送结束条件的数据信号
  nop();
  SCL=1;
  nop();nop();nop();nop();nop();
  SDA=1;
  nop();nop();nop();nop();
}

/*=================================================================
字节数据传送函数
函数原型: void send_byte(uchar c);
Function: 将数据C发送出去,可以是地址,也可以是数据,发完后等待回应,并对此状态
          位进行操作(不应答或非应答都使ack=0 ),发送数据正常,ack=1;ack=0
          表示被控器无应答或损坏。
==================================================================*/
void send_byte(uchar c)
{
  uchar bit_count;
  for (bit_count=0;bit_count<8;bit_count++)
   {
    if ((c<<bit_count)&0x80) {SDA=1;}
    else {SDA=0;}
    nop();
    SCL=1;
    nop();nop();nop();nop();nop();
    SCL=0;
   }
   nop();nop();
   SDA=1;
   nop();nop();
   SCL=1;
   nop();nop();nop();
   if (RC4==1) ack=0;
   else ack=1; //用ASK=1为有应答信号
   SCL=0;
   nop();nop();
}

/*==================================================================
字节数据接收函数
函数原型:uchar receive_byte();
FUNCTION: 用来接收从器件传来的数据,并判断总线错误(不发应答信号),
          发完后请用应答函数。
===================================================================*/
uchar receive_byte()
{
   uchar retc,bit_count;
   retc=0;
   SDA=1;
   for (bit_count=0;bit_count<8;bit_count++)
   {
      nop();
      SCL=0;
      nop();nop();nop();nop();nop();
      SCL=1;
      nop();nop();
      retc=retc<<1;
      if (RC4==1)  retc=retc+1;
      nop();nop();
    }
    SCL=0;
    nop();nop();
    return (retc);
}


/*================================================================
向有子地址器件发送多字节数据函数
函数原型: bit I_send_str(uchar sla,uchar suba,uchar *s,uchar no);
Function: 从启动总线到发送地址,数据,结束总线的全过程,从器件地址sla。如果
          返回1表示操作成功,否则操作有误。
=================================================================*/
void I_send_str(uchar sla,uchar suba,uchar *s,uchar no)
{
   uchar i;
   start_i2c();
   send_byte(sla);
   if (ack==0)  i2c_error();
   send_byte(suba);
   if (ack==0)  i2c_error();
   for (i=0;i<no;i++)
    {
      send_byte(*s);
      if (ack==0)  i2c_error();
      s++;
    }
   stop_i2c();
  // return(1);
}

/*****************************************************************
延时函数
函数原型: void delay_250ms();
FUNCTION: 延明250ms
*****************************************************************/
void delay_250ms()
{
  unsigned int d=24999;
  while (--d);
}

/*****************************************************************
总线错误函数
函数原型: void i2c_error();
Function: 通过RD7闪动8次表示总线操作失败一次报警。
*****************************************************************/
void i2c_error ()
{
  uchar i;
  for (i=0;i<8;i++)
  {
    RD7=0;
    delay_250ms();
    RD7=1;
    delay_250ms();
  }
  
}
/**********END**************/
  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
你想了解关于 Verilog 的 I2C 驱动程序吗?Verilog 是一种硬件描述语言,用于描述数字电路。I2C 是一种串行通信协议,常用于连接微控制器和外部设备。编 Verilog I2C 驱动程序可以实现对 I2C 总线的控制和通信。 下面是一个简单的 Verilog I2C 主控驱动程序例子: ```verilog module i2c_master ( input wire clk, input wire rst, output wire sda, inout wire scl ); // 定义状态 reg [7:0] state; // 定义计数器 reg [3:0] count; // 定义数据缓冲区 reg [7:0] data; // I2C 总线状态定义 parameter IDLE = 4'b0000; parameter START = 4'b0001; parameter ADDR_WRITE = 4'b0010; parameter ADDR_READ = 4'b0011; parameter SEND_DATA = 4'b0100; parameter RECEIVE_ACK = 4'b0101; parameter RECEIVE_DATA = 4'b0110; parameter SEND_ACK = 4'b0111; parameter STOP = 4'b1000; // 初始化状态和计数器 always @(posedge clk) begin if (rst) begin state <= IDLE; count <= 0; end else begin case (state) IDLE: begin // 等待起始条件 if (sda == 0 && scl == 1) state <= START; end START: begin // 发送起始条件 sda <= 0; // 进入地址发送状态 state <= ADDR_WRITE; end ADDR_WRITE: begin // 发送设备地址和命令 sda <= addr_write_data; // 进入数据发送状态 state <= SEND_DATA; end // 其他状态依此类推... endcase end end // 其他模块代码... endmodule ``` 以上代码只是一个简单的示例,实际的 Verilog I2C 驱动程序需要根据具体的应用场景和要求进行更详细的设计和实现。希望这个示例能对你有所帮助!如果有更多问题,请随时提问。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值