背景:拟采用bq33100超级电容管理芯片,实现自动的超级电容组的均压任务。需监控芯片的工作情况,以及电容组的均压情况。

平台:

硬件:STM32F103C8T6

通信:SMBus(低速IIC)

目标芯片:bq33100(TI)

SMbus简介:SMBus其实就是低速的IIC,和IIC协议基本相同,速度限制在10K~100KHz之间,一般应用于电源管理芯片等。

通信方式说明:这里考虑到SMBus需要限制IIC的速度,而通常使用的软件模拟IIC,我目前不清楚具体其通讯速率,而且我发现很多类似电源管理芯片的通信都是直接使用的硬件IIC,因此决定试一下硬件IIC的方式。由于STM32的硬件IIC普遍反映不是太稳定,可能会不定时卡死,这里参考野火的硬件IIC的历程中做了相应的超时处理(一旦卡死,就放弃本次的IIC通信),在实际的使用过程中,基本从来没有出现过触发这个卡死处理机制的情况(也就是说,其实可以尝试取消掉超时处理),但是这里以防万一还是选择保留。

配置代码:

void vIicConfig(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
I2C_InitTypeDef I2C_InitStructure; RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB, ENABLE );
RCC_APB1PeriphClockCmd( RCC_APB1Periph_I2C1, ENABLE ); /* GPIO.B6(IIC1_SCL) GPIO.B7(IIC1_SDA) */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD;
GPIO_Init( GPIOB, &GPIO_InitStructure ); /* can try to set to smbus mode */
I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;
I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;
I2C_InitStructure.I2C_OwnAddress1 = HUST_ADDRESS;
I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;
I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
/* smbus require frequency between 100KHz and 10KHz -> 10K */
I2C_InitStructure.I2C_ClockSpeed = I2C_Speed; I2C_Cmd( I2C1, ENABLE );
I2C_Init( I2C1, &I2C_InitStructure ); /* enable iic acknowledge */
I2C_AcknowledgeConfig( I2C1, ENABLE );
}

IIC读数据函数封装:(含超时处理以及错误报告)

/* for bq33100 chip realtime monitoring (just read base data) */
uint8_t I2C_Hardware_BufferRead(u8* pBuffer, u8 ReadAddr, u16 NumByteToRead)
{
I2CTimeout = I2C_LONG_TIMEOUT; while(I2C_GetFlagStatus(IIC1, I2C_FLAG_BUSY))
{
if((I2CTimeout--) == 0) return I2C_TIMEOUT_UserCallback(9);
} /* Send START condition */
I2C_GenerateSTART(IIC1, ENABLE); I2CTimeout = I2C_SHORT_TIMEOUT;
/* Test on EV5 and clear it */
while(!I2C_CheckEvent(IIC1, I2C_EVENT_MASTER_MODE_SELECT))
{
if((I2CTimeout--) == 0) return I2C_TIMEOUT_UserCallback(10);
} /* Send EEPROM address for write */
I2C_Send7bitAddress(IIC1, BQ33100_DEVICE_ADDRESS, I2C_Direction_Transmitter); I2CTimeout = I2C_SHORT_TIMEOUT;
/* Test on EV6 and clear it */
while(!I2C_CheckEvent(IIC1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED))
{
if((I2CTimeout--) == 0) return I2C_TIMEOUT_UserCallback(11);
} /* Clear EV6 by setting again the PE bit */
I2C_Cmd(IIC1, ENABLE); /* Send the EEPROM's internal address to write to */
I2C_SendData(IIC1, ReadAddr); I2CTimeout = I2C_SHORT_TIMEOUT;
/* Test on EV8 and clear it */
while(!I2C_CheckEvent(IIC1, I2C_EVENT_MASTER_BYTE_TRANSMITTED))
{
if((I2CTimeout--) == 0) return I2C_TIMEOUT_UserCallback(12);
} /* Send STRAT condition a second time */
I2C_GenerateSTART(IIC1, ENABLE); I2CTimeout = I2C_SHORT_TIMEOUT;
/* Test on EV5 and clear it */
while(!I2C_CheckEvent(IIC1, I2C_EVENT_MASTER_MODE_SELECT))
{
if((I2CTimeout--) == 0) return I2C_TIMEOUT_UserCallback(13);
} /* Send EEPROM address for read */
I2C_Send7bitAddress(IIC1, BQ33100_DEVICE_ADDRESS, I2C_Direction_Receiver); I2CTimeout = I2C_SHORT_TIMEOUT;
/* Test on EV6 and clear it */
while(!I2C_CheckEvent(IIC1, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED))
{
if((I2CTimeout--) == 0) return I2C_TIMEOUT_UserCallback(14);
} /* While there is data to be read */
while(NumByteToRead)
{
if(NumByteToRead == 1)
{
/* Disable Acknowledgement */
I2C_AcknowledgeConfig(IIC1, DISABLE); /* Send STOP Condition */
I2C_GenerateSTOP(IIC1, ENABLE);
} /* Test on EV7 and clear it */
I2CTimeout = I2C_LONG_TIMEOUT; while(I2C_CheckEvent(IIC1, I2C_EVENT_MASTER_BYTE_RECEIVED)==0)
{
if((I2CTimeout--) == 0) return I2C_TIMEOUT_UserCallback(3);
}
{
/* Read a byte from the EEPROM */
*pBuffer = I2C_ReceiveData(IIC1); /* Point to the next location where the byte read will be saved */
pBuffer++; /* Decrement the read bytes counter */
NumByteToRead--;
}
} /* Enable Acknowledgement to be ready for another reception */
I2C_AcknowledgeConfig(IIC1, ENABLE); return 0;
} /* hardware iic block processing */
static uint8_t I2C_TIMEOUT_UserCallback(uint8_t errorCode)
{
Error_Report(errorCode); return errorCode;
} /* report error information for debug */
static void Error_Report(uint8_t errorcode)
{
if(errorcode != 0)
{ }
}

bq33100通信函数示例:(只截取其中2个)

/* read health percent */
void bq33100_readhealthpercent(void)
{
uint8_t origin_healthpercent; bq33100.healthpercent_errorcode = I2C_Hardware_BufferRead(&origin_healthpercent,Health_ADD,1); bq33100.healthpercent = origin_healthpercent;
} /* read capacitance */
void bq33100_readcapacitance(void)
{
uint8_t temp[2];
uint16_t tmp = 0;
uint16_t origin_capacitance = 0; bq33100.capacitance_errorcode = I2C_Hardware_BufferRead(temp,Capacitance_ADD,2); tmp = (((uint16_t)temp[1] << 8) & 0xFF00); origin_capacitance = ((u16)(tmp + temp[0]) & 0xFFFF); bq33100.capacitance_mF = (float)origin_capacitance*1000;
}

——cloud over sky

——2020/3/1

STM32读取bq33100数据——硬件IIC的更多相关文章

  1. STM32读取Guidance数据——Guidance SDK

    更新记录:2019/11/14    更新STM32(F407VET6)读取Guidance数据 Github地址. 背景:想要将祖传的Guidance用于DJI A3/新固件的N3飞控.DJI已经停 ...

  2. STM32硬件IIC

    /** * @brief 写一个字节到I2C设备中 * @param * @arg pBuffer:缓冲区指针 * @arg WriteAddr:写地址 * @retval 正常返回1,异常返回0 * ...

  3. STM32 IIC双机通信—— HAL库硬件IIC版

    参考传送门 关于IIC的原理这里我就不多说了,网上有很多很好的解析,如果要看我个人对IIC的理解的话,可以点击查看,这里主要讲一下怎样利用STM32CubeMx实现IIC的通讯,经过个人实践,感觉HA ...

  4. STM32硬件IIC操作

    Stm32具有IIC接口,接口有以下主要特性 多主机功能:该模块既可做主设备也可做从设备 主设备功能 C地址检测 位/10位地址和广播呼叫 支持不同的通讯速度 状态标志: 发送器/接收器模式标志 字节 ...

  5. STM32硬件IIC (转)

    源: STM32硬件IIC

  6. STM32硬件IIC驱动设计(转)

    源: STM32硬件IIC驱动设计 参考: STM32—硬件IIC主机通信 STM32’s I2C 硬件BUG引发的血案(qzm) 解决STM32 I2C接口死锁在BUSY状态的方法讨论

  7. STM32读取HX711(AD)模块数据——压力传感器

    背景:在无人机动力系统的选型时,为了测试无人机的动力系统所能提供的最大拉力,使用压力传感装置测量拉力. 链接: 压力传感器tb链接: HX711模块是一个24位精度的AD模块. (1)https:// ...

  8. STM32读取匿名光流数据——与Guidance的光流和超声波做对比测试

    使用两个串口同时读取匿名光流和Guidance数据:用以比较两个光流的效果 Github链接:https://github.com/W-yt/YuTian_Pro/tree/master/Guidan ...

  9. STM32读取温湿度传感器DHT11和DHT21(AM2301)系列问题

    1.DHT11和DHT21传感器 这两种传感器都是奥松公司的产品,具体的传感器说明书在其官网上有(www.aosong.com). DHT11 数字温湿度传感器是一款含有已校准数字信号输出的温湿度复合 ...

随机推荐

  1. Xenia and Colorful Gems(二分--思维)

    给定三个数组a,b,c. 要求从每个数字取一个数,使得两两之差和最小. 求出这个数. \(我又懵逼了.我是会O(n^3)的暴力啊,怎么办.\) \(\color{Red}{从结果看,选出来的三个数必定 ...

  2. 聊聊算法——BFS和DFS

    如果面试字节跳动和腾讯,上来就是先撕算法,阿里就是会突然给你电话,而且不太在意是周末还是深夜, 别问我怎么知道的,想确认的可以亲自去试试.说到算法,直接力扣hard三百题也是可以的,但似乎会比较伤脑, ...

  3. 在web中使用shiro(会话管理,登出,shiro标签库的使用)

    在shiro的主配置文件中配置,登出的请求经过的过滤器就可以了,在shiro的过滤器中有一个名称为logout的过滤 器专门为我们处理登出请求: 一.shiro会话管理器 shiro中也提供了类似于w ...

  4. Spring Boot学习 之 Spring Boot Actuator(一)

    Spring Boot版本:2.1.4.RELEASE 启用: spring-boot-actuator模块提供了一系列的用于监控的端点.最简单的开启这个功能的方法就是,在pom文件中添加如下的依赖. ...

  5. 报错:Maven创建An internal error occurred during: "Retrieving archetypes:". Java heap space

    在Eclipse中创建Maven的Web项目时出现错误:An internal error occurred during: "Retrieving archetypes:". J ...

  6. 手把手教你撸一套Redux(Redux源码解读)

    Redux 版本:3.7.2 Redux 是 JavaScript 状态容器,提供可预测化的状态管理. 说白了Redux就是一个数据存储工具,所以数据基础模型有get方法,set方法以及数据改变后通知 ...

  7. JavaScript 的核心机制——event loop(最易懂版)

    前言 javascript从诞生之日起就是一门单线程的非阻塞的脚本语言. 非阻塞就是当代码需要进行一项异步任务(无法立刻返回结果,需要花一定时间才能返回的任务,如ajax事件)时,主线程会挂起(pen ...

  8. MySQL索引知识介绍

    前言: 索引是MySQL数据库中的重要对象之一,索引的目的在于提高查询效率.可以类比字典中的目录,查找字典内容时可以根据目录查找到数据的存放位置,然后直接获取即可.索引是表的目录,在查找内容之前可以先 ...

  9. HTTP Status完整枚举

    HTTP Status完整枚举 public enum HttpStatus { // 1xx Informational    1xx信息类的 继续    CONTINUE(100, "C ...

  10. Mysql 常用数据库操作

    一.数据库操作: 1.查看数据库: >SHOW DATABASES; 2.创建数据库: >CREATE DATABASE db_name; //db_name为数据库名 3.使用数据库: ...