stm32f4硬件IIC读取MPU6050数据
stm32f4硬件IIC读取MPU6050数据
** JY901B 串⼝10轴加速度计 MK695**
stm32f4“硬件协议”⽅式,STM32 的I2C ⽚上外设专门负责实现I2C 通讯协议,只要置好该外设,它就会⾃动
根据协议要求产⽣通讯信号,收发数据并缓存起来,CPU 只要检测该外设的状态和访问数据寄存器,就能完
成数据收发。这种由硬件外设处理I2C 协议的⽅式减轻了CPU 的⼯作,且使软件设计更加简单。不需要关⼼
底层的设计。
1. I2C 通讯协议
I2C 通讯协议(Inter - Integrated Circuit) 是由Phiilps 公司开发的,由于它引脚少,硬件实现简单,可扩
展性强,不需要USART、CAN 等通讯协议的外部收发设备,现在被⼴泛地使⽤在系统内多个集成电路(IC) 间的通讯。
通讯的起始和停⽌信号
数据有效性
地址及数据⽅向
响应
2. 设备
**3. STM32的硬件IIC
由stm32f4xx的中⽂参考⼿册可得,f4在f1的基础上对iic的性能进⾏了加强,稳定性⽅⾯得到了很⼤的增强。“硬件协议”⽅式,STM32 的I2C ⽚上外设专门负责实现I2C 通讯协议,只要配
置好该外设,它就会⾃动根据协议要求产⽣通讯信号,收发数据并缓存起来,CPU 只要检测该
外设的状态和访问数据寄存器,就能完成数据收发。这种由硬件外设处理I2C 协议的⽅式减轻了
CPU 的⼯作,且使软件设计更加简单。不需要关⼼底层的库设计。
4.*** 程序设计****(最最⼲货)
STM32 标准库提供了I2C 初始化结构体及初始化函数来配置I2C 外设。初始
化结构体及函数定义在库⽂件“stm32f4xx_i2c.h”及“stm32f4xx_i2c.c”中,编程时我们可以结合
这两个⽂件内的注释使⽤或参考库帮助⽂档。了解初始化结构体后我们就能对I2C 外设运⽤⾃
如了。
4.1. ⾸先要对IIC总线的IO⼝和iic的结构体进⾏初始化
/**
* @brief 初始化I2C总线,使⽤I2C前需要调⽤
* @param ⽆
* @retval ⽆
*/
void I2cMaster_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
I2C_InitTypeDef I2C_InitStructure;
/* Enable I2Cx clock */
RCC_APB1PeriphClockCmd(SENSORS_I2C_RCC_CLK, ENABLE);
/* Enable I2C GPIO clock */
RCC_AHB1PeriphClockCmd(SENSORS_I2C_SCL_GPIO_CLK | SENSORS_I2C_SDA_GPIO_CLK, ENABLE);
/* Configure I2Cx pin: SCL ----------------------------------------*/
GPIO_InitStructure.GPIO_Pin = SENSORS_I2C_SCL_GPIO_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_InitStructure.GPIO_OType = GPIO_OType_OD;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
/* Connect pins to Periph */
GPIO_PinAFConfig(SENSORS_I2C_SCL_GPIO_PORT, SENSORS_I2C_SCL_GPIO_PINSOURCE, SENSORS_I2C_AF);
GPIO_Init(SENSORS_I2C_SCL_GPIO_PORT,&GPIO_InitStructure);
/* Configure I2Cx pin: SDA ----------------------------------------*/
GPIO_InitStructure.GPIO_Pin = SENSORS_I2C_SDA_GPIO_PIN;
/* Connect pins to Periph */
GPIO_PinAFConfig(SENSORS_I2C_SDA_GPIO_PORT, SENSORS_I2C_SDA_GPIO_PINSOURCE, SENSORS_I2C_AF);
GPIO_Init(SENSORS_I2C_SDA_GPIO_PORT,&GPIO_InitStructure);
I2C_DeInit(SENSORS_I2C);
I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;
I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;
I2C_InitStructure.I2C_OwnAddress1 = I2C_OWN_ADDRESS;
I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;
I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
I2C_InitStructure.I2C_ClockSpeed = I2C_SPEED;
/* Enable the I2C peripheral */
I2C_Cmd(SENSORS_I2C, ENABLE);
/* Initialize the I2C peripheral */
I2C_Init(SENSORS_I2C,&I2C_InitStructure);
return;
}
这些结构体成员说明如下,其中括号内的⽂字是对应参数在STM32 标准库中定义的宏:
(1) I2C_ClockSpeed
本成员设置的是I2C 的传输速率,在调⽤初始化函数时,函数会根据我们输⼊的数值经过
运算后把时钟因⼦写⼊到I2C 的时钟控制寄存器CCR。⽽我们写⼊的这个参数值不得⾼于400KHz。由于CCR 寄存器不能写⼊⼩数类型的时钟因⼦,固件库计算CCR 值时会向下取
整,影响到SCL 的实际频率可能会低于本成员设置的参数值,这时除了通讯稍慢⼀点以外,
不会对I2C 的标准通讯造成其它影响。
(2) I2C_Mode
本成员是选择I2C 的使⽤⽅式,有I2C 模式(I2C_Mode_I2C) 和SMBus 主、从模式
(I2C_Mode_SMBusHost、I2C_Mode_SMBusDevice ) 。I2C 不需要在此处区分主从模式,直接设置I2C_Mode_I2C 即可。
(3) I2C_DutyCycle
本成员设置的是I2C 的SCL 线时钟的占空⽐。该配置有两个选择,分别为低电平时间⽐⾼
电平时间为2:1 ( I2C_DutyCycle_2) 和16:9 (I2C_DutyCycle_16_9)。其实这两个模式的⽐例差别并不⼤,⼀般要求都不会如此严格,这⾥随便选就可以了。
(4) I2C_OwnAddress1
本成员配置的是STM32 的I2C 设备⾃⼰的地址,每个连接到I2C 总线上的设备
都要有⼀个⾃⼰的地址,作为主机也不例外。地址可设置为7 位或10 位(受下⾯
I2C_AcknowledgeAddress 成员决定),只要该地址是I2C 总线上唯⼀的即可。
STM32 的I2C 外设可同时使⽤两个地址,即同时对两个地址作出响应,这个结构成员
I2C_OwnAddress1 配置的是默认的、OAR1 寄存器存储的地址,若需要设置第⼆个地址寄存
器OAR2,可使⽤I2C_OwnAddress2Config 函数来配置,OAR2 不⽀持10 位地址。
(5) I2C_Ack_Enable
本成员是关于I2C 应答设置,设置为使能则可以发送响应信号。该成员值⼀般配置为允
许应答(I2C_Ack_Enable),这是绝⼤多数遵循I2C 标准的设备的通讯要求,改为禁⽌应答
(I2C_Ack_Disable) 往往会导致通讯错误。
(6) I2C_AcknowledgeAddress
本成员选择I2C 的寻址模式是7 位还是10 位地址。这需要根据实际连接到I2C 总线上设备
的地址进⾏选择,这个成员的配置也影响到I2C_OwnAddress1 成员,只有这⾥设置成10 位
模式时,I2C_OwnAddress1 才⽀持10 位地址。
配置完这些结构体成员值,调⽤库函数I2C_Init 即可把结构体的配置写⼊到寄存器中。
4.2 写⼀个字节
/
**
* @brief 写⼀个字节到I2C EE中
* @param @param slave_addr, 外设地址
* @arg pBuffer:缓冲区指针
* @arg WriteAddr:写地址
* @retval ⽆
configuredclockspeed是什么意思*/
u8 I2C_ByteWrite(u8 slave_addr,u8* pBuffer, u8 WriteAddr)
{
u16 I2CTimeout;
/* Send STRAT condition */
I2C_GenerateSTART(SENSORS_I2C, ENABLE);
I2CTimeout =((uint32_t)0x1000);
/* Test on EV5 and clear it */
while(!I2C_CheckEvent(SENSORS_I2C, I2C_EVENT_MASTER_MODE_SELECT))
{
if((I2CTimeout--)==0)printf("I2C 等待超时!errorCode = 0 \r\n");
}
/* Send EE address for write */
I2C_Send7bitAddress(SENSORS_I2C, slave_addr, I2C_Direction_Transmitter);
I2CTimeout =((uint32_t)0x1000);
/* Test on EV6 and clear it */
while(!I2C_CheckEvent(SENSORS_I2C, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)) {
if((I2CTimeout--)==0)printf("I2C 等待超时!errorCode = 1 \r\n");
}
/* Send the EE's internal address to write to */
I2C_SendData(SENSORS_I2C, WriteAddr);
I2CTimeout =((uint32_t)0x1000);
/* Test on EV8 and clear it */
while(!I2C_CheckEvent(SENSORS_I2C, I2C_EVENT_MASTER_BYTE_TRANSMITTED))
{
if((I2CTimeout--)==0)printf("I2C 等待超时!errorCode = 2 \r\n");
}
/* Send the byte to be written */
I2C_SendData(SENSORS_I2C,*pBuffer);
I2CTimeout =((uint32_t)0x1000);
/* Test on EV8 and clear it */
while(!I2C_CheckEvent(SENSORS_I2C, I2C_EVENT_MASTER_BYTE_TRANSMITTED))
{
if((I2CTimeout--)==0)printf("I2C 等待超时!errorCode = 3 \r\n");
}
/* Send STOP condition */
I2C_GenerateSTOP(SENSORS_I2C, ENABLE);
return1;
}
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论