软件i2c读多字节只能读出第一个字节
1. 我用的是cypress芯片,用IO模拟软件i2c,读取单个字节没有问题,读取多个字节时,只有第一个字节是对的,后面的字节都是02. 波形图中左边是电脑端读i2c的波形,是没有问题的,排除硬件问题
3. 波形图中右边是单片机io模拟读i2c的波形,第一个字节对,第二个字节是0,看波形图,ACK(0)之前SDA被拉高(红色箭头处),可能slave误以为发了ACK(1)所以结束了
4. 请问那个SDA被拉高是什么原因?
多半是应答错了 ayb_ice 发表于 2020-6-10 16:32
多半是应答错了
能不能具体说一下,看波形,我的应答ack(0)在那个高电平产生之后发送的,但那个高电平不是我的代码操作的 qinchxiong 发表于 2020-6-10 16:43
能不能具体说一下,看波形,我的应答ack(0)在那个高电平产生之后发送的,但那个高电平不是我的代码操作的 ...
你应答时,要先切换GPIO模式 ayb_ice 发表于 2020-6-10 16:46
你应答时,要先切换GPIO模式
我了解你的意思,切换SDA为输出模式,这个我想到过,cypress平台配置sda为bidirectional,双向模式,用psoc生成的代码,但没看到它的代码里设置模式的接口,所以我推测调用pin write和pin read的时候它自动切换的 本帖最后由 ayb_ice 于 2020-6-11 08:39 编辑
qinchxiong 发表于 2020-6-10 16:57
我了解你的意思,切换SDA为输出模式,这个我想到过,cypress平台配置sda为bidirectional,双向模式,用ps ...
自己测试下GPIO,这种情况下直接输出0,或1,正确吗 每个receive byte都都必须ack(0),除了最后一个字节。
你只有N个字节后ack了一下。
你应该知道I2C的一个byte frame是9个bit,前8个是一方发送,第9个是另外一方发送的。
William1994 发表于 2020-6-11 08:48
每个receive byte都都必须ack(0),除了最后一个字节。
你只有N个字节后ack了一下。
你应该知道I2C的一个byt ...
整理代码图片前不小心把ack(0)删掉了,原本代码是:
......
......
......
for (i = 0; i < len - 1; i++)
{
*buffer = recv_byte();
ack_i2c(0);
buffer++;
}
*buffer = recv_byte();
ack_i2c(1);
stop_i2c(); ayb_ice 发表于 2020-6-11 08:24
自己测试下GPIO,这种情况下直接输出0,或1,正确吗
我测试了一下,这种情况下输出0,1正常,另外我的接收代码是(昨天整理代码图片时删了一句ack_i2c(0)):
for (i = 0; i < len - 1; i++)
{
*buffer = recv_byte();
ack_i2c(0);
buffer++;
}
*buffer = recv_byte();
ack_i2c(1);
stop_i2c();
根本问题还是:那个红色箭头处的SDA拉高不知道是哪里给出的,不是我的代码发出的 qinchxiong 发表于 2020-6-11 09:36
我测试了一下,这种情况下输出0,1正常,另外我的接收代码是(昨天整理代码图片时删了一句ack_i2c(0)):
fo ...
是不是其它地方也在控制,时序没有问题,方便的话发下完整的代码 qinchxiong 发表于 2020-6-11 09:36
我测试了一下,这种情况下输出0,1正常,另外我的接收代码是(昨天整理代码图片时删了一句ack_i2c(0)):
fo ...
那个高其实是没问题的,因为SCL低时,SDA可以 变化,只要在SCL上升沿前电平是对的就可以 了 ayb_ice 发表于 2020-6-11 09:36
是不是其它地方也在控制,时序没有问题,方便的话发下完整的代码
附件是操作代码,你说的在非clk周期内sda是高电平没有影响,我也是这么想的,但我看电脑操作的波形是没有的,读取也没有问题。 qinchxiong 发表于 2020-6-11 10:07
附件是操作代码,你说的在非clk周期内sda是高电平没有影响,我也是这么想的,但我看电脑操作的波形是没有 ...
read_ack只能发送一次时钟,不可以发送多次,
其它的地方暂时没看 ayb_ice 发表于 2020-6-11 10:40
read_ack只能发送一次时钟,不可以发送多次,
其它的地方暂时没看
static uint8_t wait_read_ack(void)
{
uint8_t ack = 1;
int32_t i;
uint8_t max_count = 10;
SDA_H;
SCL_H;
for(i = 0; i < max_count; i++)
{
ack = I2C_SDA_READ;
if(ack == 0)
break;
if(i == max_count - 1)
return 1;
}
SCL_L;
return 0;
}
我确认了一下,跟read_ack里的多次发送时钟无关,我改成上面的代码,仍然只能读一个字节,波形是一样的 qinchxiong 发表于 2020-6-11 11:48
static uint8_t wait_read_ack(void)
{
uint8_t ack = 1;
这是协议的问题,你连协议都没搞清楚,
读应答之前要将GPIO设为输入状态,没看到哪里有切换,
就是标准的51也要置个1才能读, qinchxiong 发表于 2020-6-11 11:48
static uint8_t wait_read_ack(void)
{
uint8_t ack = 1;
你这个代码有延时吗,这样肯定不行 ayb_ice 发表于 2020-6-11 12:57
这是协议的问题,你连协议都没搞清楚,
读应答之前要将GPIO设为输入状态,没看到哪里有切换,
我知道你的意思,我最开始的时候想到过这个问题,用cypress的 pSoC4配置和生成的代码,没看到IO方向切换接口,我推测配置为bidretcional和open drive + low模式生成的代码,SDA pin write和read时我不确定是不是自动切换io方向,因为read单个字节,是没有问题的。 ayb_ice 发表于 2020-6-11 13:09
你这个代码有延时吗,这样肯定不行
试过了,这里的延时没有影响 qinchxiong 发表于 2020-6-11 13:51
我知道你的意思,我最开始的时候想到过这个问题,用cypress的 pSoC4配置和生成的代码,没看到IO方向切换 ...
可以忽略这个应答的结果,直接往下读试试 qinchxiong 发表于 2020-6-11 13:51
我知道你的意思,我最开始的时候想到过这个问题,用cypress的 pSoC4配置和生成的代码,没看到IO方向切换 ...
你这就是类似51的准双向口,读GPIO之前先输出1
页:
[1]
2