查看:
2038
|
回复:
1
|
M0+MAC+TCP/IP 以太网单芯片方案 W7500EVB用户手册连载(12)--实战...
|
|
WSGustin
29
主题
48
回复 |
发表于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 |
|
WSGustin
29
主题
48
回复 |
发表于2018-03-10 11:16:36
|
显示全部楼层
2#
第十三章 AT24C32试验本次试验目的是通过W7500EVB的硬件I2C接口实现与AT24C32存储芯片通信,达到数据的存储目的。 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所示:
图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函数来完成:
I2C_SendDataAck函数在传输完数据后还会等待从机发送应答。 需要进行数据接收时可以调用I2C_ReceiveData函数来完成:
I2C_ReceiveData函数会返回从机发送过来的数据,第二个参数可以选择接收完数据后还发不发送应答给从机。 如果I2C跟AT24C32通信要按在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的试验结果 |
|