我在C中通过mmap实现了GPIO,现在我需要使用GPIO来模拟I2C,但是当我改变一个引脚的输出时,另一个引脚的级别会被拉低。我认为我用和和或操作来改变一个引脚的值不会改变其他引脚的值,我的操作有什么问题?这是我的代码和图片:
void i2cSDA(u8* map_base, bool isHigh)
{
(*(volatile u32*)(map_base + GPIO_BASE_OFFSET + rPE_DAT)) = (isHigh) ?
((PE_DAT & 0XFFFFEFFF) | 0X00001000):
((PE_DAT & 0XFFFFEFFF));
}
void i2cSCL(u8* map_base, bool isHigh)
{
(*(volatile u32*)(map_base + GPIO_BASE_OFFSET + rPE_DAT)) = (isHigh) ?
((PE_DAT & 0XFFFFF7FF) | 0X00000800):
((PE_DAT & 0XFFFFF7FF));
}在主要方面:
int main(int argc, char** argv)
{
static int dev_fd;
unsigned char *map_base;
dev_fd = open("/dev/mem", O_RDWR);
map_base = (unsigned char *)mmap(NULL, MAP_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, dev_fd, GPIO_PAGE_OFFSET);
i2cInit(map_base);
i2cSCL(map_base, 1);
i2cDely();
i2cSDA(map_base, 1);
i2cDely();
i2cSDA(map_base, 0);
i2cDely();
i2cSDA(map_base, 1);
i2cDely();
close(dev_fd);
return 0;
}PE_DAT被定义为u32 PE_DAT = (*(volatile u32*)(map_base+GPIO_BASE_OFFSET+rPE_DAT));
我使用PE12和PE11,数据寄存器是32位,0:12是PE0到PE12的数据,13:32是保留的。

当我试图把黄线拉高时,绿线就会变低。完整代码在这里,主要使用I2C.h和GPIO.h。
发布于 2022-06-27 08:27:26
设置/清除位的功能是错误的:
void i2cSDA(u8* map_base, bool isHigh)
{
(*(volatile u32*)(map_base + GPIO_BASE_OFFSET + rPE_DAT)) = (isHigh) ?
((PE_DAT & 0XFFFFEFFF) | 0X00001000):
((PE_DAT & 0XFFFFEFFF));
}您永远不会更新PE_DAT,这使得它包含旧的无效值。而且你的表达太复杂了。此函数应如下所示:
void i2cSDA(u8* map_base, bool isHigh)
{
if (isHigh != 0)
{
(*(volatile u32*)(map_base + GPIO_BASE_OFFSET + rPE_DAT)) |= 0X00001000;
}
else
{
(*(volatile u32*)(map_base + GPIO_BASE_OFFSET + rPE_DAT)) &= 0XFFFFEFFF;
}
}https://stackoverflow.com/questions/72768048
复制相似问题