wxdjs 发表于 2024-8-21 12:18:20

8H8K64U 的模拟 I2C 一直不成功,硬件 I2C 没问题,请帮忙指导一下

3.3v,上拉4.7k,端口设置为准双向,开漏都试过,通过硬件i2c没问题,读取和写入都可以的,模拟死活不行
8H系列 做主,读取一个温度采样模块,就一个从设备
开机sda和scl都是高,但是我仿真单步也没法设置低,置低后测量电压还是高
用了汇编来模拟i2c,下面也是例程上的汇编程序
现在用硬件的start命令可以进入,但是模拟的start没办法进入
读取程序如下:


                        LCALL   I2C_Start_sim
                        MOV   A,#90H

                        LCALL   I2C_WriteAbyte
                        LCALL   I2C_Check_ACK
                        MOV   A,#00H
                        LCALL   I2C_WriteAbyte
                        LCALL   I2C_Check_ACK
                        LCALL   I2C_Start
                        MOV   A,#91H
                        LCALL   I2C_WriteAbyte
                        LCALL   I2C_Check_ACK
                        LCALL   I2C_ReadAbyte
                        MOV   R1,A
                        LCALL   S_ACK
                        LCALL   I2C_ReadAbyte
                        MOV   R2,A
                        LCALL   S_ACK
                        LCALL   I2C_ReadAbyte
                        MOV   R3,A
                        LCALL   S_ACK
                        LCALL   I2C_Stop_sim



下面是子程序



I2C_Start_sim:
    SETB    SDA
    SETB    SCL
      JNB   SCL,$
    LCALL   I2C_Delay
    CLR   SDA
    LCALL   I2C_Delay      
    CLR   SCL
    LCALL   I2C_Delay      
    RET

I2C_Stop_sim:
    CLR   SDA
    LCALL   I2C_Delay
    SETB    SCL
      JNB   SCL,$
    LCALL   I2C_Delay
    SETB    SDA
    LCALL   I2C_Delay
    RET

S_ACK:
    CLR   SDA
    LCALL   I2C_Delay
    SETB    SCL
    LCALL   I2C_Delay
    CLR   SCL
    LCALL   I2C_Delay
    RET

S_NoACK:
    SETB    SDA
    LCALL   I2C_Delay
    SETB    SCL
    LCALL   I2C_Delay
    CLR   SCL
    LCALL   I2C_Delay
    RET

I2C_Check_ACK:
    SETB    SDA
    LCALL   I2C_Delay
    SETB    SCL
    LCALL   I2C_Delay
      MOV   C, SDA
    CLR   SCL
    LCALL   I2C_Delay
    RET

I2C_WriteAbyte:
    MOV   R7, #08H
TXNEXT:
    RLC   A         
    MOV   SDA, C   
    SETB    SCL      
    LCALL   I2C_Delay
    CLR   SCL      
    LCALL   I2C_Delay
    DJNZ    R7, TXNEXT
    RET

I2C_ReadAbyte:
    MOV   R7, #08H
RXNEXT:
    SETB    SCL      
    LCALL   I2C_Delay
    MOV   C, SDA
    RLC   A
    CLR   SCL      
    LCALL   I2C_Delay
    DJNZ    R7, RXNEXT
    RET

WriteNbyte:
    LCALL   I2C_Start
    MOV   A, #00H
    LCALL   I2C_WriteAbyte
    LCALL   I2C_Check_ACK
    JC      Write_Exit
    CLR   A
    LCALL   I2C_WriteAbyte ;addr
    LCALL   I2C_Check_ACK
    JC      Write_Exit

    MOV   R0,A
Write_Loop:
    MOV   A,@R0
    LCALL   I2C_WriteAbyte
    LCALL   I2C_Check_ACK
    JC      Write_Exit
    INC   R0
    DJNZ    R6, Write_Loop

Write_Exit:
    LCALL   I2C_Stop_sim
    RET



DebugLab 发表于 2024-8-21 12:33:35

用逻辑分析仪看一下

wxdjs 发表于 2024-8-21 12:41:49

DebugLab 发表于 2024-8-21 12:33
用逻辑分析仪看一下

用模拟运行的话分析仪上就是两线都是高,还是处于空闲状态,不管去仿真单步设置低,电压还是不变
用硬件是正常的,分析仪上都是能解析出正确的i2c协议
还有问一下,用硬件i2c的话,怎么去判断一些超时
我要读取的温度模块,厂家建议用模拟i2c来读取,里面加一些超时判断等,例程如下
/**
*\brief I2C 总线忙等待
*
* 等待I2C 总线释放为空闲状态。若SCL 线为高电平,I2C 总线处于空闲状态。
*
*\param timeout : 超时时间, 单位us
*
*\retval 0 : 等待成功
*\retval 1 : 等待超时
*/
static uint8_t __gpio_i2c_busy_wait(const am_i2c_gpio_devinfo_tp_devinfo,uint32_ttimeout)
{
uint32_t wait_time = 0;
while (__GPI2C_SCL_VAL_GET(p_devinfo) == 0) {
/* 等待时间到或者timeout 为0 时,直接退出*/
if (wait_time >= timeout) {
return 1;
} else {
am_udelay(1);
wait_time++;
}
}
return 0;
}
/* 读取单字节数据,指定本次数据读取后是否应答*/
uint8_t am_i2c_gpio_read_byte (am_i2c_gpio_dev_t *p_dev,bool_t   ack)
{
int i;
uint8_t data = 0;
const am_i2c_gpio_devinfo_t *p_devinfo = p_dev->p_devinfo;
__GPI2C_SDA_INPUT(p_devinfo);
/**
* \brief 主机尝试拉高SCL 线。若没有从机占用总线,则SCL 线此时为高电平;
* 若存在从机占用总线,则SCL 线此时为低电平,需要等待从机释放总线才能继续进行通信
*/
__GPI2C_SCL_HIGH(p_devinfo);
/* 等待从机释放总线*/
if (__gpio_i2c_busy_wait(p_devinfo, 200)) {
am_i2c_gpio_stop(p_dev);
return data;
}
__GPI2C_USER_DEALY(p_devinfo);
if (__GPI2C_SDA_VAL_GET(p_devinfo)) {
data |= 1 << 7;
};
__GPI2C_SCL_LOW(p_devinfo);
__GPI2C_USER_DEALY(p_devinfo);
for (i = 6; i >= 0; i--) {
__GPI2C_SCL_HIGH(p_devinfo);
__GPI2C_USER_DEALY(p_devinfo);
if (__GPI2C_SDA_VAL_GET(p_devinfo)) {
data |= 1 << i;
};
__GPI2C_SCL_LOW(p_devinfo);
__GPI2C_USER_DEALY(p_devinfo);
}
am_i2c_gpio_ack_put(p_dev, ack);
return data;
}

DebugLab 发表于 2024-8-21 13:24:46

wxdjs 发表于 2024-8-21 12:41
用模拟运行的话分析仪上就是两线都是高,还是处于空闲状态,不管去仿真单步设置低,电压还是不变
用硬件 ...


我用的硬件I2C,通过ACK/NACK判断是否有测量数据
https://www.stcaimcu.com/forum.php?mod=viewthread&tid=4612

DebugLab 发表于 2024-8-21 13:31:35


你要用的应该是这个(不推荐)

wxdjs 发表于 2024-8-21 14:10:13

DebugLab 发表于 2024-8-21 13:24
我用的硬件I2C,通过ACK/NACK判断是否有测量数据
https://www.stcaimcu.com/forum.php?mod=viewthread&t ...

感谢回复,现在就是模拟i2c一直没法驱动,i2c部分原理图

设置为准双向,开漏,硬件i2c都能正常工作,模拟驱动就不行,把端口速度设置为高速也是不行,
不过设置为硬件i2c时,如果根据手册写操作,读操作连续运行的时候,总是会在读数据时发送地址+读指令后收不到数据,感觉那时进不了中断的现象,好像一直卡在判断while(I2C_Busy);
通过仿真来全速运行,每次都是卡死在读取数据是发送地址+读指令后收不到数据了,此时数据线为高,地址线为低,通过mcu指令来stop i2c也没反应了,只能断电才能恢复空闲状态,不知道是不是温度模块的问题。但是只要不去操作写数据就没这个问题。
i2c速度也尝试过降速。



小坤 发表于 2024-8-21 14:58:14

wxdjs 发表于 2024-8-21 14:10
感谢回复,现在就是模拟i2c一直没法驱动,i2c部分原理图

设置为准双向,开漏,硬件i2c都能正常工作,模 ...

汇编{:5_332:},官方有C 的模拟IIC的代码,用C吧
页: [1]
查看完整版本: 8H8K64U 的模拟 I2C 一直不成功,硬件 I2C 没问题,请帮忙指导一下