STM32为基础的模拟I2C通用8bit和16bit读取以及多字节读取

这篇具有很好参考价值的文章主要介绍了STM32为基础的模拟I2C通用8bit和16bit读取以及多字节读取。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

GPIO模拟I2C驱动的通用代码,I2C的寄存器地址有8位和16位的,主要解决了同一个MCU同时处理8位和16位寄存器地址芯片时候的驱动问题。

typedef enum {
    IIC_8BIT_BASE_ADDR,
    IIC_16BIT_BASE_ADDR
}iic_bits_e;
typedef struct {
    uint8_t DevAddr;
    uint16_t RegAddr;
    uint8_t data_len;
    uint8_t * data_buf;
    uint8_t bit_flag;
    uint16_t delay;
}iic_param_t;

以上是结构体,作为参数,其中DevAddr是芯片地址,RegAddr是寄存器地址,data_len是写入或者读取的数据长度,data_buf是写入或者读出的数据缓冲区,bit_flag是寄存器位数IIC_8BIT_BASE_ADDR是8位,IIC_16BIT_BASE_ADDR是16位。delay是根据需求读写数据时候的延时。根据芯片需求填写,用不到就填0

下面是用法:

写8bit寄存器

void bq27426_write_data(uint16_t reg, uint8_t * buf, uint8_t len)
{
    iic_param_t bq27426 = {
        BQ27426_DEV_ADDR,
        0,
        0,
        NULL,
        IIC_8BIT_BASE_ADDR,
        30
    };
    bq27426.RegAddr = reg;
    bq27426.data_buf = buf;
    bq27426.data_len = len;
    simulate_i2c_writeblock(&bq27426);

}

写16bit寄存器

void cypd3176_write_data(uint16_t reg, uint8_t * buf, uint8_t len)
{
    iic_param_t cypd3176 = {
        CYPD3176_DEV_ADDR,
        0,
        0,
        NULL,
        IIC_16BIT_BASE_ADDR,
        0
    };
    cypd3176.RegAddr = reg;
    cypd3176.data_buf = buf;
    cypd3176.data_len = len;
    simulate_i2c_writeblock(&cypd3176);
}

读8bit寄存器

void bq27426_read_data(uint16_t reg, uint8_t * buf, uint8_t len)
{
    iic_param_t bq27426 = {
        BQ27426_DEV_ADDR,
        0,
        0,
        NULL,
        IIC_8BIT_BASE_ADDR,
        30
    };
    bq27426.RegAddr = reg;
    bq27426.data_buf = buf;
    bq27426.data_len = len;
    simulate_i2c_readblock(&bq27426);

}

读16bit寄存器

void cypd3176_read_data(uint16_t reg, uint8_t * buf, uint8_t len)
{
    iic_param_t cypd3176 = {
        CYPD3176_DEV_ADDR,
        0,
        0,
        NULL,
        IIC_16BIT_BASE_ADDR,
        0
    };
    cypd3176.RegAddr = reg;
    cypd3176.data_buf = buf;
    cypd3176.data_len = len;
    simulate_i2c_readblock(&cypd3176);
}

下面是源码

#include "stdio.h"
#include "simulate.h"

#define PORT_I2C_SCL GPIOB
#define PIN_I2C_SCL GPIO_Pin_6

#define PORT_I2C_SDA GPIOB
#define PIN_I2C_SDA GPIO_Pin_7

#define simulate_IIC_SCL PBout(6) 
#define simulate_IIC_SDA PBout(7) 
#define simulate_READ_SDA PBin(7) 

static void i2c_Delay(void);
static void i2c_PinModeOutput(void);
static void i2c_PinModeInput(void);
static void i2c_SCL(uint8_t stat);
static void i2c_SDA(uint8_t stat);
static uint8_t i2c_ReadSDA(void);
static void i2c_Stop(void);

iic_param_t simulate = {
	simulate_ADDR,
	0,
	0,
	NULL,
	IIC_16BIT_BASE_ADDR,
	0
};


static void i2c_Delay(void)
{
	unsigned char t = 3;
	while (t--)
		;
}

static void i2c_PinModeOutput(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); // ʹ��A�˿�ʱ��
	GPIO_InitStructure.GPIO_Pin = PIN_I2C_SDA;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;  // �������
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; // �ٶ�50MHz
	GPIO_Init(PORT_I2C_SDA, &GPIO_InitStructure);	  // ��ʼ��PA0,1
}

static void i2c_PinModeInput(void)
{

	GPIO_InitTypeDef GPIO_InitStructure;
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); // ʹ��A�˿�ʱ��
	GPIO_InitStructure.GPIO_Pin = PIN_I2C_SDA;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;	  // �������
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; // �ٶ�50MHz
	GPIO_Init(PORT_I2C_SDA, &GPIO_InitStructure);	  // ��ʼ��PA0,1
}

static void i2c_SCL(uint8_t stat)
{
	if (stat)
	{
		simulate_IIC_SCL = 1;
	}
	else
	{
		simulate_IIC_SCL = 0;
	}
}

static void i2c_SDA(uint8_t stat)
{
	if (stat)
	{
		simulate_IIC_SDA = 1;
	}
	else
	{
		simulate_IIC_SDA = 0;
	}
}


static uint8_t i2c_ReadSDA(void)
{
	if (simulate_READ_SDA)
	{
		return 1;
	}
	else
	{
		return 0;
	}
}

void i2c_Start(void)
{
	i2c_PinModeOutput();

	i2c_SDA(1);
	i2c_Delay();
	i2c_SCL(1);
	i2c_Delay();

	i2c_SDA(0);
	i2c_Delay();

	i2c_SCL(0);
	i2c_Delay();
}

void i2c_Stop(void)
{
	i2c_PinModeOutput();

	i2c_SCL(0);
	i2c_SDA(0);
	i2c_Delay();

	i2c_SCL(1);
	i2c_Delay();
	i2c_SDA(1);
	i2c_Delay();
}

void i2c_WriteByte(uint8_t _ucByte)
{
	uint8_t i;

	i2c_PinModeOutput();

	i2c_SCL(0);
	i2c_Delay();

	for (i = 0; i < 8; i++)
	{
		if (_ucByte & 0x80)
		{
			i2c_SDA(1);
		}
		else
		{
			i2c_SDA(0);
		}

		_ucByte = _ucByte << 1;

		i2c_SCL(1);
		i2c_Delay();
		i2c_SCL(0);
		i2c_Delay();
	}

	i2c_SDA(1);
}

uint8_t i2c_ReadByte(void)
{
	uint8_t i;
	uint8_t recv = 0;

	i2c_PinModeOutput();

	i2c_SDA(1);
	i2c_Delay();

	i2c_PinModeInput();

	for (i = 0; i < 8; i++)
	{
		recv = recv << 1;

		i2c_SCL(1);
		i2c_Delay();

		if (i2c_ReadSDA())
		{
			recv |= 0x01;
		}
		else
		{
			recv |= 0x00;
		}

		i2c_SCL(0);
		i2c_Delay();
	}

	return recv;
}

void i2c_Ack(void)
{
	i2c_PinModeOutput();

	i2c_SCL(0);
	i2c_SDA(0);
	i2c_Delay();

	i2c_SCL(1);
	i2c_Delay();

	i2c_SCL(0);
}

void i2c_NAck(void)
{
	i2c_PinModeOutput();

	i2c_SCL(0);
	i2c_SDA(1);
	i2c_Delay();

	i2c_SCL(1);
	i2c_Delay();

	i2c_SCL(0);
}

uint8_t i2c_CheckAck(void)
{
	uint8_t time = 0;

	i2c_PinModeOutput();

	i2c_SDA(1);
	i2c_Delay();
	i2c_SCL(1);
	i2c_Delay();

	i2c_PinModeInput();

	while (i2c_ReadSDA())
	{
		time++;
		if (time >= 100)
		{
			return 1;
		}
	}

	i2c_SCL(0);

	return 0;
}

#define I2C_WR 0x00
#define I2C_RD 0x01
#define ACK 0
#define NOACK 1

void simulate_i2c_init(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); 
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;  
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOB, &GPIO_InitStructure);			  
	GPIO_SetBits(GPIOB, GPIO_Pin_6 | GPIO_Pin_7);
}

uint8_t iic_chip_select(iic_param_t *param, uint8_t rw_flag)
{
	uint16_t i = 0;
	if (param->data_len > 40)
	{
		return 0xf1;
	}
	if (param->data_buf == NULL)
	{
		return 0xF2;
	}
	for (i = 0; i < 3; i++)
	{
		i2c_Start();
		i2c_WriteByte((param->DevAddr << 1) | rw_flag); 
		if (i2c_CheckAck() == ACK)
		{
			break;
		}
	}
	if (i >= 3)
	{
		i2c_Stop();
		return 0xf1;
	}
	return 0;
}

uint8_t simulate_i2c_writeblock(iic_param_t *param)
{
	uint16_t i;
	if (0 != iic_chip_select(param, I2C_WR))
	{
		return 0xF1;
	}

	if (IIC_16BIT_BASE_ADDR == param->bit_flag)
	{
		i2c_WriteByte((param->RegAddr & 0xFF00) >> 8);
		if (i2c_CheckAck() == NOACK)
		{
			i2c_Stop();
			return 0xf7;
		}
	}
	i2c_WriteByte(param->RegAddr & 0x00FF);
	if (i2c_CheckAck() == NOACK)
	{
		i2c_Stop();
		return 0xf3;
	}

	for (i = 0; i < param->data_len; i++)
	{
		i2c_WriteByte(param->data_buf[i]);
		if (i2c_CheckAck() == NOACK)
		{
			i2c_Stop();
			return 0xf4;
		}
	}

	i2c_Stop();
	for (i = 0; i < 100; i++)
	{
		i2c_Delay();
	}
	return 0;
}

uint8_t simulate_i2c_readblock(iic_param_t *param)
{

	uint16_t i;
	int16_t j;

	if (0 != iic_chip_select(param, I2C_WR))
	{
		return 0xF1;
	}

	/* 发送地址 */

	if (IIC_16BIT_BASE_ADDR == param->bit_flag)
	{
		i2c_WriteByte((param->RegAddr & 0xFF00) >> 8);
		if (i2c_CheckAck() == NOACK)
		{
			i2c_Stop();
			return 0xf7;
		}
	}
	i2c_WriteByte(param->RegAddr & 0x00FF);
	if (i2c_CheckAck() == NOACK)
	{
		i2c_Stop();
		return 0xf8;
	}

	if (0 != iic_chip_select(param, I2C_RD))
	{
		return 0xF1;
	}

	for (i = 0; i < param->data_len - 1; i++)
	{
		for (j = 0; j < param->delay; j++)
		{
			i2c_Delay();
		}
		param->data_buf[i] = i2c_ReadByte();

		for (j = 0; j < param->delay; j++)
		{
			i2c_Delay();
		}
		i2c_Ack();
	}
	for (j = 0; j < param->delay; j++)
	{
		i2c_Delay();
	}
	param->data_buf[param->data_len - 1] = i2c_ReadByte();
	i2c_NAck();
	i2c_Stop();
	return 0;
}

#ifndef __IIC_DRIVER_H__
#define __IIC_DRIVER_H__

#include "sys.h"
#include "stdlib.h"	


#define simulate_ADDR  (0x5F)

typedef enum {
    IIC_8BIT_BASE_ADDR,
    IIC_16BIT_BASE_ADDR
}iic_bits_e;
typedef struct {
    uint8_t DevAddr;
    uint16_t RegAddr;
    uint8_t data_len;
    uint8_t * data_buf;
    uint8_t bit_flag;
    uint16_t delay;
}iic_param_t;


void simulate_i2c_init(void);
uint8_t simulate_i2c_readblock(iic_param_t * param);
uint8_t simulate_i2c_writeblock(iic_param_t * param);


#endif 

如果找不到PBout可用下面的头文件,其他平台可以自己实现设置管脚的输入和输出模式替换掉文中的PBout PBin的接口文章来源地址https://www.toymoban.com/news/detail-860574.html


/* Includes ------------------------------------------------------------------*/
#ifndef __SYS_H
#define __SYS_H	
#include "stm32f10x.h"


#define BITBAND(addr, bitnum) ((addr & 0xF0000000)+0x2000000+((addr &0xFFFFF)<<5)+(bitnum<<2)) 
#define MEM_ADDR(addr)  *((volatile unsigned long  *)(addr)) 
#define BIT_ADDR(addr, bitnum)   MEM_ADDR(BITBAND(addr, bitnum))


#define GPIOA_ODR_Addr    (GPIOA_BASE+12) //0x4001080C 
#define GPIOB_ODR_Addr    (GPIOB_BASE+12) //0x40010C0C 
#define GPIOC_ODR_Addr    (GPIOC_BASE+12) //0x4001100C 
#define GPIOD_ODR_Addr    (GPIOD_BASE+12) //0x4001140C 
#define GPIOE_ODR_Addr    (GPIOE_BASE+12) //0x4001180C 
#define GPIOF_ODR_Addr    (GPIOF_BASE+12) //0x40011A0C    
#define GPIOG_ODR_Addr    (GPIOG_BASE+12) //0x40011E0C    

#define GPIOA_IDR_Addr    (GPIOA_BASE+8) //0x40010808 
#define GPIOB_IDR_Addr    (GPIOB_BASE+8) //0x40010C08 
#define GPIOC_IDR_Addr    (GPIOC_BASE+8) //0x40011008 
#define GPIOD_IDR_Addr    (GPIOD_BASE+8) //0x40011408 
#define GPIOE_IDR_Addr    (GPIOE_BASE+8) //0x40011808 
#define GPIOF_IDR_Addr    (GPIOF_BASE+8) //0x40011A08 
#define GPIOG_IDR_Addr    (GPIOG_BASE+8) //0x40011E08 
 

#define PAout(n)   BIT_ADDR(GPIOA_ODR_Addr,n)
#define PAin(n)    BIT_ADDR(GPIOA_IDR_Addr,n)

#define PBout(n)   BIT_ADDR(GPIOB_ODR_Addr,n) 
#define PBin(n)    BIT_ADDR(GPIOB_IDR_Addr,n)

#define PCout(n)   BIT_ADDR(GPIOC_ODR_Addr,n)
#define PCin(n)    BIT_ADDR(GPIOC_IDR_Addr,n)

#define PDout(n)   BIT_ADDR(GPIOD_ODR_Addr,n) 
#define PDin(n)    BIT_ADDR(GPIOD_IDR_Addr,n) 

#define PEout(n)   BIT_ADDR(GPIOE_ODR_Addr,n) 
#define PEin(n)    BIT_ADDR(GPIOE_IDR_Addr,n)

#define PFout(n)   BIT_ADDR(GPIOF_ODR_Addr,n)
#define PFin(n)    BIT_ADDR(GPIOF_IDR_Addr,n) 

#define PGout(n)   BIT_ADDR(GPIOG_ODR_Addr,n)
#define PGin(n)    BIT_ADDR(GPIOG_IDR_Addr,n)  


#endif

到了这里,关于STM32为基础的模拟I2C通用8bit和16bit读取以及多字节读取的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 电脑传输数据STM32模拟I2C显示实时画面到OLED

    写的不好,还望大家指正,有的地方引用了一下大佬的代码。 一、所需硬件: STM32F103C8T6 USB转串口模块 OLED 128*64显示屏 STLINK 二、代码部分 1.stm32串口部分代码 2.stm32OLED屏幕部分代码 3.主程序 4.电脑通过opencv库截取电脑当前1080p一帧画面,并对图片二值化处理,通过电脑端编写

    2024年02月13日
    浏览(37)
  • 【STM32】I2C练习,HAL库读取MPU6050角度陀螺仪

    MPU-6000(6050)为全球首例整合性6轴运动处理组件,相较于多组件方案,免除了组合陀螺仪与加速器时间轴之差的问题,减少了大量的封装空间。当连接到三轴磁强计时,MPU-60X0提供完整的9轴运动融合输出到其主I2C或SPI端口(SPI仅在MPU-6000上可用)。 寄存器地址 寄存器内容 0X3B

    2024年02月16日
    浏览(42)
  • STM32存储左右互搏 I2C总线读写FRAM MB85RC16

    在较低容量存储领域,除了EEPROM的使用,还有铁电存储器FRAM的使用,相对于EEPROM, 同样是非易失性存储单元,FRAM支持更高的访问速度, 其主要优点为没有EEPROM持续写操作跨页地址需要变换的要求,没有写之后的延时等待要求。MB85RC16是2K Byte(16K bit)的FRAM,能够按字节进行写

    2024年02月09日
    浏览(34)
  • STM32模拟I2C获取TCS34725光学颜色传感器数据

    TCS34725是RGB三色颜色传感器,和TCS34727都属于TCS3472系列,在电气特性上略有差别,TCS34727相比TCS34725在I2C总线的访问电平上可以更低,而在I2C软件访问地址方面则一致。 TCS3472内部有4个PD(光电二极管),一个接收clear light(净光,未做任何处理),另外三个分别接收Red, Green,

    2024年02月16日
    浏览(50)
  • STM32模拟I2C协议获取HDC1080温度和湿度传感器数据

    HDC1080是一款温湿度传感器,具有如下特点: 其中温度和湿度经过出厂校准。这里介绍STM32模拟I2C总线协议访问HDC1080的HAL库实现范例。 HDC1080的内部原理及电路连接如下: HDC1080具有低功耗特征,每次触发检测转换后进入睡眠状态,另外内部有一个加热电阻,在环境湿度高时,

    2024年02月11日
    浏览(94)
  • STM32模拟I2C协议获取HMC5883L电子罗盘磁角度数据 (HAL)

    HMC5883L 传感器采用霍尼韦尔各向异性磁阻(AMR)技术,应用于罗盘和三轴磁场角度检测领域,常用于水平物体转动的角度识别。HMC5883L 采用I2C总线接口,2.16~3.6V供电范围,带有校准测试功能。 HMC5883L的硬件连接有5个管脚,除了VCC和GND,以及I2C的SCK和SDA,还有一根INT中断线,用于

    2024年02月13日
    浏览(38)
  • HAL STM32 硬件I2C方式读取AS5600磁编码器获取角度例程

    📍相关篇《STM32 软件I2C方式读取AS5600磁编码器获取角度例程》 ✨stm32使用硬件I2C去读取角度数据,通过STM32CubeMX工具配置工程,读取角度数据,只需要调用一个函数,即可完成数据的读取。了解函数的用法以及从设备地址命令,上手十分快速和简单。 📌AS5600资料: https://p

    2024年04月26日
    浏览(56)
  • MT6701磁编码器使用指南,14Bit单圈绝对值,I2C stm32 HAL库读角度,兼容AS5600

      MT6701是麦歌恩(MagnTek)公司的磁性角度传感器芯片,提供14Bit 0~360°单圈绝对角度检测,拥有 ABZ/PWM/模拟量/I2C/SSI 等多种信息输出方式,还可根据磁场强度的瞬时变化提供非接触式按压检测功能。能够以较低的成本来替代传统光电编码器,可应用于绝对值角度输出、闭环

    2024年02月02日
    浏览(40)
  • 【STM32L496】使用HAL库实现I2C写入/读取数据(M24C32)

    IIC原理超详细讲解—值得一看 【嵌入式硬件芯片开发笔记】EEPROM芯片M24C32配置流程 STM32硬件I2C与软件模拟I2C超详解 实现通信功能的芯片为M24C32,对此,芯片手册上第一页就有对其概括描述。 Automotive 32-Kbit serial I²C bus EEPROM with 1 MHz clock 启动/停止条件 :当串行时钟(SCL)位于

    2024年02月03日
    浏览(57)
  • 基于HAL库的stm32的OLED显示屏显示(模拟I2C,四脚,0.96寸)

    参考视频:江科大oled程序移植stm32hal库,freertos学习,cpu使用率_哔哩哔哩_bilibili ​ STM32入门教程-2023持续更新中_哔哩哔哩_bilibili 高速和低速晶振均选择为陶瓷晶振即可。 不需更改初始化配置,因为模拟I2C初始化时会设置这两个引脚的电平 step1、step2完成后生成工程即可。 代

    2024年02月06日
    浏览(46)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包