首页 > 其他分享 >[单片机框架][bsp层][cx32l003][bsp_i2c] I2C/IIC硬件配置和使用

[单片机框架][bsp层][cx32l003][bsp_i2c] I2C/IIC硬件配置和使用

时间:2022-10-31 18:32:38浏览次数:54  
标签:I2C HAL cx32l003 bus bsp uint8 i2c


I2C 简介

I2C 是双线双向的串行总线,它为设备之间数据交换提供了一种简单高效的方法。I2C 标准是一个具有冲突检测机制和仲裁机制的真正意义上的多主机总线。它能防止两个或者多个主机在同时请求控制总线时发生数据冲突。

I2C 总线控制器,能满足 I2C 总线的各种规格并支持所有与 I2C 总线通信的传输模式。

I2C 总线使用连接设备的"SCL"(串行时钟总线)和"SDA"(串行数据总线)来传送信息。数据在主机与从机之间通过 SCL 时钟线控制在 SDA 数据线上实现一个字节一个字节的同步传输, 每个字节为 8位长度,一个 SCL 时钟脉冲传输一个数据位,数据由最高位 MSB 开始传输,每个传输字节后跟随一个应答位, 每个位在 SCL 为高时采样; 因此, SDA 线只有在 SCL 为低时才可以改变, 在 SCL为高时 SDA 保持稳定。 当 SCL 为高时, SDA 线上的跳变视为命令中断(START 或 STOP), I2C 逻辑能自主地处理字节的传输。它能保持跟踪串行传送,而且还有一个状态寄存器(I2C_SR)能反映I2C 总线控制器和 I2C 总线的状态。

I2C 主要特性

I2C 控制器支持以下特性:
⚫ 支持主机发送/接收,从机发送/接收四种工作模式
⚫ 支持标准(100Kbps)/快速(400Kbps)/高速(1Mbps)三种工作速率
⚫ 支持 7 位寻址功能
⚫ 支持噪声过滤功能
⚫ 支持广播地址
⚫ 支持中断状态查询功能

I2C 协议描述

通常标准 I2C 传输协议包含四个部分:

  1. 起始信号或重复起始信号
  2. 从机地址传输和 R/W 位传输
  3. 数据传输
  4. 停止信号
  5. [单片机框架][bsp层][cx32l003][bsp_i2c] I2C/IIC硬件配置和使用_cx32l003


  6. [单片机框架][bsp层][cx32l003][bsp_i2c] I2C/IIC硬件配置和使用_cx32l003_02

/********************************************************************************
* @file bsp_i2c.c
* @author jianqiang.xue
* @version V1.0.0
* @date 2021-04-11
* @brief NULL
********************************************************************************/
/* Includes ------------------------------------------------------------------*/
#include <string.h>
#include <stdlib.h>

#include "RTE_Components.h"
#include CMSIS_device_header
#include "cx32l003_hal.h"

#include "bsp_gpio.h"
#include "bsp_i2c.h"

/* Private Includes ----------------------------------------------------------*/
#include "business_gpio.h"
#include "business_function.h"

/* Private Variables ---------------------------------------------------------*/
#if BS_I2C0_EN
// 定义IIC0信息句柄
static I2C_HandleTypeDef i2c0_handle_t = {
.Instance = I2C,
.Init.master = I2C_MASTER_MODE_ENABLE, // 主机模式使能
.Init.slave = I2C_SLAVE_MODE_DISABLE, // 从机模式禁止
.Mode = HAL_I2C_MODE_MASTER, // 主机模式
.Init.broadack = I2C_BROAD_ACK_DISABLE, // 广播地址应答禁止
.Init.speedclock = BS_I2C0_SPEED_RATE, // I2C传输速率
.State = HAL_I2C_STATE_RESET
};
#endif

/**
* @brief [初始化] IIC初始化
* @note NULL
* @param i2c_bus: IIC组号
* @retval None
*/
void bsp_i2c_init(bsp_i2c_bus_t i2c_bus)
{
#if BS_I2C0_EN
if (i2c_bus == I2C_BUS0)
{
__HAL_RCC_I2C_CLK_ENABLE();
BS_I2C0_SDA_GPIO_CLK_ENABLE();
bsp_gpio_init_i2c(BS_I2C0_SCL_GPIO_PORT, BS_I2C0_SCL_PIN, GPIO_AF4_I2C_SCL);
bsp_gpio_init_i2c(BS_I2C0_SDA_GPIO_PORT, BS_I2C0_SDA_PIN, GPIO_AF4_I2C_SDA);
HAL_I2C_Init(&i2c0_handle_t);
}
#endif
}

/**
* @brief [反初始化] IIC关闭时钟并复位引脚
* @note NULL
* @param i2c_bus: IIC组号
* @retval None
*/
void bsp_i2c_deinit(bsp_i2c_bus_t i2c_bus)
{
#if BS_I2C0_EN
if (i2c_bus == I2C_BUS0)
{
__HAL_RCC_I2C_CLK_DISABLE();
bsp_gpio_deinit(BS_I2C0_SCL_GPIO_PORT, BS_I2C0_SCL_PIN);
bsp_gpio_deinit(BS_I2C0_SDA_GPIO_PORT, BS_I2C0_SDA_PIN);
HAL_I2C_DeInit(&i2c0_handle_t);
}
#endif
}

/**
* @brief i2c读取一个字节
* @note NULL
* @param i2c_bus: IIC组号
* @param dev_addr: 器件地址
* @param reg_addr: 寄存器地址
* @param r_data: 欲发送的数据头指针
* @retval 0--成功 1--失败
*/
uint8_t bsp_i2c_read_byte(bsp_i2c_bus_t i2c_bus, uint8_t dev_addr, uint8_t reg_addr, uint8_t *r_data)
{
if (i2c_bus == I2C_BUS0)
{
#if BS_I2C0_EN
return HAL_I2C_Master_Receive(&i2c0_handle_t, dev_addr, ®_addr, 1, r_data, 1);
#else
return HAL_ERROR;
#endif
}
return HAL_ERROR;
}

/**
* @brief i2c读取多个字节
* @note NULL
* @param i2c_bus: IIC组号
* @param dev_addr: 器件地址
* @param w_data: txbuff头指针 数据格式:(reg_addr, w_data, w_data1, ...)
* @param w_size: txbuff长度
* @param r_data: rxbuff的头指针
* @param r_size: rxbuff的大小
* @retval 0--成功 1--失败
*/
uint8_t bsp_i2c_read_nbyte(bsp_i2c_bus_t i2c_bus, uint8_t dev_addr, uint8_t *w_data, uint16_t w_size, uint8_t *r_data, uint16_t r_size)
{
if (i2c_bus == I2C_BUS0)
{
#if BS_I2C0_EN
return HAL_I2C_Master_Receive(&i2c0_handle_t, dev_addr, w_data, w_size, r_data, r_size);
#else
return HAL_ERROR;
#endif
}
return HAL_ERROR;
}

/**
* @brief i2c写入一个字节
* @note NULL
* @param i2c_bus: IIC组号
* @param dev_addr: 器件地址
* @param reg_addr: 寄存器地址
* @param w_data: 需要写入的字节值
* @retval 0--成功 1--失败
*/
uint8_t bsp_i2c_write_byte(bsp_i2c_bus_t i2c_bus, uint8_t dev_addr, uint8_t reg_addr, uint8_t w_data)
{
uint8_t ret = HAL_OK;

if (i2c_bus == I2C_BUS0)
{
#if BS_I2C0_EN
uint8_t data[2] = {reg_addr, w_data};
ret = HAL_I2C_Master_Transmit(&i2c0_handle_t, dev_addr, data, 2);
#else
ret = HAL_ERROR;
#endif
}
else
{
ret = HAL_ERROR;
}
return ret;
}

/**
* @brief i2c写入多个字节
* @note NULL
* @param i2c_bus: IIC组号
* @param dev_addr: 器件地址
* @param w_data: txbuff头指针 数据格式:(reg_addr, w_data, w_data1, ...)
* @param w_size: txbuff长度
* @retval 0--成功 1--失败
*/
uint8_t bsp_i2c_write_nbyte(bsp_i2c_bus_t i2c_bus, uint8_t dev_addr, uint8_t *w_data, uint16_t w_size)
{
uint8_t ret = HAL_OK;

if (i2c_bus == I2C_BUS0)
{
#if BS_I2C0_EN
ret = HAL_I2C_Master_Transmit(&i2c0_handle_t, dev_addr, w_data, w_size);
#else
ret = HAL_ERROR;
#endif
}
else
{
ret = HAL_ERROR;
}
return ret;
}

// ---------------------散装函数-----------------------------
/**
* @brief i2c写入多个字节且无停止信号(带起始信号和器件地址)
* @note NULL
* @param i2c_bus: IIC组号
* @param dev_addr: 器件地址
* @param w_data: txbuff头指针 数据格式:(reg_addr, w_data, w_data1, ...)
* @param w_size: txbuff长度
* @retval 0--成功 1--失败
*/
uint8_t bsp_i2c_write_nbyte_nostop(bsp_i2c_bus_t i2c_bus, uint8_t dev_addr, uint8_t *w_data, uint16_t w_size)
{
uint8_t ret = HAL_OK;

if (i2c_bus == I2C_BUS0)
{
#if BS_I2C0_EN
ret = HAL_I2C_Master_Transmit_NOStop(&i2c0_handle_t, dev_addr, w_data, w_size);
#else
ret = HAL_ERROR;
#endif
}
else
{
ret = HAL_ERROR;
}
return ret;
}

/**
* @brief i2c写入多个字节且无停止信号(不带起始信号和器件地址)
* @note 必须配合[bsp_i2c_write_nbyte_nostop()]使用
* @param i2c_bus: IIC组号
* @param w_data: txbuff头指针 数据格式:(w_data, w_data1, ...)
* @param w_size: txbuff长度
* @retval 0--成功 1--失败
*/
uint8_t bsp_i2c_send_nbyte(bsp_i2c_bus_t i2c_bus, uint8_t *w_data, uint16_t w_size)
{
uint8_t ret = HAL_OK;
if (i2c_bus == I2C_BUS0)
{
#if BS_I2C0_EN
uint16_t i = 0;
uint32_t i2c_flag = 0XFF;
HAL_I2C_Wait_Flag(&i2c0_handle_t, &i2c_flag);
while (i < w_size)
{
i2c_flag = 0XFF;
HAL_I2C_Send_Byte(&i2c0_handle_t, w_data[i]);
HAL_I2C_Wait_Flag(&i2c0_handle_t, &i2c_flag);
if (i2c_flag != I2C_FLAG_MASTER_TX_DATA_ACK) // 0x00000028U
{
i2c0_handle_t.State = HAL_I2C_STATE_ERROR;
i2c0_handle_t.ErrorCode = i2c0_handle_t.PreviousState;
return HAL_ERROR;
}
i++;
}
#else
ret = HAL_ERROR;
#endif
}
else
{
ret = HAL_ERROR;
}
return ret;
}

/**
* @brief 发送一个停止信号
* @note NULL
* @param i2c_bus: IIC组号
* @param state: false--清除中断标志位 true--不清除中断标记位
* @retval 0--成功 1--失败
*/
uint8_t bsp_i2c_stop(bsp_i2c_bus_t i2c_bus, bool state)
{
uint8_t ret = HAL_OK;

if (i2c_bus == I2C_BUS0)
{
#if BS_I2C0_EN
HAL_I2C_Stop_Config(&i2c0_handle_t, (FunctionalState)true);
#else
ret = HAL_ERROR;
#endif
}
else
{
ret = HAL_ERROR;
}
return ret;
}
/********************************************************************************
* @file bsp_i2c.h
* @author jianqiang.xue
* @version V1.0.0
* @date 2021-04-11
* @brief NULL
********************************************************************************/

#ifndef __BSP_I2C_H
#define __BSP_I2C_H

/* Includes ------------------------------------------------------------------*/
#include <stdint.h>
#include <stdbool.h>

/* Public enum ---------------------------------------------------------------*/
typedef enum
{
I2C_BUS0 = 0,
I2C_BUS1 = 1,
I2C_BUS2 = 2,
} bsp_i2c_bus_t;

/* Public Function Prototypes ------------------------------------------------*/

void bsp_i2c_init(bsp_i2c_bus_t i2c_bus);
void bsp_i2c_deinit(bsp_i2c_bus_t i2c_bus);

// 成品全套逻辑 启动-应答-数据-停止

uint8_t bsp_i2c_read_byte(bsp_i2c_bus_t i2c_bus, uint8_t dev_addr, uint8_t reg_addr, uint8_t *r_data);
uint8_t bsp_i2c_read_nbyte(bsp_i2c_bus_t i2c_bus, uint8_t dev_addr, uint8_t *w_data, uint16_t w_size, uint8_t *r_data, uint16_t r_size);

uint8_t bsp_i2c_write_byte(bsp_i2c_bus_t i2c_bus, uint8_t dev_addr, uint8_t reg_addr, uint8_t w_data);
uint8_t bsp_i2c_write_nbyte(bsp_i2c_bus_t i2c_bus, uint8_t dev_addr, uint8_t *w_data, uint16_t w_size);

// 散装函数

uint8_t bsp_i2c_write_nbyte_nostop(bsp_i2c_bus_t i2c_bus, uint8_t dev_addr, uint8_t *w_data, uint16_t w_size);
uint8_t bsp_i2c_send_nbyte(bsp_i2c_bus_t i2c_bus, uint8_t *w_data, uint16_t w_size);
uint8_t bsp_i2c_stop(bsp_i2c_bus_t i2c_bus, bool state);
#endif


标签:I2C,HAL,cx32l003,bus,bsp,uint8,i2c
From: https://blog.51cto.com/xuejianqiang/5810880

相关文章