第20章 通信—硬件 I2C

一、关于I2C

1.1 I2C 控制器

  STM32F103系列的I²C控制器,可作为通信主机或从机,因此有四种工作模式可选择:主机发送模式、主机接收模式、从机发送模式、从机接收模式。
  传输速度上,支持标准模式(Standard mode,最高速度100kHz)快速模式(Fast mode,最高速度400kHz)。同时,还支持SMBus2.0(System Management Bus,系统管理总线)PMBus (Power Management Bus,电源管理总线)
  I²C控制器结构如图 20.1.1 所示,可以看作四部分组成。
  ①引脚:I²C协议只需要两个引脚(SDA和SCL),SMBA引脚仅用于SMBus模式的Alert引脚,通常不用管。
  ②数据收发:主要涉及到数据寄存器(Data Register,DR)数据移位寄存器(Data Shift Register,DSR)
  当发送数据时,将发送的字节写入DR寄存器,硬件会把DR中的字节搬到DSR中,然后在时钟信号的配合下,把DSR最高位的数据放到数据线SDA上,并对DSR进行移位操作。
  当接收数据时,数据控制器(Data Control)根据时钟信号,把SDA线上的高低电平转换为“1”或“0”的数据,写到DSR的最低位,同时DSR移位操作,当接收完一个字节的8位数据后,把DSR中的数据搬到DR寄
存器中。
  ③时钟信号:时钟控制器(Clock Control)用于驱动同步时钟信号线SCL。通过配置时钟控制寄存器(Clock Control Register,CCR),可以调整SCL的频率。
  ④控制逻辑:有两个控制寄存器(Control Register 1,CR1)和(Control Register 2,CR2)用于控制逻辑。通过它们可以触发起始和停止信号,做出ACK响应,配置外设时钟频率,开启DMA和中断的功能。同时控制逻辑的状态会反馈到(Status Register 1,SR1)和(Status Register 2,SR2)两个状态寄存器上,根据它们可以知道当前总线是否被占用,本机是主设备还是从设备,数据是否发送完毕等。
在这里插入图片描述

二、AP3426 介绍

  AP3426芯片集成了光强传感器(ALS:AmbientLight Sensor)、接近传感器(PS: Proximity Sensor)、红 外LED(IR LED),最常见的应用就是手机。当我们接听电话时,耳朵靠近手机前置扬声器附近,也就靠近了该传感器,此时距离传感器就告诉CPU可以关闭屏幕显示,以防误触。光强传感器能识别当前环境光,告诉CPU对应调节屏幕亮度,手机部分传感器如图 20.1.2 所示。
  AP3426的结构如图 20.1.3 所示,左边两个光电二极管采集光照的强度,右边一个发光二极管发射940nm的红外光。
  由图 20.1.4 可知,两个光电二极管的频谱响应,ALS光电二极管对450nm~700nm波长光有响应,PS光电二极管对850nm~1000nm波长的光有响应。
  由图 20.1.5 可知,450nm~700nm波长的光在可见光范围内,而850nm~1000nm波长的光属于红外线。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
  在明亮环境中,环境光直接照射在ALS和PS上,当物体遮住AP3426,光电二极管的光照强度则会降低,即可判断物体接遮住。
  在黑暗环境中,AP3426发出红外线照射在靠近物体上,反射到PS光电二极管上,当物体遮住AP3426, PS光电二极管的光照强度则会降低,即可判断物体遮住。
在这里插入图片描述

三、硬件设计

  如图 20.2.1 为开发AP3426部分的原理图,U5为AP3426芯片。不同于AT24CXX可以电路设置设备地址,AP3426的设备地址是固定的,由芯片手册可以知为0x1E。
   I2C1的SCL使用的PB6引脚,SDA使用的PB7引脚,此外,AP3426的中断引脚连接的PE5。
在这里插入图片描述

四、软件设计

代码部分请参考工程

4.1 软件设计思路

实验目的:本实验通过使用MCU的硬件I2C,获取AP3426的数据。

  1. 初始化I2C协议相关参数:设置速度、寻址长度模式等;
  2. 初始化I2C硬件相关参数:I2C时钟使能、GPIO端口时钟使能、GPIO引脚设置为I2C复用;
  3. 使用HAL提供的I2C对AP3426读写,封装AP3426初始化函数、数据读取函数;
  4. 主函数编写控制逻辑:按下按键KEY1(KEY_U),读取一次AP3426数据,并将数据通过串口打印;

4.2 GPIO选择与接口定义

/************************* I2C 硬件相关定义 *************************/
#define I2Cx                    I2C1
#define I2Cx_CLK_EN()           __HAL_RCC_I2C1_CLK_ENABLE()

#define I2Cx_ClockSpeed         (400000)
#define I2Cx_FORCE_RESET()      __HAL_RCC_I2C1_FORCE_RESET()
#define I2Cx_RELEASE_RESET()    __HAL_RCC_I2C1_RELEASE_RESET()

#define SCL_PIN                 GPIO_PIN_6
#define SCL_PORT                GPIOB
#define SCL_PIN_CLK_EN()        __HAL_RCC_GPIOB_CLK_ENABLE()
    
#define SDA_PIN                 GPIO_PIN_7
#define SDA_PORT                GPIOB
#define SDA_PIN_CLK_EN()        __HAL_RCC_GPIOB_CLK_ENABLE()
/************************* I2C 硬件相关定义结束 *************************/

4.3 初始化I2C(协议部分和硬件部分)

协议部分:

I2C_HandleTypeDef  hi2c; 

/*
 *  函数名:void I2C_Init(void)
 *  输入参数:
 *  输出参数:无
 *  返回值:无
 *  函数作用:初始化I2C速率和地址格式
*/
void I2C_Init(void)
{
    hi2c.Instance             = I2Cx;

    hi2c.Init.ClockSpeed      = I2Cx_ClockSpeed;          // 设置SCL时钟频率(最高400000)
    hi2c.Init.DutyCycle       = I2C_DUTYCYCLE_2;          // 设置I2C的SCL时钟的占空比(都可以)
    hi2c.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;  // 设置广播呼叫模式(关闭) 
    hi2c.Init.NoStretchMode   = I2C_NOSTRETCH_DISABLE;    // 设置禁止时钟延长模式(关闭) 
	hi2c.Init.AddressingMode  = I2C_ADDRESSINGMODE_7BIT;  // 设置I2C寻址长度模式(通常7bit)
	hi2c.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;  // 是否使用两个STM32的设备地址(关闭) 
    hi2c.Init.OwnAddress1     = 0x0A;                     // STM32的设备地址1(支持7bit或10bit)
    hi2c.Init.OwnAddress2     = 0;                        // STM32的设备地址2(只支持7bit)

    if(HAL_I2C_Init(&hi2c) != HAL_OK)
    {
        Error_Handler();
    }
}

设置I2C协议参数;
  设置I2C的传输速率,最高不超过400kHz;
  设置SCL时钟的占空比,即低电平时间比高电平时间,可设置有I2C_DutyCycle_2(2:1)和I2C_DutyCycle_16_9(16:9),一般要求不高,任意即可;
  I2C作为从机模式时,广播呼叫模式设置,通常用不上,关闭即可;
  I2C作为从机模式时,禁止时钟延长,通常用不上,关闭即可;
  设置I2C寻址长度模式,需要根据所接设备的地址长度决定,通常为7bit;
  STM32作为从机模式时,支持同时对两个设备地址作出响应,这里作为主机,关闭即可;
  设置STM32的设备地址1,这里作为主机,只要设备地址不与从机一样即可;
  设置STM32的设备地址2,没用到,不需要设置;
使用“HAL_I2C_Init()”初始化前面的“hi2c”,“HAL_I2C_Init()”会调用“HAL_I2C_MspInit()”进行硬件相关初始化,“HAL_I2C_MspInit()”的内容需要自己编写。

硬件初始化:

/*
 *  函数名:void HAL_I2C_MspInit(I2C_HandleTypeDef *hi2c)
 *  输入参数:hi2c-I2C句柄
 *  输出参数:无
 *  返回值:无
 *  函数作用:使能I2C的时钟,使能引脚时钟,并配置引脚的复用功能
*/
void HAL_I2C_MspInit(I2C_HandleTypeDef *hi2c)
{  
    GPIO_InitTypeDef  GPIO_InitStruct;

    if(hi2c->Instance==I2Cx)
    {
		I2Cx_CLK_EN();   
		SCL_PIN_CLK_EN();
		SDA_PIN_CLK_EN();

		GPIO_InitStruct.Pin       = SCL_PIN;
		GPIO_InitStruct.Mode      = GPIO_MODE_AF_OD;
		GPIO_InitStruct.Pull      = GPIO_NOPULL;
		GPIO_InitStruct.Speed     = GPIO_SPEED_FREQ_HIGH;

		HAL_GPIO_Init(SCL_PORT, &GPIO_InitStruct);

		GPIO_InitStruct.Pin = SDA_PIN;   
		HAL_GPIO_Init(SDA_PORT, &GPIO_InitStruct);

		I2Cx_FORCE_RESET();   // 强制复位
		I2Cx_RELEASE_RESET(); // 释放复位
	}
}

  I2C硬件初始化的内容比较简单,依旧是先使能时钟,然后设置引脚复用,最后还需要复位下I2C。初始化后,便可使用HAL库提供的I2C发送/接收函数,HAL提供三种主机收发函数:

HAL_I2C_Master_Receive()/HAL_I2C_Master_Transmit():I2C收发数据,使用超时管理模式;
HAL_I2C_Master_Receive_IT()/HAL_I2C_Master_Transmit_IT():I2C收发数据,使用中断模式; HAL_I2C_Master_Receive_DMA()/HAL_I2C_Master_Transmit_DMA():I2C收发数据,使用DMA模式;

  这里三种收发函数都可满足需求,这里简单处理,没有使用中断和DMA,因此使用超时管理模式。

4.4 初始化和读写AP3426

  由AP3426数据手册,可知AP3426写时序如图 20.3.1 所示,首先发送设备地址,其次是命令代码(寄存器地址),最后是数据内容。
在这里插入图片描述

4.4.1 写AP3426

/*
 *  函数名:void AP3426_WriteOneByte(uint8_t reg, uint8_t data)
 *  输入参数:reg待写AP3426寄存器地址 data待写数据
 *  输出参数:无
 *  返回值:无
 *  函数作用:写AP3426一字节数据
*/
void AP3426_WriteOneByte(uint8_t reg, uint8_t data)
{
	uint16_t write_data = reg | (data<<8);  //考虑大小端问题

	if(HAL_I2C_Master_Transmit(&hi2c, (AP3426_ADDR << 1) | AP3426_W , (uint8_t*)&write_data, 2, 300) != HAL_OK)
	{
		Error_Handler();
	}
	while (HAL_I2C_GetState(&hi2c) != HAL_I2C_STATE_READY);
}

4.4.2 读AP3426

  由AP3426数据手册,可知AP3426读时序如图 20.3.1 所示,首先发送设备地址,其次是命令代码(寄存器地址),然后重新启动,发送设备地址,最后读取数据内容。根据时序,编写代码如图 20.3.2 所示。
在这里插入图片描述

/*
 *  函数名:uint8_t AP3426_ReadOneByte(uint8_t reg)
 *  输入参数:reg待读AP3426寄存器地址  
 *  输出参数:无
 *  返回值:读取的AP3426数据
 *  函数作用:读AP3426一字节数据
*/
uint8_t AP3426_ReadOneByte(uint8_t reg)
{
	uint8_t read_data = 0;

	if(HAL_I2C_Master_Transmit(&hi2c, (AP3426_ADDR << 1) | AP3426_W , (uint8_t*)&reg, 1, 300) != HAL_OK)
	{
		Error_Handler();
	}
	while (HAL_I2C_GetState(&hi2c) != HAL_I2C_STATE_READY);

	if(HAL_I2C_Master_Receive(&hi2c, (AP3426_ADDR << 1) | AP3426_R , (uint8_t*)&read_data, 1, 300) != HAL_OK)
	{
		Error_Handler();
	}

    return read_data;
}

4.5 AP3426的初始化

  AP3426的初始化比较简单,流程如下:
  ① 复位:设置System Control寄存器(地址:0x00)为“SW reset”(值:0x04);
  ② 设置工作模式:设置System Control寄存器(地址:0x00)为“ALS and PS+IR functions active”(值:0x03),即IR+PS+ALS三个都激活使用;
  ③ 设置中断(这里没使用中断);
在这里插入图片描述

五、代码工程和文档

工程链接:硬件IIC
文档链接: AP3426 Datasheet Rev3.0

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值