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
用逻辑分析仪看一下
用模拟运行的话分析仪上就是两线都是高,还是处于空闲状态,不管去仿真单步设置低,电压还是不变
用硬件是正常的,分析仪上都是能解析出正确的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;
}
wxdjs 发表于 2024-8-21 12:41
用模拟运行的话分析仪上就是两线都是高,还是处于空闲状态,不管去仿真单步设置低,电压还是不变
用硬件 ...
我用的硬件I2C,通过ACK/NACK判断是否有测量数据
https://www.stcaimcu.com/forum.php?mod=viewthread&tid=4612
你要用的应该是这个(不推荐)
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速度也尝试过降速。
wxdjs 发表于 2024-8-21 14:10
感谢回复,现在就是模拟i2c一直没法驱动,i2c部分原理图
设置为准双向,开漏,硬件i2c都能正常工作,模 ...
汇编{:5_332:},官方有C 的模拟IIC的代码,用C吧
页:
[1]