在完成实验室无人机项目中的数据采集模块时,使用ads1015完成对电压电流的采集,主机与从机之间采用软件I2C进行通信。在此记录一下调试过程并对I2C通信进行梳理。本篇是第一篇,先对单个ads1015的I2C通信的实现进行介绍。后续会更新多通道的实现。
一、ads1015的简单介绍
1.引脚
1.1、ADDR 地址引脚选择
设置地址来选择单个ads1015,主机根据地址对从机进行写寄存器,读寄存器等操作。
addr通过连接不同的引脚来设置地址。如:连接GND,地址为0x90,此时写地址为0x90,读地址为0x91;连接VDD,地址为0x92,此时写地址为0x92,读地址为0x93。
为什么这么设计呢?在ads1015的I2C通信中,
I2C设备的写地址 = I2C设备地址 << 1
I2C设备的读地址 = (I2C设备地址 << 1) + 1
我们把连接GND引脚的地址1001000左移一位得到10010000(0x90),再加一就得到了读地址0x91。这里的地址是在主机发起通信后发送给从机的,更详细的将在下面通信时序的部分介绍。
在本实验中,通过嵌入电阻将addr与GND和VCC连接,两个从机的地址分别为0x90和0x92。
1.2、ALERT/RDY 中断引脚,芯片里面可以配置电压比较,可作为数值比较器输出或转换就绪引脚
1.3、GND 地线
1.4、AIN0 AD转换通道0
1.5、AIN1 AD转换通道1
1.6、AIN2 AD转换通道2
1.7、AIN3 AD转换通道3
1.8、VDD
1.9、 SDA I2C数据线
1.10、SCL I2C时钟线
2、ads1015的寄存器
2.1、Address Pointer Register
地址指针寄存器。高6位为0,低2位用于指向四个寄存器。
2.2、Conversion Register
转换寄存器。存储ad转换的结果,我们要读取ads1015的ad数据就要读取这个寄存器的数据。
2.3、Config Register
配置寄存器。这个寄存器相当重要,在主机与从机开始通信后由主机写入配置。
OS:表示运行状态或者单次转换开始。
MUX[2:0]:输入多路复用器配置。
PGA[2:0]:可编程增益放大器配置。
FSR为满量程范围,标志着测量电压的最大范围。例如我们测量的电压VDD是3.3v,就要选择FSR=+-4.096v。
MODE:操作模式,包括连续转换模式/单次掉电模式
DR[2:0]:设置数据速率
COMP_MODE:比较器模式
COMP_POL:比较器极性:设置ALERT/RDY 低电平有效 or 高电平有效
COMP_LAT:锁存比较器
COMP_QUE[1:0]:比较器队列和禁用
4.Lo_thresh Register和Hi_thresh Register
比较器使用的上限和下限阈值以二进制形式存储在两个16位寄存器中。当PGA的值改变时,这个寄存器的值也要随之更新。同时,通过将Hi_thresh寄存器MSB设置为1和将Lo_thresh寄存器MSB设置为0,可以启用ALERT/RDY引脚的转换准备功能。
二、ads1015的I2C通信时序
3.1、I2C通信单元
首先我们先定义几个I2C通信的基本“单元”:主机发送起始信号,主机发送停止信号,主机应答ACK,主机不应答ACK(NACK),等待从机应答ACK信号。
开始位“Start”和停止位“Stop”,只能由Master主机来发出。
(1)主机发送起始信号(当SCL为高电平的时候,SDA线上由高到低的跳变被定义为起始条件):
1、主机将SDA线(对应GPIO口)配置为输出模式(推挽输出模式)
2、将SDA和SCL置为高电平,并适当延时等待电平稳定
3、将SDA置为低电平,并适当延时等待电平稳定
4、将SCL置为低电平
(2)主机发送停止信号(当SCL为高电平的时候,SDA线上由低到高的跳变被定义为停止条件):
1、主机将SDA线(对应GPIO口)配置为输出模式(推挽输出模式)
2、将SDA和SCL置为低电平
3、将SCL置为高电平,并适当延时等待电平稳定
4、将SDA置为高电平,并适当延时等待电平稳定
当读数据的时候,Slave设备每发送完8个数据位,如果Master希望继续读下一个字节,Master应该回答“ACK”以提示Slave准备下一个数据,如果Master不希望读取更多字节,Master应该回答“NACK”以提示Slave设备准备接收Stop信号。
(3)主机应答(ACK)
1、将SCL置为低电平
2、主机将SDA线(对应GPIO口)配置为输出模式(推挽输出模式)
3、将SDA置为低电平,并适当延时等待电平稳定
4、将SCL置为高电平,并适当延时等待电平稳定
5、将SCL置为低电平
(4)主机不应答(NACK)
1、将SCL置为低电平
2、主机将SDA线(对应GPIO口)配置为输出模式(推挽输出模式)
3、将SDA置为高电平,并适当延时等待电平稳定
4、将SCL置为高电平,并适当延时等待电平稳定
5、将SCL置为低电平
(5)等待从机应答ACK信号
地址的8位传送完毕后,成功配置地址的Slave设备必须发送“ACK”。否则否则一定时间之后Master视为超时,将放弃数据传送,发送“Stop”。
当写数据的时候,Master每发送完8个数据位,Slave设备如果还有空间接受下一个字节应该回答“ACK”,Slave设备如果没有空间接受更多的字节应该回答“NACK”,Master当收到“NACK”或者一定时间之后没收到任何数据将视为超时,此时Master放弃数据传送,发送“Stop”。
(6)发送一个字节
1、主机将SDA线(对应GPIO口)配置为输出模式(推挽输出模式)
2、拉低SCL开始数据传输
3、按位依次输出一个字节(8bits)的数据,若该bit大于0,SDA置高电平,反之SDA置低电平。
4、SCL置高电平,开始发送数据,并适当延时等待数据发送完成
5、SCL置低电平,并适当延时等待电平稳定,停止发送
6、循环3-5步骤八次,完成输出一个字节
(7)读取一个字节
1、主机将SDA线(对应GPIO口)配置为输入模式(上拉输入模式)
2、拉低SCL开始传输,并适当延时,等待从机发送数据
3、拉高SCL停止传输
4、通过库函数GPIO_ReadInputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)读取GPIOx_IDR,也就是当IO口设置为输入状态时候的IO口值
5、重复2、3、4步骤八次,完成一个字节的读取。
7、当读数据的时候,Slave设备每发送完8个数据位,如果Master希望继续读下一个字节,Master应该回答“ACK”以提示Slave准备下一个数据,如果Master不希望读取更多字节,Master应该回答“NACK”以提示Slave设备准备接收Stop信号。
3.2、I2C通信的主设备发送流程
(1)主机发送从机地址
从机回应后,向从机发送从机的写地址(例如上文中接GND引脚所选择的0x90),最后一位表示R/W(1/0)。若从机成功接收,则会回应ACK。
(2)主机向从机发送地址指针寄存器地址
主机向从机发送要写的寄存器config register的地址(0x01),P[1:0]为01,主机向从机发送的第二个字节就是0x01。
(3)主机向从机发送config register的配置参数
因为配置寄存器长16bit,所以要分成两个字节发送。第一个字节要右移八位放在低八位的位置,第二个字节&0xFF即可完成对config register的配置。这一步一共发送两个字节,每发送一个字节都需要等待从机的ACK。全部得到ACK后,主机发送停止信号。
3.3、主机读取ads1015的ad数据流程
(1)主机向从机发送从机地址(如上文的0x90)
主机发送开始信号,并开始传输从机地址。
(2)主机向从机发送地址指针寄存器地址
这里要读取conversion寄存器,所以P[1:0]为00,主机向从机发送的第二个字节就是0x00。
(3)主机向从机发送读地址
I2C设备的读地址 = (I2C设备地址 << 1) + 1,若从机地址为0x90,读地址为0x91。
(4)读取conversion register的数据
conversion register同样是16bit的寄存器,也要分两个字节读取。读取的第一个字节左移八位,作为高八位,第二个字节作为低八位,这样获取16位的完整数据。接收完成后,主机发送停止信号。