【ZYNQ】IIC 简介及 EMIO 模拟 IIC 驱动示例

简介: 【ZYNQ】IIC 简介及 EMIO 模拟 IIC 驱动示例

IIC 简介

IIC (Inter-Integrated Circuit) 总线是一种由 NXP (原PHILIPS) 公司开发的两线式串行通信总线,多用于主控制器和从设备之间的主从式通信,且任意时刻只能有一个主机。


IIC 总线由数据线 SDA 和时钟线 SCL 构成,可实现在主控制器与被控设备之间、设备与设备之间双向通信,高速 IIC 总线一般可达 400kbps 以上。


为驱动实验室自研基于 DAC60502 的双通道电流输出模块,基于 ZYNQ 平台,将 PS 端的 GPIO 资源通过 EMIO 引出到 PL 端,使用 PL 端引脚资源连接 IIC 从设备,既使用 EMIO 模拟 IIC 实现主从通信控制。

模拟 IIC 示例代码
  • iic_io.c
/**
 * Copyright (c) 2022-2023,HelloAlpha
 * 
 * Change Logs:
 * Date           Author       Notes
 */
#include "iic_io.h"

extern XGpioPs GpioPs;

void SCL_OUT(void)
{
    XGpioPs_SetDirectionPin(&GpioPs, SCL_PIN, GPIO_MODEL_OUTPUT);
    XGpioPs_SetOutputEnablePin(&GpioPs, SCL_PIN, GPIO_OUTPUT_ENABLE);
}

void SCL_HIGH(void)
{
    XGpioPs_WritePin(&GpioPs, SCL_PIN, GPIO_SET);
}

void SCL_LOW(void)
{
    XGpioPs_WritePin(&GpioPs, SCL_PIN, GPIO_RESET);
}

void SDA_IN(void)
{
    XGpioPs_SetDirectionPin(&GpioPs, SDA_PIN, GPIO_MODEL_INPUT);
}

uint32_t SDA_READ(void)
{
    return XGpioPs_ReadPin(&GpioPs, SDA_PIN);
}

void SDA_OUT(void)
{
    XGpioPs_SetDirectionPin(&GpioPs, SDA_PIN, GPIO_MODEL_OUTPUT);
    XGpioPs_SetOutputEnablePin(&GpioPs, SDA_PIN, GPIO_OUTPUT_ENABLE);
}

void SDA_HIGH(void)
{
    XGpioPs_WritePin(&GpioPs, SDA_PIN, GPIO_SET);
}

void SDA_LOW(void)
{
    XGpioPs_WritePin(&GpioPs, SDA_PIN, GPIO_RESET);
}

int IIC_Init(void)
{
    SCL_OUT();
    SCL_HIGH();
    SDA_OUT();
    SDA_HIGH();

    return 0;
}
  • iic_io.h
/**
 * Copyright (c) 2022-2023,HelloAlpha
 *
 * Change Logs:
 * Date           Author       Notes
 */
#ifndef __IIC_IO_H__
#define __IIC_IO_H__

#include "xgpiops.h"

#define SCL_PIN           54
#define SDA_PIN           55

#define GPIO_MODEL_INPUT        0
#define GPIO_MODEL_OUTPUT       1

#define GPIO_OUTPUT_DISABLE     0
#define GPIO_OUTPUT_ENABLE      1

#define GPIO_RESET              0
#define GPIO_SET                1

void SCL_OUT(void);
void SCL_HIGH(void);
void SCL_LOW(void);

void SDA_IN(void);
uint32_t SDA_READ(void);

void SDA_OUT(void);
void SDA_HIGH(void);
void SDA_LOW(void);

int IIC_Init(void);

#endif
  • iic_ctrl.c
/**
 * Copyright (c) 2022-2023,HelloAlpha
 *
 * Change Logs:
 * Date           Author       Notes
 */
#include "iic_ctrl.h"
#include "sleep.h"

#define I2C_DELAY(...)  usleep(__VA_ARGS__)

void IIC_Start(void)
{
    SDA_OUT();
    SDA_HIGH();
    SCL_HIGH();
    I2C_DELAY(4);
    SDA_LOW();
    I2C_DELAY(4);
    SCL_LOW();
    I2C_DELAY(2);
}
 
void IIC_Stop(void)
{
    SDA_OUT();
    SCL_LOW();
    SDA_LOW();
    I2C_DELAY(4);
    SCL_HIGH();
    SDA_HIGH();
    I2C_DELAY(4);
}
 
// 1,接收应答失败
// 0,接收应答成功
uint8_t IIC_Wait_Ack(void)
{
    uint8_t ucErrTime=0;

    SDA_OUT();
    SDA_HIGH();
    I2C_DELAY(1);
    SCL_HIGH();
    I2C_DELAY(1);
    SDA_IN();
    while(SDA_READ())
    {
        ucErrTime++;
        if(ucErrTime > 250)
        {
            IIC_Stop();
            return 1;
        }
    }
    SCL_LOW();
    return 0;  
}

//产生ACK应答
void IIC_Ack(void)
{
    SCL_LOW();
    SDA_OUT();
    SDA_LOW();
    I2C_DELAY(2);
    SCL_HIGH();
    I2C_DELAY(2);
    SCL_LOW();
}
//不产生ACK应答
void IIC_NAck(void)
{
    SCL_LOW();
    SDA_OUT();
    SDA_HIGH();
    I2C_DELAY(2);
    SCL_HIGH();
    I2C_DELAY(2);
    SCL_LOW();
}       

void IIC_Write_Byte(uint8_t data)
{
    uint8_t  i = 0;
 
    SDA_OUT();
    SCL_LOW();
    for(i=0; i<8; i++)
    {
        if(data & 0x80 )
            SDA_HIGH();
        else
            SDA_LOW();
        data <<= 1;
        I2C_DELAY(2);
        SCL_HIGH();
        I2C_DELAY(2);
        SCL_LOW();
        I2C_DELAY(2);
    }
}

// ack = 1,发送 ACK
// ack = 0,发送 nACK
uint8_t IIC_Read_Byte(uint8_t ack)
{
    uint8_t i = 0, data = 0;
 
    SDA_IN();
    for(i = 0; i < 8; i++)
    {
        SCL_LOW();
        I2C_DELAY(2);
         SCL_HIGH();
        data <<= 1;
        if(SDA_READ())
            data++;
        I2C_DELAY(1);
    }
    if(!ack)
        IIC_NAck();
    else
        IIC_Ack();
    return data;
}
 
void IIC_Write_UINT16(uint8_t dev_addr, uint8_t wr_addr, uint16_t data)
{
    IIC_Start();
    IIC_Write_Byte(dev_addr);
    IIC_Wait_Ack(); 
    IIC_Write_Byte(wr_addr);
    IIC_Wait_Ack(); 
    IIC_Write_Byte(data >> 8);
    IIC_Wait_Ack(); 
    IIC_Write_Byte(data & 0xFF);
    IIC_Wait_Ack();   
    IIC_Stop();
    I2C_DELAY(800);
}

uint16_t IIC_Read_UINT16(uint8_t dev_addr, uint8_t rd_addr)
{
    uint16_t data;

    IIC_Start();
    IIC_Write_Byte(dev_addr);
    IIC_Wait_Ack();
    IIC_Write_Byte(rd_addr);
    IIC_Wait_Ack(); 

    IIC_Start();    
    IIC_Write_Byte(dev_addr + 1);
    IIC_Wait_Ack();
    data = IIC_Read_Byte(1);
    data = (data <<8 ) + IIC_Read_Byte(0);
    IIC_Stop();

    return data;
}


  • iic_ctrl.h
/**
 * Copyright (c) 2022-2023,HelloAlpha
 *
 * Change Logs:
 * Date           Author       Notes
 */
#ifndef __I2C_CTRL_H__
#define __I2C_CTRL_H__

#include "iic_io.h"

void IIC_Start(void);
void IIC_Stop(void);
uint8_t IIC_Wait_Ack(void);
void IIC_Ack(void);     
void IIC_NAck(void);
void IIC_Write_Byte(uint8_t value );
uint8_t IIC_Read_Byte(uint8_t addr);
void IIC_Write_UINT16(uint8_t dev_addr, uint8_t wr_addr, uint16_t data);
uint16_t IIC_Read_UINT16(uint8_t dev_addr, uint8_t rd_addr);

#endif

软件模拟 IIC 最大的优点就在于方便移植,但相对于硬件 IIC 来说,模拟 IIC 通信速率要慢得多。

  • 自问:那为啥不用硬件 IIC
  • 自答:就想用模拟的嘿嘿嘿
相关实践学习
通过Ingress进行灰度发布
本场景您将运行一个简单的应用,部署一个新的应用用于新的发布,并通过Ingress能力实现灰度发布。
容器应用与集群管理
欢迎来到《容器应用与集群管理》课程,本课程是“云原生容器Clouder认证“系列中的第二阶段。课程将向您介绍与容器集群相关的概念和技术,这些概念和技术可以帮助您了解阿里云容器服务ACK/ACK Serverless的使用。同时,本课程也会向您介绍可以采取的工具、方法和可操作步骤,以帮助您了解如何基于容器服务ACK Serverless构建和管理企业级应用。 学习完本课程后,您将能够: 掌握容器集群、容器编排的基本概念 掌握Kubernetes的基础概念及核心思想 掌握阿里云容器服务ACK/ACK Serverless概念及使用方法 基于容器服务ACK Serverless搭建和管理企业级网站应用
相关文章
|
8月前
|
传感器 编解码 API
【STM32开发入门】温湿度监测系统实战:SPI LCD显示、HAL库应用、GPIO配置、UART中断接收、ADC采集与串口通信全解析
SPI(Serial Peripheral Interface)是一种同步串行通信接口,常用于微控制器与外围设备间的数据传输。SPI LCD是指使用SPI接口与微控制器通信的液晶显示屏。这类LCD通常具有较少的引脚(通常4个:MISO、MOSI、SCK和SS),因此在引脚资源有限的系统中非常有用。通过SPI协议,微控制器可以向LCD发送命令和数据,控制显示内容和模式。
277 0
|
10月前
|
Perl
【ZYNQ】SPI 简介及 EMIO 模拟 SPI 驱动示例
【ZYNQ】SPI 简介及 EMIO 模拟 SPI 驱动示例
852 0
|
传感器
STM32F407软件模拟I2C实现MPU6050通讯(CUBEIDE)(下)
STM32F407软件模拟I2C实现MPU6050通讯(CUBEIDE)(下)
677 0
STM32F407软件模拟I2C实现MPU6050通讯(CUBEIDE)(上)
STM32F407软件模拟I2C实现MPU6050通讯(CUBEIDE)
306 0
|
10月前
|
测试技术 Perl
【ZYNQ】ZYNQ7000 UART 控制器及驱动应用示例
【ZYNQ】ZYNQ7000 UART 控制器及驱动应用示例
377 0
14 STM32之IIC通信(软件模拟篇)
14 STM32之IIC通信(软件模拟篇)
|
传感器 芯片 内存技术
STM32与测温芯片ADT7410通过模拟IIC通信
STM32与测温芯片ADT7410通过模拟IIC通信
STM32与测温芯片ADT7410通过模拟IIC通信
|
编解码 C语言 芯片
STM32入门开发:编写XPT2046电阻触摸屏驱动(模拟SPI)
STM32入门开发:编写XPT2046电阻触摸屏驱动(模拟SPI)
780 0
STM32入门开发:编写XPT2046电阻触摸屏驱动(模拟SPI)
IIC总线接口简介
1、IIC总线接口操作模式:        主传送模式、主接收模式、从传送模式和从接收模式 2、起始和停止条件     当I2C总线接口未被激活时,一般处于从模式,也就是说,在检测到SDA线上的启动条件之前,接口应处于从模式(当SCL时钟信号保持高电平时,SDA线由高电平到低电平的转变产生启动条件)。
961 0