上图是TPS65987的i2c读写协议,和标准i2c协议有点出入,不过也不难理解,在读的时候i2c slave在发送数据过来之前会先发送1byte数据表示后面会有几个字节数据过来,在写的时候i2c host要先写1byte数据告诉i2c slave接下来会写几个bytes数据。

 Talk is cheap. Show me the code.

以下代码是基于STM8S。

/*******************************************************************************
**函数名称:void IIC_Read(unsigned char subaddr , unsigned char Byte_addr , unsigned char *buffer)
**功能描述:向IIC器件读数据
**入口参数:
subaddr : 从器件地址
Byte_addr : 确定从器件写地址的起始地址
*buffer : 读数据的缓冲区起始地址
**输出:无
*******************************************************************************/
void TPS65987_IIC_Read(unsigned char subaddr , unsigned char Byte_addr , unsigned char *buffer)
{
unsigned char i2csr1;
unsigned char DataLen; I2C_CR2_bit.ACK = ; //产生应答信号 I2C_CR2_bit.START = ; //发送起始信号
while(I2C_SR1_bit.SB == ); //等待起始信号产生
i2csr1 = I2C_SR1; //SR1.AF??
I2C_DR = subaddr; //发送器件地地址,并清除SB标志位
while(I2C_SR1_bit.ADDR == ); //等待器件地址发送完成
i2csr1 = I2C_SR1;
i2csr1 = I2C_SR3; //读状态寄存器1和状态寄存器3清除发送器件地址标志位
I2C_DR = Byte_addr;
while(I2C_SR1_bit.BTF == );//等待移位发送器发送完成
i2csr1 = I2C_SR1; //清除BIT标志位 //重新发送起始信号
I2C_CR2_bit.START = ;//I2C1->CR1 |= I2C_CR1_START;
while(I2C_SR1_bit.SB == );//等待起始信号产生 i2csr1 = I2C_SR1;//SR1.AF??
I2C_DR = (char)(subaddr | 0x01); //发送器件地地址,并清除SB标志位
while(I2C_SR1_bit.ADDR == ); //等待器件地址发送完成
i2csr1 = I2C_SR1;
i2csr1 = I2C_SR3; //读状态寄存器1和状态寄存器2清除发送器件地址标志位 while (I2C_SR1_bit.RXNE == ); //先读取Byte Count到DataLen
i2csr1 = I2C_SR1;
DataLen = I2C_DR; while(DataLen)
{
if(DataLen == )
{
I2C_CR2_bit.ACK = ; //最后一个字节不产生应答信号
I2C_CR2_bit.STOP = ; //发送停止信号结束数据传输
} while(I2C_SR1_bit.RXNE == );
i2csr1 = I2C_SR1; *buffer = I2C_DR;
buffer++;
DataLen--;
}
}
/*******************************************************************************
**函数名称:void IIC_Write(unsigned char subaddr , unsigned char Byte_addr , unsigned char *buffer , unsigned short num)
**功能描述:向IIC器件写数据
**入口参数:
subaddr : 从器件地址
Byte_addr : 确定器件写地址的起始地址
*buffer : 写数据的起址地址
num : 要写数据的个数
**输出:无
*******************************************************************************/
void TPS65987_IIC_Write(unsigned char subaddr , unsigned char Byte_addr , unsigned char *buffer , unsigned short num)
{
unsigned char i2csr1; //while(I2C1->SR2 & I2C_SR2_BUSY); //判断I2C模块是否忙 //发送起始信号
I2C_CR2_bit.START = ;
while(I2C_SR1_bit.SB == ); //等待起始信号产生
i2csr1 = I2C_SR1; //SR1.AF
I2C_DR = (subaddr); //发送从器件地址,并清除SB标志位
while(I2C_SR1_bit.ADDR == ); //等待器件地址发送完成
i2csr1 = I2C_SR1;
i2csr1 = I2C_SR3; //读状态寄存器1和状态寄存器3清除发送器件地址标志位 I2C_DR = Byte_addr; //发送从器件存储首地址
#if 1
while(I2C_SR1_bit.BTF == ); //等待移位发送器发送完成
i2csr1 = I2C_SR1; //清除BIT标志位
#else
while((I2C_SR1_bit.TXE) == );//数据寄存器为空,跳出循环继续运行
i2csr1 = I2C_SR1;
#endif
I2C_DR = (unsigned char)num; //把Byte Count先告诉给TPS65987
while(I2C_SR1_bit.BTF == );//等待移位发送器发送完成
i2csr1 = I2C_SR1; //清除BIT标志位
i2csr1 = I2C_DR; while(num > )
{
I2C_DR = *buffer; //发送器件存储首地址 while(I2C_SR1_bit.BTF == );//等待移位发送器发送完成
i2csr1 = I2C_SR1; //清除BIT标志位
i2csr1 = I2C_DR;
buffer++;
num--;
}
I2C_CR2_bit.STOP = ; //发送停止信号结束数据传输
}

这样就可以对TPS65987进行读写了。

上面的i2c读写函数没有加上timeout功能,如果不想在i2c通信不成功时一直阻塞的话,可以在while循环里面加上,例如:

unsigned int count = ;

while(I2C_SR1_bit.ADDR == )    //等待器件地址发送完成
{
if (++count > ) { //count大于6000立即返回
I2C_CR2_bit.STOP = ;
return;
}
}

注意:

从Windows下上位机工具也可以进行TPS65987的register读写,TPS65981_2_6_7_8 Application Customization 6.1.1上显示的i2c1地址为0x20, i2c2的地址为0x38;注意0x20/0x38是七位地址位的值,进行i2c读写时的地址要左移一位,即0x20/0x38 << 1等于0x40/0x70。

如果直接用地址0x20/0x38进行读写会怎么样呢,结果就是地址发过去没收到ACK。下图是用0x38地址去读寄存器值的时候示波器抓到的波形(黄色波形是SCL,粉红色波形是SDA)。

从波形上看0x38地址发过去是没有ACK的,所以slave地址0x38肯定是错误的了。

后面用示波器量了一下TPS65981_2_6_7_8 Application Customization 6.1.1上位机软件和TPS65987 EVM进行i2c读写时的波形,发现i2c2的地址发过去的确实是0x70。

使用STM8S i2c对TPS65987寄存器进行读写的更多相关文章

  1. MSP430的IO口模拟I2C总线对AT24C25进行读写程序

    功能: 实现MSP430口线模拟I2C总线协议与24C04通信.                                           ** 描述: 主系统工作时钟为12MHz,I2C工 ...

  2. Linux I2C总线设备驱动模型分析(ov7740)

    1. 框架1.1 硬件协议简介1.2 驱动框架1.3 bus-drv-dev模型及写程序a. 设备的4种构建方法a.1 定义一个i2c_board_info, 里面有:名字, 设备地址 然后i2c_r ...

  3. Linux下读写芯片的I2C寄存器

    要想在Linux下读写芯片的I2C寄存器,一般需要在Linux编写一份该芯片的I2C驱动,关于Linux下如何编写I2C驱动,前一篇文章<手把手教你写Linux I2C设备驱动>已经做了初 ...

  4. 第23章 I2C—读写EEPROM—零死角玩转STM32-F429系列

    第23章     I2C—读写EEPROM 全套200集视频教程和1000页PDF教程请到秉火论坛下载:www.firebbs.cn 野火视频教程优酷观看网址:http://i.youku.com/f ...

  5. [RK3288][Android6.0] 调试笔记 --- pmu(rk818)寄存器读写【转】

    本文转载自:http://blog.csdn.net/kris_fei/article/details/76919134 Platform: Rockchip OS: Android 6.0 Kern ...

  6. i2c总线,设备,驱动之间的关系

    ------ 总线上先添加好所有具体驱动,i2c.c遍历i2c_boardinfo链表,依次建立i2c_client, 并对每一个i2c_client与所有这个线上的驱动匹配,匹配上,就调用这个驱动的 ...

  7. Linux设备驱动模型之I2C总线

    一.I2C子系统总体架构 1.三大组成部分 (1)I2C核心(i2c-core):I2C核心提供了I2C总线驱动(适配器)和设备驱动的注册.注销方法,提供了与具体硬件无关的I2C读写函数. (2)I2 ...

  8. Linux+I2C总线分析(主要是probe的方式)

    Linux I2C 总线浅析 ㈠ Overview Linux的I2C体系结构分为3个组成部分: ·I2C核心: I2C核心提供了I2C总线驱动和设备驱动的注册.注销方法,I2C通信方法(即“algo ...

  9. IMX6 PCA9698应用层读写库

    .c #include <stdio.h> #include <string.h> #include <linux/types.h> #include <st ...

随机推荐

  1. coding++:Spring IOC/DI 实现原理

    什么是 SpringIOC: spring ioc 指的是控制反转,IOC容器负责实例化.定位.配置应用程序中的对象及建立这些对象间的依赖.交由Spring容器统一进行管理,从而实现松耦合. “控制反 ...

  2. 常用的python标准库

    os  :   操作系统接口 sys:    命令行操作 re : 正则模块 math :   数学模块 time,timedate: 日期模块 random: 随机数模块 threading: 线程 ...

  3. Eclipse打包jar

    对一个包打jar包 右键包名-Export-Jar File-选择所在包的class文件(注意),如果选择java文件会失败-然后Finish 检查jar包是否正确,使用如jd-gui这样的反编译工具 ...

  4. vulnhub~incllusiveness

    这个机子相对简单一点,但是也是从中发现了自己不少问题 技能一:  nmap 扫描发现了21,22 ,80三个端口,并且ftp服务允许匿名登录,在pub目录下面有writeable权限,这就好办了.我以 ...

  5. 《Java基础复习》—常识与入门

    突然发现自己Java基础的底子不到位,复习! 所记知识会发布在CSDN与博客网站jirath.cn <Java基础复习>-常识与入门 一.Java语言的知识体系图 分为三部分 编程语言核心 ...

  6. resetFields() 有时无效问题

    elementui在重置表单时,无法使用this.$refs['formRefVal'].resetFields()清空表单数据; elementui 设置rules后没有效果 解决方法: prop属 ...

  7. 曹工说Redis源码(4)-- 通过redis server源码来理解 listen 函数中的 backlog 参数

    文章导航 Redis源码系列的初衷,是帮助我们更好地理解Redis,更懂Redis,而怎么才能懂,光看是不够的,建议跟着下面的这一篇,把环境搭建起来,后续可以自己阅读源码,或者跟着我这边一起阅读.由于 ...

  8. 【Debug记录】Exeption thrown by glCreateVertexArrays

    继在机场丢失笔记本后又一大灾难--小组项目无法在老电脑上运行. 位置:glCreateVertexArrays函数 报错:Exception thrown at 0x00000000 in Clien ...

  9. python 函数--装饰器

    一.装饰器 1.为什么要用装饰器? 装饰器的功能:在不修改原函数以及调用方式的情况下对原函数功能进行扩展. 二.开放和封闭原则 1.对扩展是开放的 2.对修改是封闭的 三.装饰器的固有结构 impor ...

  10. Linux基础篇,系统服务(service)的管理

    一.服务是什么? 用白话文说,服务就是"常驻在内存中的进程",用来提供一些系统或网络功能. 二.service和daemon的区别与联系 因为服务(service)本质上来说也是程 ...