OpenEdv-开源电子网

 找回密码
 立即注册

扫一扫,访问微社区

正点原子新作:阿波罗STM32F767&F429&探索者STM32F4开发板&赶快来下载资料哦。

查看: 2099|回复: 1

M0+MAC+TCP/IP 以太网单芯片方案 W7500EVB用户手册连载(12)--实战篇

[复制链接]

  离线 

27

主题

59

帖子

0

精华

初级会员

Rank: 2

积分
190
金钱
190
注册时间
2018-2-23
在线时间
18 小时
发表于 2018-3-10 11:29:42 | 显示全部楼层 |阅读模式
正点原子公众号
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
回复

使用道具 举报

  离线 

27

主题

59

帖子

0

精华

初级会员

Rank: 2

积分
190
金钱
190
注册时间
2018-2-23
在线时间
18 小时
 楼主| 发表于 2018-3-10 11:31:45 | 显示全部楼层
本帖最后由 WSGustin 于 2018-3-10 11:42 编辑

第十三章 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;接口类型:串行接口:I2C;Vcc:5.5V;电源电压最大:5.5V;电源电压最小:1.8V,支持I2C通信。
I2C总线接口采用两线设计串行数据线SDA和串行时钟线SCL,可提供双向的数据传输,并连接到串行存储器RAM和ROM、网络设备、LCD、音频发生器等外部I2C设备上。本芯片支持标准模式(100Kbps)和高速模式(400Kbps)。
I2C的4个工作模式
主机发送从机接收、主机接收从机发送、从机发送主机接收、从机接收主机发送。
数据的有效性
有效的数据在时钟线的高电平期间,SDA 线上的数据必须保持稳定, SDA 线上的数据仅可在时钟 SCL 为低电平时改变。每一位数据传输触发一个时钟脉冲,如图13.1.1所示:
1.JPG

图13.1.1 有效数据范围
应答
所有总线传输都带有所需的应答时钟周期, 该时钟周期由主机产生。 在响应周期内,发送器不能执行下一操作。
START 和 STOP 条件
I2C总线协议定义了开始条件(START Condition) 和结束条件(STOP Condition) 两种状态。当 SCL 为高电平时, SDA 线上由高到低的跳变被定义为开始(START) 条件,由低到高的跳变被定义为结束条件(STOP Condition) ,如图13.1.2所示
2.JPG

图13.1.2 I2C起始和停止时序
如果说要通过I2C进行通信那么就要先发送起始信号,发送起始信号可以用I2C_Start函数来完成。
[AppleScript] 纯文本查看 复制代码
ErrorStatus I2C_Start(I2C_TypeDef* I2Cx, uint16_t slave_address, I2C_CTR ctr);
I2C_Start函数的第一个传参是选择I2C,第二个传参是从器件地址,第三个传参是I2C的读写状态位。如果要对AT24C32进行写操作可以这样写:
[AppleScript] 纯文本查看 复制代码
I2C_Start(I2C0, 0xa0, I2C_WRITE_SA7);
重启状态
开始条件(START Condition) 和 结束条件(STOP Condition) 总是由主机产生的。I2C总线在结束条件(STOP Condition) 之后一段时间重新被释放。 如果使用重新开始条件(Repeated START Condition) 条件替代结束条件(STOP Condition) 的话,I2C将会保持占用(忙)状态,如图13.1.3所示:
3.JPG

图13.1.3 I2C重启时序
从机地址
放到 SDA 线上的每个数据字节应该都是 8 位。每个字节之后跟随一个应答位,如图13.1.4所示:
4.JPG
图13.1.4 发送从机地址时序
读写位
7 位地址位之后的第 8 位是数据方向位(R/W) ,‘0’代表写操作, ‘1’ 代表读操作,也可以通过 I2Cx_CTR 寄存器的CTRRWN位来选择读写方向,‘0’代表从写模式,‘1’代表 读模式。
应答(ACK) 和无应答(NACK)
每个字节之后都有一个应答位。 应答位可以使接收者在成功接收到本字节之后,告诉发送者此数据已经被成功接收,可以发送下个字节。主机产生所有的时钟脉冲,包括应答位(第 9 位)的时钟脉冲。
需要进行数据发送时可以调用I2C_SendDataAck函数来完成:
[AppleScript] 纯文本查看 复制代码
int8_t I2C_SendDataAck(I2C_TypeDef* I2Cx,uint16_t Data);

I2C_SendDataAck函数在传输完数据后还会等待从机发送应答。
需要进行数据接收时可以调用I2C_ReceiveData函数来完成:
[AppleScript] 纯文本查看 复制代码
int I2C_ReceiveData(I2C_TypeDef* I2Cx, int last);
I2C_ReceiveData函数会返回从机发送过来的数据,第二个参数可以选择接收完数据后还发不发送应答给从机。
如果I2C跟AT24C32通信要按在AT24C32规定的时序图来操作。
写一个字节的时序是这个如图13.1.5所示:
5.JPG

图13.1.5 往AT24C32里写一个字节数据
连续写的时序是这个如图13.1.6所示:
6.JPG

图13.1.6 往AT24C32里连续写多个字节的数据
读一个字节的时序是这个如图13.1.7所示:
7.JPG

图13.1.7 从AT24C32里读一个字节数据出来
连续读的时序是这个如图13.1.8所示:
8.JPG

图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文件。
[AppleScript] 纯文本查看 复制代码
#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  #########\rundefined");
  for(i=0;i<MAX_SIZE;i+=2) 
    printf("[%02d]:0x%02x,  [%02d]:0x%02x\rundefined",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所示:
9.JPG
图13.4.1 at24c32的试验结果





回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则




QQ|联系我们|手机版|官方淘宝店|新浪微博|微信公众平台|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2018-6-24 01:28

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表
/* */