STM32F4的I2C读取BMP085模块的温度和气压

这个i2c搞了好几天,网上很多人都讲这是ST封装库的问题,而且基本上讲的都是STM32F1系列的片子,甚至给出了一些他们自己研究的成果,至于F4,这方面的说法不多。

没办法,从头来吧。

研究了下BMP085的datasheet,就是要用I2C读写寄存器,地址为0xee(写),从而计算温度和气压。

创建了一个项目文件,把I2C的库文件放进去,写main函数

首先配置uart1和I2c: USART_Configuration();//这个函数就不说了,问题不大

I2C_Configuration();

主要说下这个函数的内容,源码:

#define I2C_BMP085 I2C1

void I2C_Configuration(void){I2C_InitTypeDef I2C_InitStructure;GPIO_InitTypeDef GPIO_InitStructure;RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB,ENABLE);RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1,ENABLE);GPIO_PinAFConfig(GPIOB, GPIO_PinSource6, GPIO_AF_I2C1);GPIO_PinAFConfig(GPIOB, GPIO_PinSource7, GPIO_AF_I2C1);GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; GPIO_InitStructure.GPIO_OType = GPIO_OType_OD; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;GPIO_Init(GPIOB, &GPIO_InitStructure);I2C_DeInit(I2C_BMP085);I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;I2C_InitStructure.I2C_OwnAddress1 = 0xEE; //BMP085地址I2C_InitStructure.I2C_Ack = I2C_Ack_Enable; //ack enableI2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;I2C_InitStructure.I2C_ClockSpeed = 100000; //100kI2C_Cmd(I2C_BMP085, ENABLE);I2C_Init(I2C_BMP085, &I2C_InitStructure);//I2C_AcknowledgeConfig(I2C_BMP085, ENABLE);}

开始在这个函数里面犯了个低级的错误,误将RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1,ENABLE)写为RCC_AHB1PeriphClockCmd(RCC_APB1Periph_I2C1,ENABLE),这是在复制过程中容易出现的问题。

结果会导致的问题就是程序一直停在while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT));,这句话会出现在后面的I2C读函数I2C_Read中。

这个比较好理解,因为时钟没开,所以F4的I2C的寄存器都没有写进去,,I2C还没有开始工作。

I2C_Read()函数的源码:

char value[2];uint8_t I2C_Read(uint8_t addr){ while(I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY));I2C_AcknowledgeConfig(I2C1, ENABLE); I2C_GenerateSTART(I2C1, ENABLE); while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT)); I2C_Send7bitAddress(I2C1, 0xee, I2C_Direction_Transmitter); while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));I2C_SendData(I2C1, addr); while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));I2C_GenerateSTART(I2C1, ENABLE);while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT));I2C_Send7bitAddress(I2C1, 0xee, I2C_Direction_Receiver);while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED)); while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_RECEIVED)); /* EV7 */ value[0] = I2C_ReceiveData(I2C1); I2C_AcknowledgeConfig(I2C1, DISABLE); I2C_GenerateSTOP(I2C1, ENABLE); while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_RECEIVED)); /* EV7 */ value[1] = I2C_ReceiveData(I2C1); //cal_data = value[0]<<8 | value[1];//printf("buf[0] = %x,buf[1] = %x,%d,%d\r\n",buf[0],buf[1],(buf[0]<<8|buf[2]),cal_data); /* Decrement the read bytes counter */I2C_AcknowledgeConfig(I2C1, ENABLE);return 0;}

在这个函数中也遇到了问题,又是因为复制代码,没有看清楚,误将while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED))写为while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)),导致的问题就是程序一直停在while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)),为什么在这里死循环我还没搞明白。

如果没有出现上述的错误,这时候就可以在main函数里面添加函数read_calibration_data()去读BMP085内部E2PROM的校准数据了

下面整理出最终的代码

uint8_t I2C_Read(I2C_TypeDef *I2Cx,uint8_t I2C_Addr,uint8_t addr,uint8_t *buf,uint16_t num){ if(num==0)return 1; while(I2C_GetFlagStatus(I2Cx, I2C_FLAG_BUSY));I2C_AcknowledgeConfig(I2Cx, ENABLE); I2C_GenerateSTART(I2Cx, ENABLE); while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_MODE_SELECT)); I2C_Send7bitAddress(I2Cx, I2C_Addr, I2C_Direction_Transmitter); while (!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));I2C_SendData(I2Cx, addr); while (!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_TRANSMITTED));I2C_GenerateSTART(I2Cx, ENABLE);while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_MODE_SELECT));I2C_Send7bitAddress(I2Cx, I2C_Addr, I2C_Direction_Receiver);while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED)); while (num) {if(num==1){ I2C_AcknowledgeConfig(I2Cx, DISABLE); I2C_GenerateSTOP(I2Cx, ENABLE);} while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_RECEIVED)); /* EV7 */ *buf = I2C_ReceiveData(I2Cx); buf++; /* Decrement the read bytes counter */ num–; } I2C_AcknowledgeConfig(I2Cx, ENABLE);return 0;}uint8_t I2C_Write(I2C_TypeDef *I2Cx,uint8_t I2C_Addr,uint8_t addr,uint8_t value){while(I2C_GetFlagStatus(I2Cx, I2C_FLAG_BUSY)) I2C_GenerateSTART(I2Cx, ENABLE);while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_MODE_SELECT)); I2C_Send7bitAddress(I2Cx, I2C_Addr, I2C_Direction_Transmitter); while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)); I2C_SendData(I2Cx, addr); while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_TRANSMITTED)); I2C_SendData(I2Cx, value); while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_TRANSMITTED)); I2C_GenerateSTOP(I2Cx, ENABLE); I2C_AcknowledgeConfig(I2Cx, DISABLE);//I2C_delay(200000);//4.5msreturn 0;}

大多数人想要改造这个世界,但却罕有人想改造自己。

STM32F4的I2C读取BMP085模块的温度和气压

相关文章:

你感兴趣的文章:

标签云: