查看: 2013  |  回复: 1
M0+MAC+TCP/IP 以太网单芯片方案 W7500EVB用户手册连载(12)--实战...

主题

回复
发表于2018-03-10 11:06:24 | 显示全部楼层
1# 电梯直达
W7500(W7500P)芯片简介: 
W7500 芯片为工业级以太网单芯片解决方案, 集成 ARM Cortex-M0,128KB Flash 及全硬件TCP/IP 核(和W5500、W5100内核一致),特别适用于物联网领域。 使用 W7500EVB, 让您轻松完成原型开发。

全硬件TCP/IP核的最大优点是他在执行联网操作时不需要占用MCU的运行资源,大大增加了MCU的工作效率。

本次试验目的是通过W7500EVB的硬件I2C接口实现与AT24C32存储芯片通信,达到数据的存储目的。

想了解更多关于WIZnet W7500更多信息,或者有技术问题请联系我们:gustin@wisioe.com
深圳炜世科技—WIZnet官方代理商,全程技术支持,价格绝对优势!
电话:0755-86568556
邮箱:support@wisioe.com

主题

回复
发表于2018-03-10 11:16:36   |  显示全部楼层
2#

第十三章 AT24C32试验

本次试验目的是通过W7500EVB的硬件I2C接口实现与AT24C32存储芯片通信,达到数据的存储目的。
本章分为如下几个部分:
13.1 AT24C32
简介
13.2
硬件设计
13.3
软件设计
13.4
下载验证


13.1 AT24C32 简介

存储器容量:32Kbit;时钟频率:1MHz;电源电压范围:1.8V 3.6V;针脚数:8;存储类型:EEPROM;工作温度最低:-40°C;工作温度最高:+85°C接口类型:串行接口:I2CVcc5.5V电源电压最大:5.5V;电源电压最小:1.8V,支持I2C通信。

I2C总线接口采用两线设计串行数据线SDA和串行时钟线SCL,可提供双向的数据传输,并连接到串行存储器RAMROM、网络设备、LCD、音频发生器等外部I2C设备上。本芯片支持标准模式(100Kbps)和高速模式(400Kbps)。

I2C4个工作模式

主机发送从机接收、主机接收从机发送、从机发送主机接收、从机接收主机发送。

数据的有效性

有效的数据在时钟线的高电平期间,SDA 线上的数据必须保持稳定, SDA 线上的数据仅可在时钟 SCL 为低电平时改变。每一位数据传输触发一个时钟脉冲,如图13.1.1所示:

 


13.1.1 有效数据范围

应答

所有总线传输都带有所需的应答时钟周期, 该时钟周期由主机产生。 在响应周期内,发送器不能执行下一操作。

START STOP 条件

I2C总线协议定义了开始条件(START Condition) 和结束条件(STOP Condition) 两种状态。当 SCL 为高电平时, SDA 线上由高到低的跳变被定义为开始(START) 条件,由低到高的跳变被定义为结束条件(STOP Condition) ,如图13.1.2所示

 


13.1.2 I2C起始和停止时序

如果说要通过I2C进行通信那么就要先发送起始信号,发送起始信号可以用I2C_Start函数来完成。

ErrorStatus I2C_Start(I2C_TypeDef* I2Cx, uint16_t slave_address, I2C_CTR ctr);

I2C_Start函数的第一个传参是选择I2C,第二个传参是从器件地址,第三个传参是I2C的读写状态位。如果要对AT24C32进行写操作可以这样写:

I2C_Start(I2C0, 0xa0, I2C_WRITE_SA7);

重启状态

开始条件(START Condition) 和 结束条件(STOP Condition) 总是由主机产生的。I2C总线在结束条件(STOP Condition) 之后一段时间重新被释放。 如果使用重新开始条件(Repeated START Condition) 条件替代结束条件(STOP Condition) 的话,I2C将会保持占用()状态,如图13.1.3所示:

 


13.1.3 I2C重启时序

从机地址

放到 SDA 线上的每个数据字节应该都是 8 位。每个字节之后跟随一个应答位,如图13.1.4所示:

 

13.1.4 发送从机地址时序

读写位

7 位地址位之后的第 8 位是数据方向位(R/W) ‘0’代表写操作, ‘1’ 代表读操作,也可以通过 I2Cx_CTR 寄存器的CTRRWN位来选择读写方向,‘0’代表从写模式,‘1’代表 读模式。

应答(ACK) 和无应答(NACK)

每个字节之后都有一个应答位。 应答位可以使接收者在成功接收到本字节之后,告诉发送者此数据已经被成功接收,可以发送下个字节。主机产生所有的时钟脉冲,包括应答位(第 9 位)的时钟脉冲。

需要进行数据发送时可以调用I2C_SendDataAck函数来完成:

int8_t I2C_SendDataAck(I2C_TypeDef* I2Cx,uint16_t Data);

I2C_SendDataAck函数在传输完数据后还会等待从机发送应答。

需要进行数据接收时可以调用I2C_ReceiveData函数来完成:

int I2C_ReceiveData(I2C_TypeDef* I2Cx,int last);

I2C_ReceiveData函数会返回从机发送过来的数据,第二个参数可以选择接收完数据后还发不发送应答给从机。

如果I2CAT24C32通信要按在AT24C32规定的时序图来操作。

写一个字节的时序是这个如图13.1.5所示:

 


13.1.5 AT24C32里写一个字节数据

连续写的时序是这个如图13.1.6所示:

 


13.1.6 AT24C32里连续写多个字节的数据

读一个字节的时序是这个如图13.1.7所示:

 


13.1.7 AT24C32里读一个字节数据出来

连续读的时序是这个如图13.1.8所示:

 


13.1.8 AT24C32里读连续多个字节数据出来

13.2 硬件设计

本章试验简介:向AT24C32写入8个数据,写入成功后再将数据读出来,最后再将第二个数据加1再次写入AT24C32中,不断更新数据来确保数据的准确性。

本实验用到的硬件资源有:

1)      串口

2)      硬件I2C

3)      AT24C32

W7500EVB与AT24C32连线说明

SCL  ---> PA_09

SDA  --->  PA_10

13.3 软件设计

打开 AT24C32实验工程,可以看到工程里有一个文件at24c32.c文件。


#define MAX_SIZE 8

void AT24C32_I2C_Init(void) 
{
  I2C_ConfigStruct I2C_InitStructure; 
  I2C_InitStructure.mode = I2C_Master;                  //选择主机模式
  I2C_InitStructure.slave_address = Slave_address;  //器件地址
  I2C_InitStructure.master.prescale = 0x61;             //分频
  I2C_InitStructure.master.timeout = 0xFFFF;           //等待超时时间
  /* Cofigure I2C0 */
  I2C_Init(I2C0, I2C_InitStructure);                          //I2C初始化
}

void I2C_Test(void) 
{
  static uint8_t TX_Data[MAX_SIZE]={0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08};
  uint8_t i,RX_Data[MAX_SIZE]="\0";
       
  I2C_Burst_Write(I2C0,Slave_address,Memory_address,TX_Data,MAX_SIZE); //连续写函数
  I2C_Burst_Read(I2C0,Slave_address,Memory_address,RX_Data,MAX_SIZE); //连续读函数
       
  printf("########  I2C EEPROM TEST  #########\r\n");
  for(i=0;i<MAX_SIZE;i+=2) 
    printf("[%02d]:0x%02x,  [%02d]:0x%02x\r\n",i,RX_Data[i],i+1,RX_Data[i+1]); 
  TX_Data[1]+=1; 
}


SHAPE \* MERGEFORMAT
int I2C_Burst_Read(I2C_TypeDef* I2Cx, uint16_t address, uint16_t memory_address, uint8_t *rx_data, int length)
{

  int recv_cnt;

  I2C_Reset(I2Cx); /* I2C复位 */

  if(I2C_Start(I2Cx,address,I2C_WRITE_SA7) != ERROR)                     //起始信号加器件地址写

  {

    if(I2C_SendDataAck(I2Cx,(memory_address >> 8)) == ERROR)       //EEPROM的内存地址高位

    {

      I2C_Stop(I2Cx);

      return -1;

    }

    if(I2C_SendDataAck(I2Cx,(memory_address & 0xff)) == ERROR)     //EEPROM的内存地址低位

    {

      I2C_Stop(I2Cx);

      return -1;

    }

    I2C_Delay(0x01);                                                                         //用延时来增加稳定性

    if(I2C_Restart_Structure(I2Cx,address,I2C_READ_SA7) == ERROR)  //重发起始信号加器件地址读

    {

      I2C_Stop(I2Cx);

      return -1;

    }

    for(recv_cnt=0;recv_cnt<length;recv_cnt++)

    {

      rx_data[recv_cnt] = I2C_ReceiveData(I2Cx,0);                               //连续读取数据

    }

    I2C_Delay(0x01);                                                                          //用延时来增加稳定性

    I2C_Stop(I2Cx);                                                                            //发送停止信号

  }

  I2C_Delay(0x000F0000);                                                                  //读写之间必须要有延时

  return length;

}


int I2C_Burst_Write(I2C_TypeDef* I2Cx, uint16_t address, uint16_t memory_address, uint8_t *tx_data, int length)

{

  int cnt;

      

  I2C_Reset(I2Cx); /* I2C复位 */

  //只要有一种起始方式能开启它都可以

  if(I2C_Start(I2Cx,address,I2C_WRITE_SA7) != ERROR || I2C_Restart_Structure(I2Cx,address,I2C_WRITE_SA7) != ERROR)


SHAPE \* MERGEFORMAT
  {

    if(I2C_SendDataAck(I2Cx,(memory_address >> 8)) == ERROR)       //EEPROM的内存地址高位

    {

      I2C_Stop(I2Cx);

      return -1;

    }

if(I2C_SendDataAck(I2Cx,(memory_address & 0xff)) == ERROR)     //EEPROM的内存地址低位

    {

      I2C_Stop(I2Cx);

      return -1;

    }

for(cnt=0;cnt<length;cnt++)

    {

      if(I2C_SendDataAck(I2Cx,tx_data[cnt]) == ERROR)                      //连读发送数据

      {

        I2C_Stop(I2Cx);

        return -1;

      }

      I2C_Delay(0x01);                                                                      //用延时来增加稳定性

    }

    I2C_Stop(I2Cx);                                                                          //发送停止信号

  }

  I2C_Delay(0x000F0000);                                                                //读写之间必须要有延时

  return length;

}


at24c32.c文件中写的代码都是按照AT24C32的时序来写的。

13.4 下载验证

在代码编译成功之后,下载代码到 W7500EVB 开发板上,可以看到串口打印出来的数据。如图13.4.1所示:

 


13.4.1 at24c32的试验结果


主题

回复
  • 温馨提示: 标题不合格、重复发帖、发布广告贴,将会被删除帖子或禁止发言。 详情请参考: 社区发帖规则
  • 您当前输入了 0 个文字。还可以输入 8000 个文字。 已添加复制上传图片功能,该功能目前仅支持chrome和火狐

禁言/删除

X
请选择禁言时长:
是否清除头像:
禁言/删除备注:
昵 称:
 
温馨提示:昵称只能设置一次,设置后无法修改。
只支持中文、英文和数字。

举报

X
请选择举报类型:
请输入详细内容:

顶部