当前位置: 首页 > article >正文

STM32软件模拟I2C的实现方式(一)

文章目录

  • 关键代码:
  • 关键技术点
    • 时钟信号的稳定性和准确性:
    • 数据同步问题:
    • 应答位的处理:
    • 起始和停止条件的精确控制:

关键代码:

//产生IIC起始信号
static void IIC_Start(void)
{
IIC_SDA(1);
IIC_SCL(1);
delay_us(4);
IIC_SDA(0);//START:when CLK is high,DATA change form high to low
delay_us(4);
IIC_SCL(0);//钳住I2C总线,准备发送或接收数据
}
//产生IIC停止信号
static void IIC_Stop(void)
{
// Set_SDA_Output_Mode();//sda线输出
IIC_SCL(0);
IIC_SDA(0);//STOP:when CLK is high DATA change form low to high
delay_us(4);
IIC_SCL(1);
IIC_SDA(1);//发送I2C总线结束信号
delay_us(4);
}
//等待应答信号到来
//返回值:1,接收应答失败
// 0,接收应答成功
static u8 IIC_Wait_Ack(void)
{
u8 ucErrTime=0;
IIC_SDA(1);delay_us(1);
IIC_SCL(1);delay_us(1);
while(IIC_READ_SDA){
ucErrTime++;
if(ucErrTime>250){
IIC_Stop();
return 1;
}
}
IIC_SCL(0);//时钟输出0
return 0;
}
//产生ACK应答
static void IIC_Ack(void)
{
IIC_SCL(0);
IIC_SDA(0);
delay_us(2);
IIC_SCL(1);
delay_us(2);
IIC_SCL(0);
}
//不产生ACK应答
static void IIC_NAck(void)
{
IIC_SCL(0);
// Set_SDA_Output_Mode();
IIC_SDA(1);
delay_us(2);
IIC_SCL(1);
delay_us(2);
IIC_SCL(0);
}
//IIC发送一个字节
//返回从机有无应答
//1,有应答
//0,无应答
static void IIC_Send_Byte(u8 txd)
{
u8 t;
IIC_SCL(0);//拉低时钟开始数据传输
for(t=0;t<8;t++){
if((txd&0x80))
IIC_SDA(1);
else
IIC_SDA(0);
txd<<=1;
delay_us; //对TEA5767这三个延时都是必须的
IIC_SCL(1);
delay_us;
IIC_SCL(0);
}
}
//读1个字节,ack=1时,发送ACK,ack=0,发送nACK
static u8 IIC_Read_Byte(unsigned char ack)
{
unsigned char i,receive=0;
for(i=0;i<8;i++ ){
IIC_SCL(0);
delay_us;
IIC_SCL(1);
receive<<=1;
if(IIC_READ_SDA)receive++;
delay_us(1);
}
if (!ack)
IIC_NAck();//发送nACK
else
IIC_Ack(); //发送ACK
return receive;
}
//reg_addr:开始读数的地址
//返回值 :读到的数据
static u8 IIC_ReadOneByte(uint8_t i2c_addr, uint8_t reg_addr)
{
u8 temp=0;
u8 i2c_address = i2c_addr;
u8 reg_address = reg_addr;
IIC_Start();
IIC_Send_Byte(i2c_address); //发送器件地址,写数据
IIC_Wait_Ack();
IIC_Send_Byte(reg_address); //发送
IIC_Wait_Ack();
IIC_Start();
IIC_Send_Byte(i2c_address|0x01); //进入接收模式
IIC_Wait_Ack();
temp=IIC_Read_Byte(0);
IIC_Stop();//产生一个停止条件
return temp;
}
//reg_addr :写入数据的目的地址
//reg_data:要写入的数据
static void IIC_WriteOneByte(uint8_t i2c_addr, uint8_t reg_addr, uint8_t reg_data)
{
u8 i2c_address = i2c_addr;
u8 reg_address = reg_addr;
IIC_Start();
IIC_Send_Byte(i2c_address); //发送器件地址,写数据
IIC_Wait_Ack();
IIC_Send_Byte(reg_address); //发送低地址
IIC_Wait_Ack();
IIC_Send_Byte(reg_data); //发送字节
IIC_Wait_Ack();
IIC_Stop();//产生一个停止条件
}
static void Dev_i2c_read(uint8_t Addr, uint8_t Reg, uint8_t *pBuffer, uint16_t Length)
{
u8 temp=0;
u8 i=0;
u8 i2c_address = Addr;
u8 reg_address = Reg;
IIC_Start();
IIC_Send_Byte(i2c_address); //发送器件地址,写数据
IIC_Wait_Ack();
IIC_Send_Byte(reg_address); //发送
IIC_Wait_Ack();
IIC_Start();
IIC_Send_Byte(i2c_address|0x01); //进入接收模式
IIC_Wait_Ack();
for(i = 0; i <Length; i++){
*pBuffer=IIC_Read_Byte(0);
pBuffer++;
}
IIC_Stop();//产生一个停止条件
}
static void Dev_i2c_write(uint8_t Addr, uint8_t Reg, uint8_t *pBuffer, uint16_t Length)
{
u8 i2c_address = Addr;
u8 reg_address = Reg;
IIC_Start();
IIC_Send_Byte(i2c_address); //发送器件地址,写数据
IIC_Wait_Ack();
IIC_Send_Byte(reg_address); //发送低地址
IIC_Wait_Ack();
while(Length–){
IIC_Send_Byte(*pBuffer); //发送字节
pBuffer++;
IIC_Wait_Ack();
}
IIC_Stop();//产生一个停止条件
}

关键技术点

时钟信号的稳定性和准确性:

时钟信号的稳定性和准确性对I2C通信的可靠性至关重要。在软件模拟中,需要确保时钟信号的频率和占空比在可接受的范围内。

数据同步问题:

在SCL高电平时,SDA线的状态必须保持稳定以防止数据读取错误。这要求在软件实现中严格控制数据的发送和接收时机。

应答位的处理:

应答位的处理是I2C通信中的一个重要环节。主机需要根据从机的应答情况来决定是否继续发送数据或采取其他措施。

起始和停止条件的精确控制:

起始和停止条件是I2C通信的边界条件,需要精确控制SCL和SDA线的电平变化以确保通信的顺利进行。


http://www.kler.cn/a/369052.html

相关文章:

  • 从 Hadoop 迁移到数据 Lakehouse 的架构师指南
  • python 制作 发货单 (生成 html, pdf)
  • maven之pom.xml文件解读
  • ELK之路第二步——可视化界面Kibana
  • 亿家旺生鲜云订单零售系统的设计与实现小程序ssm+论文源码调试讲解
  • 计算机前沿技术-人工智能算法-大语言模型-最新研究进展-2024-10-24
  • 常用设计模式总结
  • conda虚拟环境中安装cuda方法、遇到的问题
  • 如何用AI绘画插画!价值5万的AI绘画思路分享
  • 《关于神经网络的几个问题》
  • Gazebo学习笔记(2)--传感器和执行器的使用
  • Angular中ChangeDetectorRef.detectChanges是如何实现的,对比vue种的nextTick有何不同
  • 海量数据面试题
  • springmvc-springsecurity-redhat keycloak SAML2 xml实现
  • 【C++】继承与模板
  • WASM 使用说明23事(RUST实现)
  • 【TIMM库】是一个专门为PyTorch用户设计的图像模型库 python库
  • 15分钟学 Go 第 23 天:并发基础:Goroutines
  • 【CSS3】css开篇基础(4)
  • JavaScript 函数与事件处理
  • 灵动AI:艺术与科技的融合
  • 网络搜索引擎Shodan(4)
  • 最优化方法-无约束优化算法(最速下降法)matlab实现
  • opencv学习笔记(3):图像和视频的读取(C++)
  • 【AIGC】ChatGPT提示词Prompt精确控制指南:Scott Guthrie的建议详解与普通用户实践解析
  • 26.Redis主从架构