1. 前言
本文只做软件协议相关的使用说明,对于硬件设计相关不做讨论。
本使用明细中涉及到的所有文档均来自诺泰官方技术支持并征得同意进行技术公开交流。其中涉及的代码均由我本人编写,仅供交流学习。
2. 数据手册
经由淘宝“青岛诺泰微电子有限公司”店铺客服获得资料,其中包含
1). 51设置板hex烧录文件和EEPROM二进制文件
2). STC软件、桌面端控制软件
3). 《1》通用水位设置板说明V2.5(支持USB).pdf、《3》如何使用通用液位设置板固定液位阈值V2.5(支持USB).pdf、《4》打印数据说明V2.5(支持USB).pdf
以上文件如需请自行前往上述淘宝店铺进行询问下载。
在诺泰微电子官网(https://www.nutechchip.cn/)找到芯片的数据手册(https://www.nutechchip.cn/product/showproduct.php?id=123),其下载链接(https://www.nutechchip.cn/upload/file/TM611AWL4P_chspec_V00.pdf)
在数据手册中了解到,本芯片使用IIC总线进行数据通信,芯片地址固定为0x40
其中本芯片一共有四个寄存器WL、REG1、REG2、REG3
此外本芯片有着较宽的电压输入范围
上述数据手册仅仅只介绍了芯片的基础用法,并没有对如何配置空液位、低液位、满液位信息进行更新,而是指出需要使用官方标配的“设置板”进行配置,这无疑增加了设备的复杂程度,对环境的适配程度也会降低,于是我开始寻找关于上述三个阈值设置的方式,最终通过诺泰淘宝客服添加技术人员的微信,技术人员得知我的需求后,给出了一份“连续和八点液位通信说明.docx”的相关文档,并征得同意后允许公开交流学习。
获得上述详细的协议交接过程后,便可以开始正式的代码编写了
3. 协议代码
本次使用VSCode和ESP32作为测试平台进行代码编写,可参考协议流程
0). 基础宏定义
#define TM611ARR 0x40
#define TM611_REG1 0x01
#define TM611_REG2 0x02
#define TM611_REG3 0x03
#define ACCESS1 0x01
#define ACCESS2 0x02
#define ACCESS3 0x03
#define ACCESS4 0x04
1). 基础IIC交互函数代码
// 类构造函数
TM611AWLCOR::TM611AWLCOR(unsigned char addres){
// 保存初始化地址
this->addres = addres;
};
// 初始化
void TM611AWLCOR::begin(){
// 使用硬件iic
Wire.begin();
}
// 呼叫AT24C02
void TM611AWLCOR::wait(){
int resault = 0;
do{
Wire.beginTransmission(addres);
resault = Wire.endTransmission();
} while (resault != 0);
}
// 在指定地址写入一位数据
void TM611AWLCOR::write_byte(unsigned char addr,unsigned char dat){
TM611AWLCOR::wait();
Wire.beginTransmission(addres);
Wire.write(addr); /*发送写地址*/
Wire.write(dat); /*写数据*/
Wire.endTransmission();
}
// 在指定地址读取一位数据
unsigned char TM611AWLCOR::read_byte(unsigned char addr){
int ret = 0xff;
TM611AWLCOR::wait();
Wire.beginTransmission(addres);
Wire.write(addr); /*发送要读的地址*/
Wire.endTransmission();
/*读数据*/
Wire.requestFrom((int)addres,1);
ret = Wire.read();
return ret;
}
2). 获取液面位置信息函数
// 读取液面数值
unsigned char TM611AWLCOR::readLiquid(){
return read_byte(0x00);
}
3). 协议握手函数
// 协议握手
unsigned char TM611AWLCOR::handshake(unsigned char dat){
unsigned char reg1;
unsigned int num=0;
while(reg1!=dat){
Wire.requestFrom((int)0x40,1);
reg1 = Wire.read();
num++;
if(num>1000)return 0; // 握手失败
}
return 1; // 握手成功
}
4). 设置空水位阈值函数
// 设置空水位
void TM611AWLCOR::setNullLiquid(){
// 向REG1寄存器写入0xca
write_byte(TM611_REG1,0xca);
// 等待从机发送0xcd握手数据
handshake(0xcd);
// 写入操作通道号1
write_byte(TM611_REG1,ACCESS1+0x30);
delay(50);
// 读取REG1(0x01)数据
Wire.beginTransmission(0x40);
Wire.write(TM611_REG1);
Wire.endTransmission();
handshake(ACCESS1);
reg2 = read_byte(0x02);
reg3 = read_byte(0x03);
// 向REG1(0x01)写入0x8c
write_byte(TM611_REG1,0x8c);
// 等待从机发送0xcd握手数据
handshake(0xcd);
// 写入操作通道号1
write_byte(TM611_REG1,ACCESS1+0x30);
delay(50);
// 读取REG1(0x01)数据
Wire.beginTransmission(0x40);
Wire.write(TM611_REG1);
Wire.endTransmission();
handshake(ACCESS1);
}
5). 设置低水位阈值函数
// 设置低水位
void TM611AWLCOR::setLowLiquid(){
// 向REG1寄存器写入0xca
write_byte(TM611_REG1,0xca);
// 等待从机发送0xcd握手数据
handshake(0xcd);
// 写入操作通道号2
write_byte(TM611_REG1,ACCESS2+0x30);
delay(50);
// 读取REG1(0x01)数据
Wire.beginTransmission(0x40);
Wire.write(TM611_REG1);
Wire.endTransmission();
handshake(ACCESS2);
reg2 = read_byte(0x02);
reg3 = read_byte(0x03);
// 向REG1(0x01)写入0x8c
write_byte(TM611_REG1,0x8c);
// 等待从机发送0xcd握手数据
handshake(0xcd);
// 写入操作通道号2
write_byte(TM611_REG1,ACCESS2+0x30);
delay(50);
// 请求读取REG1(0x01)数据
Wire.beginTransmission(0x40);
Wire.write(TM611_REG1);
Wire.endTransmission();
handshake(ACCESS2);
}
6). 设置满水位阈值函数
// 设置满水位
void TM611AWLCOR::setFullLiquid(){
// 向REG1寄存器写入0xca
write_byte(TM611_REG1,0xca);
// 等待从机发送0xcd握手数据
handshake(0xcd);
// 写入操作通道号1
write_byte(TM611_REG1,ACCESS1+0x30);
delay(50);
// 读取REG1(0x01)数据
Wire.beginTransmission(0x40);
Wire.write(TM611_REG1);
Wire.endTransmission();
handshake(ACCESS1);
reg2 = read_byte(TM611_REG2);
reg3 = read_byte(TM611_REG3);
// 向REG1(0x01)写入0x8c
write_byte(TM611_REG1,0x8c);
// 等待从机发送0xcd握手数据
handshake(0xcd);
// 写入操作通道号1
write_byte(TM611_REG1,ACCESS3+0x30);
delay(50);
// 读取REG1(0x01)数据
Wire.beginTransmission(0x40);
Wire.write(TM611_REG1);
Wire.endTransmission();
handshake(ACCESS3);
// 向REG1寄存器写入0xca
write_byte(TM611_REG1,0xca);
// 等待从机发送0xcd握手数据
handshake(0xcd);
// 写入操作通道号2
write_byte(TM611_REG1,ACCESS2+0x30);
delay(50);
// 读取REG1(0x01)数据
Wire.beginTransmission(0x40);
Wire.write(TM611_REG1);
Wire.endTransmission();
handshake(ACCESS2);
reg2 = read_byte(TM611_REG2);
reg3 = read_byte(TM611_REG3);
// 向REG1(0x01)写入0x8c
write_byte(TM611_REG1,0x8c);
// 等待从机发送0xcd握手数据
handshake(0xcd);
// 写入操作通道号4
write_byte(TM611_REG1,ACCESS4+0x30);
delay(50);
// 读取REG1(0x01)数据
Wire.beginTransmission(0x40);
Wire.write(TM611_REG1);
Wire.endTransmission();
handshake(ACCESS4);
}
以上,便可轻松在本设备无需通过设置板而直接通过IIC接口实现三个阈值的设置,减轻外设,方便快捷