
刚入手STM32的开发板,最近调试I2C时碰到难点,在读取0-8个字节时正常,在读取大于8个字节的数据时,实际读出的数据是第九个和之后的字节会将前面的数据覆盖,然后补齐0xff,比如"STM32F103CB",直接读取11个字节的结果是字符“03CB2F10”+“0xff,0xff,0xff,0xff”,这是怎么回事? 读取函数是使用的固件库函数 I2C_Result I2C_Comm_MasterReceive(I2C_TypeDef* I2Cx, uint16_t slaveaddr, uint8_t offset, uint8_t* pBuffer, uint32_t length) { /* wait 5us max for bus free time limitation for later transaction */ *(uint32_t *)0xe000e014 = one_us_unit*5; *(uint32_t *)0xe000e018 = 0; *(uint32_t *)0xe000e010 |= 1; while(!I2C_OT); *(uint32_t *)0xe000e010 &= 0xfffffffe; I2C_OT = FALSE; /* wait bus free */ *(uint32_t *)0xe000e014 = BUS_BUSY_TIMEOUT; *(uint32_t *)0xe000e018 = 0; *(uint32_t *)0xe000e010 |= 1; while((I2C_GetFlagStatus(I2Cx, I2C_FLAG_BUSY))&&(!I2C_OT)); *(uint32_t *)0xe000e010 &= 0xfffffffe; if (I2C_OT) { I2C_OT = FALSE; return BUS_BUSY; } /* send start and wait */ I2C_GenerateSTART(I2Cx, ENABLE); *(uint32_t *)0xe000e014 = SEND_START_TIMEOUT; *(uint32_t *)0xe000e018 = 0; *(uint32_t *)0xe000e010 |= 1; while(!(I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_MODE_SELECT) || I2C_OT)); *(uint32_t *)0xe000e010 &= 0xfffffffe; if (I2C_OT) { I2C_OT = FALSE; return SEND_START_ERR; } /* if offset needed: (1) slave address with write direction (2) offset (3) re-start */ if (offset!=0xff) { /* (1) */ I2C_Send7bitAddress(I2Cx, (uint8_t)(slaveaddr & 0xFF), I2C_Direction_Transmitter); *(uint32_t *)0xe000e014 = SEND_ADDR7_TIMEOUT; *(uint32_t *)0xe000e018 = 0; *(uint32_t *)0xe000e010 |= 1; while(!(I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED) || I2C_OT)); *(u32 *)0xe000e010 &= 0xfffffffe; if (I2C_OT) { I2C_OT = FALSE; I2C_GenerateSTOP(I2Cx, ENABLE); while ((I2Cx->CR1 & 0x200) == 0x200); if(I2C_GetFlagStatus(I2Cx, I2C_FLAG_AF)) I2C_ClearFlag(I2Cx, I2C_FLAG_AF); return ADDR_MATCH_ERR; } /* (2) */ I2C_SendData(I2Cx, offset); *(uint32_t *)0xe000e014 = SEND_DATA_TIMEOUT; *(uint32_t *)0xe000e018 = 0; *(uint32_t *)0xe000e010 |= 1; while(!(I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_TRANSMITTED) || I2C_OT)); *(uint32_t *)0xe000e010 &= 0xfffffffe; if (I2C_OT) { I2C_OT = FALSE; I2C_GenerateSTOP(I2Cx, ENABLE); while ((I2Cx->CR1 & 0x200) == 0x200); if(I2C_GetFlagStatus(I2Cx, I2C_FLAG_AF)) I2C_ClearFlag(I2Cx, I2C_FLAG_AF); return DATA_TIMEOUT; } /* (3) */ I2C_GenerateSTART(I2Cx, ENABLE); *(uint32_t *)0xe000e014 = SEND_START_TIMEOUT; *(uint32_t *)0xe000e018 = 0; *(uint32_t *)0xe000e010 |= 1; while(!(I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_MODE_SELECT) || I2C_OT)); *(uint32_t *)0xe000e010 &= 0xfffffffe; if (I2C_OT) { I2C_OT = FALSE; return SEND_START_ERR; } } /* send addr with read direction */ I2C_Send7bitAddress(I2Cx, (uint8_t)(slaveaddr & 0xFF), I2C_Direction_Receiver); /* different implementation of receive data depends on communication length (1) length >=3 (2) length = 2 (3) length = 1 */ if (length >=3) { *(uint32_t *)0xe000e014 = SEND_ADDR7_TIMEOUT; *(uint32_t *)0xe000e018 = 0; *(uint32_t *)0xe000e010 |= 1; while(!(I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED) || I2C_OT)); *(uint32_t *)0xe000e010 &= 0xfffffffe; if (I2C_OT) { I2C_OT = FALSE; I2C_GenerateSTOP(I2Cx, ENABLE); while ((I2Cx->CR1 & 0x200) == 0x200); if(I2C_GetFlagStatus(I2Cx, I2C_FLAG_AF)) I2C_ClearFlag(I2Cx, I2C_FLAG_AF); return ADDR_MATCH_ERR; } /* receive data */ /* use another safe procedure to receive data */ while(length) { if (length !=3) { *(uint32_t *)0xe000e014 = RECEIVE_DATA_TIMEOUT; *(uint32_t *)0xe000e018 = 0; *(uint32_t *)0xe000e010 |= 1; while(((I2C_GetLastEvent(I2Cx)&0x04) != 0x04)&& !I2C_OT); // poll on BTF *(uint32_t *)0xe000e010 &= 0xfffffffe; if (I2C_OT) { I2C_OT = FALSE; I2C_GenerateSTOP(I2Cx, ENABLE); return DATA_TIMEOUT; } *pBuffer++ = I2C_ReceiveData(I2Cx); length--; } if (length == 3) { /* D(n-2) in DR; D(n-1) in shift register */ *(uint32_t *)0xe000e014 = RECEIVE_DATA_TIMEOUT; *(uint32_t *)0xe000e018 = 0; *(uint32_t *)0xe000e010 |= 1; while(((I2C_GetLastEvent(I2Cx)&0x04) != 0x04)&& !I2C_OT); // poll on BTF *(uint32_t *)0xe000e010 &= 0xfffffffe; if (I2C_OT) { I2C_OT = FALSE; I2C_GenerateSTOP(I2Cx, ENABLE); return DATA_TIMEOUT; } /* clear ACK */ I2C_AcknowledgeConfig(I2Cx, DISABLE); __disable_irq(); //NVIC_SETPRIMASK(); /* read D(n-2) */ *pBuffer++ = I2C_ReceiveData(I2Cx); /* program stop */ I2C_GenerateSTOP(I2Cx, ENABLE); /* read D(n-1) */ *pBuffer++ = I2C_ReceiveData(I2Cx); __enable_irq(); //NVIC_RESETPRIMASK(); *(uint32_t *)0xe000e014 = RECEIVE_DATA_TIMEOUT; *(uint32_t *)0xe000e018 = 0; *(uint32_t *)0xe000e010 |= 1; while(((I2C_GetLastEvent(I2Cx)&0x40) != 0x40)&& !I2C_OT); // poll on RxNE *(uint32_t *)0xe000e010 &= 0xfffffffe; if (I2C_OT) { I2C_OT = FALSE; I2C_GenerateSTOP(I2Cx, ENABLE); return DATA_TIMEOUT; } *pBuffer = I2Cx->DR; length = 0; } } *(uint32_t *)0xe000e014 = RECEIVE_DATA_TIMEOUT; *(uint32_t *)0xe000e018 = 0; *(uint32_t *)0xe000e010 |= 1; while (((I2Cx->CR1 & 0x200) == 0x200)&&(!I2C_OT)); *(uint32_t *)0xe000e010 &= 0xfffffffe; if (I2C_OT) { I2C_OT = FALSE; return SEND_STOP_ERR; } I2C_AcknowledgeConfig(I2Cx, ENABLE); } else if (length == 2) { vu32 tmp; /* ACK=1,POS=1 */ I2Cx->CR1 = 0xc01; *(uint32_t *)0xe000e014 = SEND_ADDR7_TIMEOUT; *(uint32_t *)0xe000e018 = 0; *(uint32_t *)0xe000e010 |= 1; while((!I2C_GetFlagStatus(I2Cx,I2C_FLAG_ADDR))&& !I2C_OT); //wait for ADDR event *(uint32_t *)0xe000e010 &= 0xfffffffe; if (I2C_OT) { I2C_OT = FALSE; I2C_GenerateSTOP(I2Cx, ENABLE); return ADDR_MATCH_ERR; } __disable_irq(); //NVIC_SETPRIMASK(); /* clear ADDR */ tmp = I2Cx->SR2; /* disable ACK */ I2C_AcknowledgeConfig(I2Cx, DISABLE); __enable_irq(); //NVIC_RESETPRIMASK(); *(uint32_t *)0xe000e014 = RECEIVE_DATA_TIMEOUT; *(uint32_t *)0xe000e018 = 0; *(uint32_t *)0xe000e010 |= 1; while(((I2C_GetLastEvent(I2Cx)&0x0004) != 0x0004)&& !I2C_OT); // poll on BTF *(uint32_t *)0xe000e010 &= 0xfffffffe; if (I2C_OT) { I2C_OT = FALSE; I2C_GenerateSTOP(I2Cx, ENABLE); return DATA_TIMEOUT; } __disable_irq(); //NVIC_SETPRIMASK(); I2C_GenerateSTOP(I2Cx, ENABLE); *pBuffer++ = I2Cx->DR; *pBuffer = I2Cx->DR; __enable_irq(); //NVIC_RESETPRIMASK(); length = 0; /* POS=0; ACK=PE=1 */ I2Cx->CR1 = 0x0401; } else if (length == 1) { __IO uint32_t tmp; *(uint32_t *)0xe000e014 = SEND_ADDR7_TIMEOUT; *(uint32_t *)0xe000e018 = 0; *(uint32_t *)0xe000e010 |= 1; while((!I2C_GetFlagStatus(I2Cx,I2C_FLAG_ADDR))&& !I2C_OT); //wait for ADDR event *(uint32_t *)0xe000e010 &= 0xfffffffe; if (I2C_OT) { I2C_OT = FALSE; I2C_GenerateSTOP(I2Cx, ENABLE); return ADDR_MATCH_ERR; } /* disable ACK */ I2C_AcknowledgeConfig(I2Cx, DISABLE); __disable_irq(); //NVIC_SETPRIMASK(); /* clear ADDR */ tmp = I2Cx->SR2; I2C_GenerateSTOP(I2Cx, ENABLE); __enable_irq(); //NVIC_RESETPRIMASK(); *(uint32_t *)0xe000e014 = RECEIVE_DATA_TIMEOUT; *(uint32_t *)0xe000e018 = 0; *(uint32_t *)0xe000e010 |= 1; while(((I2C_GetLastEvent(I2Cx)&0x40) != 0x40)&& !I2C_OT); // poll on RxNE *(uint32_t *)0xe000e010 &= 0xfffffffe; if (I2C_OT) { I2C_OT = FALSE; I2C_GenerateSTOP(I2Cx, ENABLE); return DATA_TIMEOUT; } *pBuffer = I2Cx->DR; length = 0; while ((I2Cx->CR1 & 0x200) == 0x200); I2C_AcknowledgeConfig(I2Cx, ENABLE); } return NO_ERR; } |
STM32F105 USB HID RCC設定
STM32F103VCT6单片机的复位引脚和地引脚短路
【官方例程】STM32F107以太网官方例程
【MCU实战经验】基于STM32F103C8T6的hart总线调试器设计
求教STM32F103进入STOP模式后用外部中断唤醒的问题
基于STM32F103RCT6的无源蜂鸣器音乐播放(生日快乐歌)
STM32F103c8t6有没有DAC 功能?
STM32F103x中文数据手册
新手求教,为何在我电脑上找不到STM32F1Xx.h文件
金龙107例程汇总(STM32F107)
RE:STM32F103CB----I2C读取错误
RE:STM32F103CB----I2C读取错误
length你赋值是多少?