目录

芯课堂 | SWM341 I2C 接口应用

一、I2C 简介

物理连接

I2C总线由时钟线SCL、数据线SDA两根线构成,连接在其上的设备分为主机和从机两种,I2C上的通信全部由主机发起。

I2C设备对总线的输出采用开漏输出结构,即它只有在总线和GND之间的NMOS管,没有总线和VDD之间的PMOS管。输出0时通过开启NMOS管将总线与GND短接;输出1时无法像推挽输出那样开启PMOS管将总线与VDD短接,而是只能通过关闭NMOS从而由外接的上拉电阻将总线拉到高电平。

由于上拉电阻阻值一般比较大(10K欧姆),因此如果此时有其他I2C设备输出0,总线会被拉到低电平。只有当总线上的所有设备都不输出0时,总线才是高电平;只要有一个设备输出0,总线就是低电平,这也就是所谓的"线与"。这是I2C总线应答与多主机通信的基础。

协议格式

0、空闲时总线上所有设备都不驱动总线,即都不开启NMOS管,总线由外部上拉电阻拉到高电平。

1、I2C上的通信全部由主机发起,主机通过发送起始位启动传输,起始位由SCL为高时SDA线上的下降沿产生。

2、起始位后面跟7位地址和1位读写方向指示(0表示主机向从机写入,1表示主机从从机读取),主机发送完这8位后停止驱动总线,总线由外部上拉电阻拉到高电平,被寻址的从机输出0将总线拉低。主机检测到这个低电平,就知道从机可以相应主机请求,可以进行数据传输。

3、数据传输阶段,若R/W=0,则主机发送数据,从机发送响应;若R/W=1,则从机发送数据,主机发送响应,每传输一个字节数据,后面都跟一个响应位。

4、数据传输完成后,主机发送停止位终止传输,终止位由SCL为高时SDA线上的上升沿产生。

5、由于SCL为高时,SDA的上升沿、下降沿均有特殊含义,因此I2C中数据传输时,SDA只在SCL为低时变化,在SCL为高时保持不变。即发送方在SCL为低时改变SDA状态,接收方在SCL上升沿读取SDA状态。

二、SWM341 I2C 接口

功能框图

SWM341 I2C 的核心是一个双向移位寄存器,发送时,数据通过TXDATA寄存器写入移位寄存器,然后按位移除到SDA引脚;接收时,将SDA引脚状态移入移位寄存器,通过RXDATA寄存器读出。

移位寄存器的移位节拍来自内部I2C时钟分频器(主机模式下)或SCL引脚(从机模式下),主机模式下时钟分频器产生的时钟同时输出到SCL引脚,驱动总线上的I2C从机的移位寄存器。

使用示例:读写 EEPROM AT24C024

int main(void)

{

uint32_t i;

uint8_t ack;

SystemInit();

SerialInit();

I2CMstInit();

while(1==1)

{

/*************** EEPROM Write ***************/

ack = I2C_Start(I2C0, (SLV_ADDR << 1) | 0, 1);

if(ack == 0)

{

printf("Slave send NACK for address\r\n");

goto nextloop;

}

ack = I2C_Write(I2C0, MEM_ADDR, 1);

if(ack == 0)

{

printf("Slave send NACK for memory address\r\n");

goto nextloop;

}

for(i = 0; i < 4; i++)

{

ack = I2C_Write(I2C0, txbuff[i], 1);

if(ack == 0)

{

printf("Slave send NACK for data\r\n");

goto nextloop;

}

}

I2C_Stop(I2C0, 1);

printf("Master Write %X %X %X %X @ %X\r\n", txbuff[0], txbuff[1], txbuff[2], txbuff[3], MEM_ADDR);

for(i = 0; i < 1000000; i++) __NOP(); // 延时等待内部写入操作完成

/*************** EEPROM Read ***************/

ack = I2C_Start(I2C0, (SLV_ADDR << 1) | 0, 1);

if(ack == 0)

{

printf("Slave send NACK for address\r\n");

goto nextloop;

}

ack = I2C_Write(I2C0, MEM_ADDR, 1);

if(ack == 0)

{

printf("Slave send NACK for memory address\r\n");

goto nextloop;

}

for(i = 0; i < CyclesPerUs; i++) __NOP(); // 不加此延时,系统主频高于 100MHz 时,re-start 发不出来

ack = I2C_Start(I2C0, (SLV_ADDR << 1) | 1, 1);

if(ack == 0)

{

printf("Slave send NACK for address\r\n");

goto nextloop;

}

for(i = 0; i < 3; i++)

{

rxbuff[i] = I2C_Read(I2C0, 1, 1);

}

rxbuff[i] = I2C_Read(I2C0, 0, 1);

printf("Master Read %X %X %X %X @ %X\r\n", rxbuff[0], rxbuff[1], rxbuff[2], rxbuff[3], MEM_ADDR);

if((txbuff[0] == rxbuff[0]) && (txbuff[1] == rxbuff[1]) && (txbuff[2] == rxbuff[2]) && (txbuff[3] == rxbuff[3]))

printf("Success\r\n");

else

printf("Fail\r\n");

nextloop:

I2C_Stop(I2C0, 1);

for(i = 0; i < SystemCoreClock/3; i++) __NOP();

}

}


I2C_Start()的参数是7位从机地址和读写方向选择位,调用该函数在I2C总线上产生起始位,然后发送地址和方向位,读取从机响应位ACK并返回。执行该函数后需要检查返回的从机响应ack,若有从机相应,则继续后续读写操作;若没有从机相应,则打印调试信息然跳转到程序末尾。

EEPROM AT24C02 的 Page Write 帧格式如下

设备地址后,需要发送要将数据写入EEPROM的位置(Word Address),然后再发送要写入的数据。程序中首先执行 I2C_Write(I2C0, MEM_ADDR, 1) 发送数据在EEPROM中的存储位置,然后执行 I2C_Write(I2C0, txbuff[i], 1) 将要写入 EEPROM的数据逐个发出。最后执行 I2C_Stop(I2C0, 1) 在总线上产生停止条件,终止数据传输。

需要注意的是,以上操作只是将要写入EEPROM的数据通过I2C接口写入EEPROM内部缓存中,EEPROM还需要一定时间将缓存中的数据写入实际存储介质中。若此时立即读取EEPROM,读取到的依然会是写入之前的数据。查手册可知,AT24C02 的写入时间大概 5ms。

AT24C02 的读取操作与上述的写入操作类似,唯一不同的是,在读取操作中,响应ACK由主机发送、从机检查,I2C_Read()调用中需要给出本次读取后响应ACK还是NAK(即不响应,不在ACK位时将SDA拉低)。在读取前面的数据时,需要响应ACK,以通知从机准备好后续数据;读取最后一个数据时,最好响应NAK,通知从机主机不再需要后续数据。

本文是转载文章,点击查看原文
如有侵权,请联系 xyy@jishuzhan.net 删除
相关推荐
lin辰傍边的风2 小时前
关于STM32G030和G070未初始化看门狗,程序里面喂狗会导致擦除Flash失败或进入‘HardFault_Handler’
stm32·单片机·嵌入式硬件
冻结的鱼2 小时前
STM32N6 平台如何使用 MCO2 输出 Clock
stm32·单片机·嵌入式硬件
FreakStudio3 小时前
一文速通Python并行计算:09 Python多进程编程-进程之间的数据同步-基于互斥锁、递归锁、信号量、条件变量、事件和屏障
单片机·嵌入式·大学生·面向对象·多进程·技术栈·并行计算·电子diy
Rousson3 小时前
硬件学习笔记--57 MCU相关资源介绍
笔记·单片机·mcu·学习
XINVRY-FPGA4 小时前
XCZU7EG‑L1FFVC1156I 赛灵思XilinxFPGA ZynqUltraScale+ MPSoC EG
c++·嵌入式硬件·阿里云·fpga开发·云计算·fpga·pcb工艺
双叶8367 小时前
(51单片机)LCD显示数据存储(DS1302时钟模块教学)(LCD1602教程)(独立按键教程)(延时函数教程)(I2C总线认识)(AT24C02认识)
c语言·数据库·单片机·嵌入式硬件·mongodb·51单片机·nosql
wutianxin08 小时前
硬件测试项之电源纹波的测量和纹波的要求、纹波的抑制
嵌入式硬件·硬件工程
格里姆肖8 小时前
HAL库通过FATFS和SDIO+DMA写入SD卡数据错误
c语言·stm32·单片机
嘿,二极管8 小时前
硬件工程师面试常见问题(4)
单片机·嵌入式硬件
易知嵌入式小菜鸡9 小时前
STM32CubeMX-H7-15-SPI通信协议读写W25Q64
stm32·嵌入式硬件·fpga开发