【ZYNQ】EMIO 模拟 IIC 驱动示例
创始人
2025-05-29 13:39:05
0

IIC 简介

IIC(Inter-Integrated Circuit) 总线是一种由 PHILIPS 公司开发的两线式串行总线,用于连接
微控制器及其外围设备。它是由数据线 SDA 和时钟 SCL 构成的串行总线,可发送和接收数据。
在 CPU 与被控 IC 之间、IC 与 IC 之间进行双向传送,高速 IIC 总线一般可达 400kbps 以上。

IIC 总线在传送数据过程中共有三种类型信号, 分别是:开始信号、结束信号和应答
信号。

  • 开始信号:SCL 为高电平时,SDA 由高电平向低电平跳变,开始传送数据。
  • 结束信号:SCL 为高电平时,SDA 由低电平向高电平跳变,结束传送数据。
  • 应答信号:接收数据的 IC 在接收到 8bit 数据后,向发送数据的 IC 发出特定的低电平脉冲,
    表示已收到数据。CPU 向受控单元发出一个信号后,等待受控单元发出一个应答信号,CPU 接
    收到应答信号后,根据实际情况作出是否继续传递信号的判断。若未收到应答信号,由判断为
    受控单元出现故障。

这些信号中,起始信号是必需的,结束信号和应答信号,都可以不要。IIC 总线时序图如
图所示:

在这里插入图片描述

为驱动实验室自研基于 DAC60502 的双通道电流输出模块,使用 EMIO 模拟 IIC 实现。

在这里插入图片描述

问:为啥不用硬件 IIC

答:就想用模拟的嘿嘿嘿

用软件模拟 IIC,最大的好处就是方便移植,同一个代码兼容所有 MCU,任何一个微控制器
只要有 IO 口,就可以很快的移植过去,而且不需要特定的 IO 口。

EMIO 模拟 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_RESET      		0
#define GPIO_SET        		1#define GPIO_MODEL_INPUT    	0
#define GPIO_MODEL_OUTPUT  		1#define GPIO_OUTPUT_DISABLE     0
#define GPIO_OUTPUT_ENABLE      1void 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();elseSDA_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();elseIIC_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

相关内容

热门资讯

中证A500ETF摩根(560... 8月22日,截止午间收盘,中证A500ETF摩根(560530)涨1.19%,报1.106元,成交额...
A500ETF易方达(1593... 8月22日,截止午间收盘,A500ETF易方达(159361)涨1.28%,报1.104元,成交额1...
何小鹏斥资约2.5亿港元增持小... 每经记者|孙磊    每经编辑|裴健如 8月21日晚间,小鹏汽车发布公告称,公司联...
中证500ETF基金(1593... 8月22日,截止午间收盘,中证500ETF基金(159337)涨0.94%,报1.509元,成交额2...
中证A500ETF华安(159... 8月22日,截止午间收盘,中证A500ETF华安(159359)涨1.15%,报1.139元,成交额...
科创AIETF(588790)... 8月22日,截止午间收盘,科创AIETF(588790)涨4.83%,报0.760元,成交额6.98...
创业板50ETF嘉实(1593... 8月22日,截止午间收盘,创业板50ETF嘉实(159373)涨2.61%,报1.296元,成交额1...
港股异动丨航空股大幅走低 中国... 港股航空股大幅下跌,其中,中国国航跌近7%表现最弱,中国东方航空跌近5%,中国南方航空跌超3%,美兰...
电网设备ETF(159326)... 8月22日,截止午间收盘,电网设备ETF(159326)跌0.25%,报1.198元,成交额409....
红利ETF国企(530880)... 8月22日,截止午间收盘,红利ETF国企(530880)跌0.67%,报1.034元,成交额29.0...