
STM32F103ZET6的开发板,MCU作为主I2C,用I2C硬件轮询的方式读写一个I2C从设备。板子启动后,通过一个按钮开关来打开或关闭I2C写数据和读数据,在开始的第一次写数据时会偶现出现BUSY超时错误,后面持续数百万次的写和读操作结果都是正常的,而且这个错误也不是必现,是随机出现的,大概有50%多的错误概率,完全发现不了规律。从调试跟踪的结果看,都是在主I2C给从I2C发送器件地址后,主I2C没有收到ACK,然后超时。看了网上以前的一些分析,提到的一些可能原因,对比分析了,都对应不上。这个是偶现的错误,而且后面的读写都正常,所以写的从I2C的地址肯定是没有问题的。主I2C读写测试是在MCU上电启动后通过按钮开关控制的,不是一上电就开始读写。IO的初始化顺序也试了,IO的端口速率400K和100K都试了,都不能解决这个问题。 通过在软件中判断写操作的结果,如果发现写错误就重复写几次,也解决不了第一次偶然写失败的问题。 另外用中断的方式读写I2C,也有一样的问题,偶现第一次写失败,中断方式中发现主I2C能收到I2C_IT_AF中断错误。从I2C设备暂时不太好分析,现在还不确定到底是STM32F103的I2C的问题还是从设备的I2C问题。 不知道有没有遇到类似的问题的?能不能解决? 下面是STM32F103的I2C的IO/I2C初始化代码和I2C读写单个字节的代码: void I2C_Config(void) { I2C_InitTypeDef I2C_InitStructure; GPIO_InitTypeDef GPIO_InitStructure; RCC_ClocksTypeDef rcc_clocks; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C2, ENABLE); GPIO_AFIODeInit(); RCC_APB1PeriphResetCmd(RCC_APB1Periph_I2C1|RCC_APB1Periph_I2C2, ENABLE); RCC_APB1PeriphResetCmd(RCC_APB1Periph_I2C1|RCC_APB1Periph_I2C2, DISABLE); GPIO_DeInit(GPIOB); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10 | GPIO_Pin_11; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOB, &GPIO_InitStructure); GPIO_SetBits(GPIOB, GPIO_InitStructure.GPIO_Pin); GPIO_PinLockConfig(GPIOB, GPIO_InitStructure.GPIO_Pin); I2C_DeInit(I2C2); I2C_InitStructure.I2C_Mode = I2C_Mode_I2C; I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2; I2C_InitStructure.I2C_OwnAddress1 = 0x23; //unuseful I2C_InitStructure.I2C_Ack = I2C_Ack_Enable; I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit; I2C_InitStructure.I2C_ClockSpeed = 400000; I2C_Init(I2C2, &I2C_InitStructure); I2C_Cmd(I2C2, ENABLE); I2C_AcknowledgeConfig(I2C2, ENABLE); RCC_GetClocksFreq(&rcc_clocks); g_ulTimeOut = (rcc_clocks.SYSCLK_Frequency /10000); } void I2C_WriteByte(u8 addr, u8 data) { u32 timeout = g_ulTimeOut; while((timeout--)&&(I2C_GetFlagStatus(I2C2, I2C_FLAG_BUSY))); I2C_GenerateSTART(I2C2, ENABLE); timeout = g_ulTimeOut; while((timeout--)&&(SUCCESS!=I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_MODE_SELECT))); I2C_Send7bitAddress(I2C2, IIC_DEVICE_ADDRESS, I2C_Direction_Transmitter); timeout = g_ulTimeOut; while((timeout--)&&(SUCCESS!=I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED))); I2C_SendData(I2C2, addr); timeout = g_ulTimeOut; while((timeout--)&&(SUCCESS!=I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_BYTE_TRANSMITTING))); I2C_SendData(I2C2, data); timeout = g_ulTimeOut; while((timeout--)&&(SUCCESS!=I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_BYTE_TRANSMITTED))); I2C_GenerateSTOP(I2C2, ENABLE); } void I2C_ReadByte(u8 addr, u8 *pdata) { u32 timeout = g_ulTimeOut; while((timeout--)&&I2C_GetFlagStatus(I2C2, I2C_FLAG_BUSY)); I2C_GenerateSTART(I2C2, ENABLE); timeout = g_ulTimeOut; while((timeout--)&&(SUCCESS!=I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_MODE_SELECT))); I2C_Send7bitAddress(I2C2, IIC_DEVICE_ADDRESS, I2C_Direction_Transmitter); timeout = g_ulTimeOut; while((timeout--)&&(SUCCESS!=I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED))); I2C_SendData(I2C2, addr); timeout = g_ulTimeOut; while((timeout--)&&(SUCCESS!=I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_BYTE_TRANSMITTING))); //restart I2C_GenerateSTART(I2C2, ENABLE); timeout = g_ulTimeOut; while((timeout--)&&(SUCCESS!=I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_MODE_SELECT))); // device address, read action I2C_Send7bitAddress(I2C2, IIC_DEVICE_ADDRESS, I2C_Direction_Receiver); timeout = g_ulTimeOut; while((timeout--)&&(SUCCESS!=I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED))); // receive byte I2C_AcknowledgeConfig(I2C2, DISABLE); I2C_GenerateSTOP(I2C2, ENABLE); // read timeout = g_ulTimeOut; while((timeout--)&&(SUCCESS!=I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_BYTE_RECEIVED))); *pdata = I2C_ReceiveData(I2C2); I2C_AcknowledgeConfig(I2C2, ENABLE); } |
串口DMA + 空闲中断收发 ?
STM32L433 单片机在串口配置为IRDA模式后,IRDA是否可以在STOP Mode1下唤醒
两个TIM调用HAL_TIM_PeriodElapsedCallback发生冲突
为何Tim2自动装载定时的首次中断时间总是设定时间的2倍?
STM32H5的I3C模块,target rx和tx时,硬件都存在bug
上电RC,电阻1M 电容0.1uf,导致uart失效
stm32编码器模式计数问题
I3C 可仲裁头的IBI中断
AS608指纹模块的判断中断接收的数组有没有应答包的函数,程序卡死
DMA和GPIO外部中断异常
软件模拟通过延时来确定SCL的频率,不精确,对实时性要求高的需求就不行了。
没抓波形。有上拉电阻,上拉1K,2.2K,5.1K都有。这个问题是随机出现的。我的测试方法是,用STM32F103写好的测试程序,MCU和从I2C上电初始化后,I2C是不能读写的。通过一个按键控制的,当控制按键按下后,MCU的主I2C开始发送写和读操作,读写操作是持续循环的。在第一次的时候发生写操作错误,错误的原因分析出来是发现主I2C没有收到ACK,用中断模式的情况下会伴随发现AF中断错误。第一次错误后,后面的写和读操作都正常了。我改测试程序,如果判断写错误,重新写5次,发现这样重复写5次也是一样错,软件发现写错误时,有发STOP操作。