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

2023-12-20 04:30

本文主要是介绍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; // �ٶ�50MHzGPIO_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; // �ٶ�50MHzGPIO_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 1void 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的接口


/* 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读取以及多字节读取的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/514759

相关文章

mysql的基础语句和外键查询及其语句详解(推荐)

《mysql的基础语句和外键查询及其语句详解(推荐)》:本文主要介绍mysql的基础语句和外键查询及其语句详解(推荐),本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋... 目录一、mysql 基础语句1. 数据库操作 创建数据库2. 表操作 创建表3. CRUD 操作二、外键

Python基础语法中defaultdict的使用小结

《Python基础语法中defaultdict的使用小结》Python的defaultdict是collections模块中提供的一种特殊的字典类型,它与普通的字典(dict)有着相似的功能,本文主要... 目录示例1示例2python的defaultdict是collections模块中提供的一种特殊的字

Python基础文件操作方法超详细讲解(详解版)

《Python基础文件操作方法超详细讲解(详解版)》文件就是操作系统为用户或应用程序提供的一个读写硬盘的虚拟单位,文件的核心操作就是读和写,:本文主要介绍Python基础文件操作方法超详细讲解的相... 目录一、文件操作1. 文件打开与关闭1.1 打开文件1.2 关闭文件2. 访问模式及说明二、文件读写1.

使用Java实现通用树形结构构建工具类

《使用Java实现通用树形结构构建工具类》这篇文章主要为大家详细介绍了如何使用Java实现通用树形结构构建工具类,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录完整代码一、设计思想与核心功能二、核心实现原理1. 数据结构准备阶段2. 循环依赖检测算法3. 树形结构构建4. 搜索子

C#基础之委托详解(Delegate)

《C#基础之委托详解(Delegate)》:本文主要介绍C#基础之委托(Delegate),具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录1. 委托定义2. 委托实例化3. 多播委托(Multicast Delegates)4. 委托的用途事件处理回调函数LINQ

解决Java中基于GeoTools的Shapefile读取乱码的问题

《解决Java中基于GeoTools的Shapefile读取乱码的问题》本文主要讨论了在使用Java编程语言进行地理信息数据解析时遇到的Shapefile属性信息乱码问题,以及根据不同的编码设置进行属... 目录前言1、Shapefile属性字段编码的情况:一、Shp文件常见的字符集编码1、System编码

Oracle存储过程里操作BLOB的字节数据的办法

《Oracle存储过程里操作BLOB的字节数据的办法》该篇文章介绍了如何在Oracle存储过程中操作BLOB的字节数据,作者研究了如何获取BLOB的字节长度、如何使用DBMS_LOB包进行BLOB操作... 目录一、缘由二、办法2.1 基本操作2.2 DBMS_LOB包2.3 字节级操作与RAW数据类型2.

利用Python实现添加或读取Excel公式

《利用Python实现添加或读取Excel公式》Excel公式是数据处理的核心工具,从简单的加减运算到复杂的逻辑判断,掌握基础语法是高效工作的起点,下面我们就来看看如何使用Python进行Excel公... 目录python Excel 库安装Python 在 Excel 中添加公式/函数Python 读取

CSS模拟 html 的 title 属性(鼠标悬浮显示提示文字效果)

《CSS模拟html的title属性(鼠标悬浮显示提示文字效果)》:本文主要介绍了如何使用CSS模拟HTML的title属性,通过鼠标悬浮显示提示文字效果,通过设置`.tipBox`和`.tipBox.tipContent`的样式,实现了提示内容的隐藏和显示,详细内容请阅读本文,希望能对你有所帮助... 效

Python如何实现读取csv文件时忽略文件的编码格式

《Python如何实现读取csv文件时忽略文件的编码格式》我们再日常读取csv文件的时候经常会发现csv文件的格式有多种,所以这篇文章为大家介绍了Python如何实现读取csv文件时忽略文件的编码格式... 目录1、背景介绍2、库的安装3、核心代码4、完整代码1、背景介绍我们再日常读取csv文件的时候经常