IIC介绍_2实际使用

5 IIC的实际使用

5.1 MCU做主机读写eeprom数据

5.1.1 轮询
  • IIC初始化
    • 使能IIC主机模式
    • 配置波形
    • 设置空闲超时时间
  • 轮询发送数据

IIC通信时,除了遵循基本的IIC协议,还要遵循通信设备的应用层协议,以复旦微的FM24C256E型号的eeprom为例,和这块eeprom通信时,主要目的是读写eeprom的内容,所以要明确需要往哪个地址读写数据,需要使用子地址(从机地址指的是从机地址,子地址指的是从机设备中的地址)。相关手册中定义了读写协议如下:
请添加图片描述

请添加图片描述

在通信时,是将要发送的数据放入主机发送数据寄存器(MTDR)中,这个寄存器有两个字段,分别是命令数据(CMD)和发送数据(DATA)。一般这个寄存器和数据接收寄存器(MRDR)都是fifo结构的,可以往里放fifo深度的数据,遵循先进先出原则。以MTDR为例,可以理解为放入fifo中的数据是要发送的数据,从fifo中出来的数据已经变成了波形,能被示波器或逻辑分析仪抓到(只是便于理解,都是数字信号)。

请添加图片描述

以往eeprom的0x0000地址写16个byte数据,数据内容为[0x00, 0x01…0x0F]为例:

需要首先往MTDR寄存器写入开始信号+从机地址+ 读(100b,代表开始一个start信号,并发送data数据(7位地址加写入位))

u8Addr   = (uint8)((uint8)(pRequest->u8SlaveAddress << 1) + I2C_DIR_WRITE);
eRetType = FCIIC_MasterWriteHw(u8I2cIdx, FCIIC_TX_CMD_STARTANDTRANSMIT, u8Addr);

//FCIIC_MasterWriteHw()实现功能为将CMD和DATA拼接后写入MEDR

然后往往MTDR寄存器写入子地址,从前面通信协议得知子地址长度为2byte,循环写2次

for (i = pRequest->subAddressSize; i > 0 ; --i)
{
    eRetType = FCIIC_MasterWriteHw(u8I2cIdx, FCIIC_TX_CMD_TRANSMIT, FCIIC_MTDR_DATA(pSubAddr[i - 1]));
    if (E_NOT_OK == eRetType)
    {
        break;
    }
}

循环写入需要存入eeprom中的数据,要写入16byte的数据,故循环写入16次。(写入的长度)

for (u16LoopCount = 0; u16LoopCount < u16LoopMax; u16LoopCount++)
{
    eRetType = FCIIC_MasterWriteHw(u8I2cIdx, FCIIC_TX_CMD_TRANSMIT, pRequest->BufferPtr[u16LoopCount]));
    /* if u8RetVal == 1 means send timeout */
    if (E_NOT_OK == eRetType)
    {
        break;
    }
}

最后写入stop信号

FCIIC_MasterWriteHw(u8I2cIdx, FCIIC_TX_CMD_STOP, 0x00);

信号波形如图
请添加图片描述

读取的时候,发送完子地址信息后,继续发送一帧数据:起始信号+从机地址+读取方向;然后还有一帧数据,代表需要读取数据的长度(根据这个决定SCL的长度,没有相应波形产生)。

if (I2C_DIR_READ == pRequest->u8Direction)
{
    u8Addr   = (uint8)((uint8)(pRequest->u8SlaveAddress << 1) + I2C_DIR_READ);
    eRetType = FCIIC_MasterWriteHw(u8I2cIdx, FCIIC_TX_CMD_STARTANDTRANSMIT, u8Addr);
    if (E_OK == eRetType)
    {
        eRetType = FCIIC_MasterWriteHw(u8I2cIdx, FCIIC_TX_CMD_RECEIVE, (uint8)(pRequest->u16Len - 1));
    }
}

请添加图片描述

5.1.2 中断

中断和轮询相比,需要配置中断寄存器,打开发送数据中断使能(TDIE)和接收数据中断使能(RDIE),打开相应中断。如果发送数据寄存器(MDTR)的fifo是空的(或者低于设定的阈值),发送数据标志位就会被置上,代表需要往fifo中填充数据,中断打开会就会进入发送数据中断,在中断中不断往MDTR寄存中填充数据,完成发送,填充数据的流程和轮询一致。(如果是读,方向相反,当接收数据寄存器中不为空时,进中断,读取fifo中的数据)。

5.1.3 DMA

DMA和轮询相比,就是往MDTR中填充数据的时候,提前配置好DMA,通过DMA的方式填充,避免手动挨个填充。(读取方向相反)

for (u16LoopCount = 0; u16LoopCount < u16LoopMax; u16LoopCount++)
{
    eRetType = FCIIC_MasterWriteHw(u8I2cIdx, FCIIC_TX_CMD_TRANSMIT, pRequest->BufferPtr[u16LoopCount]));
    /* if u8RetVal == 1 means send timeout */
    if (E_NOT_OK == eRetType)
    {
        break;
    }
}
//即将这部分代码替换为下面的代码,就是开启DMA的数据发送(需要提前配置好DMA,这里只是开启DMA的搬运)
FCIIC_MasterDmaStart(u8I2cIdx, pRequest);

5.2 MCU做从机

5.2.1 中断
  • IIC初始化
    • 使能IIC从机模式
    • 设置从机地址
  • 开启监听
    • 开启地址匹配接收中断((当主机发送的地址和IIC外设设置的从机地址一致时,会进中断)
  • 此时主机发送数据,从机地址匹配就会进入地址匹配中断(IIC),查看IIC从机状态寄存器,可以发现AMF(地址匹配标志位)置1。
  • 中断处理(IIC):根据中断原因做出回应
    • 发送ack(作为地址和读写判断位的回应)
    • 根据接收到的第一个byte数据中的读写位判断读写方向
    • 根据读写方向使能对应的IIC中断
      • 如果是读,说明MCU做从机应当发送数据,使能从机发送中断
      • 如果是写,方向相反
  • 中断处理(IIC): 进入读写中断
    • 中断发送数据或读取数据
  • 中断处理(IIC):进入结束信号中断
    • 清状态,关读写中断

工具测试可参照DMA从机方式,中断和DMA的区别是DMA需要提前配置好一帧数据长度(配置DMA时需要使用),中断不需要,中断是以stop信号进入stop中断结束。

5.2.2 DMA
  • IIC初始化
    • 使能IIC从机模式
    • 使能DMA发送接收数据
    • 设置从机地址
  • 开启监听
    • 关闭发送接收数据中断使能(打开后发送fifo是空的,会一直进中断)
    • 配置DMA(DMA发送长度(所以IIC做从机使用DMA方式需要提前知道数据长度),DMA传输目标地址等等)
    • 使能地址匹配接收中断(当主机发送的地址和IIC外设设置的从机地址一致时,会进中断)
    • 使能停止信号检测中断
  • 此时主机发送数据,从机地址匹配就会进入地址匹配中断(IIC),查看IIC从机状态寄存器,可以发现AMF(地址匹配标志位)置1。
  • 中断处理(IIC):根据中断原因做出回应
    • 发送ack(作为地址和读写判断位的回应)
    • 根据接收到的第一个byte数据中的读写位判断读写方向
    • 根据读写方向使能对应的DMA通道
      • 如果是读,说明MCU做从机应当发送数据,将发送数据buffer中的数据搬到IIC发送fifo寄存器中完成发送
      • 如果是写,方向和读相反
  • 中断处理(DMA):当DMA搬运结束后触发DMA中断
    • 发送(接收)完成
  • 中断处理(IIC):接收到结束信号后进入IIC中断
    • 判断是否发送完成,发送接收长度是否和需求长度一致。

使用IIC工具做主机,从地址和MCU设置保持一致,读取数据,读取数据为buffer中设置的数据,同时抓取波形。

请添加图片描述

请添加图片描述

然后发送数据,同时抓取波形

请添加图片描述

请添加图片描述

再次读取数据,同时抓取波形,和写入数据一致:

请添加图片描述

请添加图片描述

写入数据和读取数据一致,通信成功。

5.3 主机从机区别

  • 初始化配置不同
    • 主机需要配置波特率,波形等等;从机不需要配置,波特率是由主机决定的
    • 从机需要配置从机地址;主机不需要
  • 发送读取数据由主机决定
    • 主机随时开始读取发送数据,从机只能开启监听等待(打开从地址匹配中断,从地址匹配后开始响应)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

@Nascent

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值