GX28E17兼容DS28E17 一种1-Wire从机至I2C主机桥接器的二氧化碳(CO2)模组应用
一、文章摘要
二、基本参数
三、器件应用
四、参考驱动
一、文章摘要
CO2浓度监测模组应用有长远距离要求,在标准模式下,I2C通信距离长度被限制在几米,已无法满足需求。本文主要介绍使用GX28E17延长I2C器件通信距离,同时降低成本。
I2C总线的最大距离取决于电容大小。因为构建系统必须以容纳400pF的最大总线电容,以满足I2C总线规范(2014年4月6日至4日修订)中列出的上升时间要求。为了通过运行在最大允许总线电容之上实现更大的距离,I2C总线规范允许以较低的速度运行,使用更高的驱动输出设备,将总线分成带有总线缓冲区的段,或使用开关上拉电路。虽然从表面上看,这些方法似乎可行,但它们要么不满足长距离要求,要么显著增加成本。因此使用GX28E17 1-Wire对I2C主桥接器。
二、基本参数
●● 产品特点
● 将1-Wire 通信协议转换为 I2C 主I/O
● 通过单触点、1-Wire 接口操作 I2C 从设备外设
● 使用1-Wire 协议扩展 I2C 通信距离(典型100米)
● 灵活的1-Wire 从机和 I2C 主机工作模式
● 1-Wire接口支持 15kbps 和 77kbps 通信速率,带分组 I2C 数据有效负载
● I2C 的标准 100kHz 、400kHz 和1MHZ 通信速率
● I2C接口支持时钟延展功能
● 工厂编程的唯一 64 位 1-Wire ROM ID 为终端设备提供不可更改的序列号
●● 低功耗
● 正常工作时为 1.5mA(典型值)
● 睡眠模式下为 0.3μA(典型值)
● 具有可用于睡眠和唤醒灵活性的独立引脚
● 可由唤醒引脚控制的远程电源
● 通过睡眠引脚或 1-Wire 器件命令使能睡眠模式
●● 应用场景
● 远端外设识别与控制
● IIC传感器
● 显示控制器
● 数模、模数转换器
三、器件应用
一、典型应用电路
二、1-Wire 信号时序
1-Wire 协议在单根信号线上定义了以下六种基本信号类型:复位脉冲,响应脉冲,写 0,写 1,读 0, 读 1。除响应脉冲外,所有信号都由主机启动,且以总线下降沿为计时起点。
如图 1 所示主机通过拉低总线超过 480us 向总线发送复位脉冲。GX28E17识别到复位脉冲后会复位自身通信状态,并在复位脉冲结束后(主机释放总线) 等待一定时间(15~60us)再发送响应脉冲(通过拉低总线 60~240us)。为了检测响应脉冲,主机必须在特定窗口时间内对总线采样。当采样到总线为低电平时, 说明存在响应脉冲,表示GX28E17已经准备好开始通信;当采样到总线为高电平时,说明不存在响应脉冲,表示复位脉冲未被GX28E17识别,或总线上未挂载任何器件。
1-Wire 数据传输以时隙(Time Slot)为基本单位,每次仅携带一位数据。 其中,写时隙将主机发送的数据传输给IIC器件;读时隙将GX28E17发送的数 据传输给主机。 读写时隙均开始于主机拉低总线,时隙宽度不短于 65us,相邻时隙之间必 须提供不短于 1us 的恢复时间。 写时隙启动后,GX28E17将在特定窗口时间内对总线采样,如图 2 所示。 采样结果即为GX28E17接收到的一位数据。
● 写 1 时隙:主机拉低总线后,必须在 15us 内释放总线;
● 写 0 时隙:主机拉低总线后,必须维持至少 60us 才能释放总线。
当且仅当主机启动读时隙时,GX28E17才能向主机发送数据。如图 3 所示, 主机拉低总线启动读时隙后,必须维持 1~15us 以确保总线下降沿能够被GX28E17 识别。如果GX28E17 识别成功,将根据自身即将发送的数据来决定对总线的后续操作。因此,读时隙可以进一步区分为以下两种信号:
● 读 1 时隙:从总线下降沿开始,直接释放总线;
● 读 0 时隙:从总线下降沿开始,拉低总线并维持 15~60us。
为了接收 GX28E17发送的数据,主机必须在特定窗口时间内对总线采样, 采样结果即为所接收到的一位数据。注意:读 0 时隙的数据有效时间最短为 15us, 因此采样窗口最大不能超过该有效时间。出于最大化时序裕度的考虑,建议将主 机释放总线时间尽可能提前,将主机采样时间尽可能延后。
三、1-Wire 通信流程
GX28E17 的 1-Wire 通信流程由初始化序列、寻址命令、功能命令和 I2C 数据这四个部分组成。当初始化完成后主机可以发送寻址命令来搜索和选择特定器件。GX28E17 支持七种寻址命令
● 读寻址(Read ROM)[33h]
● 匹配寻址(Match ROM)[55h]
● 搜索寻址(Search ROM)[F0h]
● 跳过寻址(Skip ROM)[CCh]
● 恢复寻址(Resume ROM)[A5h]
● 超速跳过寻址(Overdrive-Skip ROM)[3Ch]
● 超速匹配寻址(Overdrive-Match ROM)[69h]
四、二氧化碳模组GX28E17应用
4.1 产品外观
4.2产品功能特点
4.3产品指标参数
4.4寄存器命令
4.5.1写寄存器
4.5.2读数据
4.5.3寄存器数据表
4.6部分寄存器说明
4.6.1开始测量
4.6.2读取测量
4.6.3停止测量
4.7实测波形
4.7.1 读寻址
4.7.2 发送命令 0XE4B8 读取数据就绪状态
4.7.3 发送 CO2 读值命令
4.7.4 CO2 读值返回
四、GX28E17驱动参考(部分)
gx28e17.c
#include "globle.h"
/*---------------------------------------------------------------------
Function : gx28e17_read_rom
Description : execute READ_ROM command
Parameter 1 : 1-wire communication speed
Return : ID number of current device (0=no device was found)
---------------------------------------------------------------------*/
uint64_t gx28e17_read_rom(u8 spd)
{
u8 rxd = 0;
uint64_t id = 0;
u8 i;
if(onewire_reset(spd) == ACK) {
onewire_write(spd, ROM_READ);
for( i = 0; i < 8; i ++) {
rxd = onewire_read(spd);
printf("%02X",rxd);
id = id | (((uint64_t) rxd) << (8 * i));
}
}
else
printf("Read ROM : No device on the bus.\r\n");
return id;
}
/*---------------------------------------------------------------------
Function : gx28e17_match_rom
Description : execute MATCH_ROM command
Parameter 1 : 1-wire communication speed
Parameter 2 : ID number of selected device
Return : finish flag
---------------------------------------------------------------------*/
u8 gx28e17_match_rom(u8 spd, uint64_t id)
{
u8 txd = 0;
u8 i;
if(onewire_reset(spd) == ACK) {
onewire_write(spd, ROM_MATCH);
for( i = 0; i < 8; i ++) {
txd = (u8) (id >> (8 * i));
onewire_write(spd, txd);
}
return DONE;
}
else {
printf("Match ROM : No device on the bus.\r\n");
return ERROR;
}
}
/*---------------------------------------------------------------------
Function : gx28e17_match_rom_od
Description : execute MATCH_ROM_OVERDRIVE command
Parameter 1 : 1-wire communication speed
Parameter 2 : ID number of selected device
Return : finish flag
---------------------------------------------------------------------*/
u8 gx28e17_match_rom_od(u8 spd, uint64_t id)
{
u8 txd = 0;
u8 i;
if(onewire_reset(spd) == ACK) {
onewire_write(spd, ROM_MATCH_OD);
for( i = 0; i < 8; i ++) {
txd = (u8) (id >> (8 * i));
onewire_write(SPD_OD, txd);
}
return DONE;
}
else {
printf("Match ROM (od) : No device on the bus.\r\n");
return ERROR;
}
}
/*---------------------------------------------------------------------
Function : gx28e17_search_rom
Description : execute search algorithm
Parameter 1 : 1-wire communication speed
Parameter 2 : ID number array of devices found
Return : number of devices found (0=no device was found)
---------------------------------------------------------------------*/
u8 gx28e17_search_rom(u8 spd, uint64_t * ids)
{
u8 num = 0; // number of device found
u8 pos = 0; // current bit position
u8 dir = 0; // search direction
u8 val = 0; // current bit
u8 val_cmp = 0; // complement of current bit
u8 brn_new = 0; // the bit position where a new branch is taken
u8 brn_chk = 0; // branch checkpoint
uint64_t cur_id = 0; // current ID
uint64_t reg_id = 0; // last ID found
do {
if(onewire_reset(spd) == ACK) {
brn_new = 0;
cur_id = 0;
onewire_write(spd, ROM_SEARCH);
for(pos = 1; pos < 65; pos ++) {
cur_id = cur_id >> 1;
val = onewire_read_bit(spd);
val_cmp = onewire_read_bit(spd);
/*
00 : There are both 0s and 1s in the current bit position of the participating ROM numbers => discrepancy
01 : There are only 0s in the current bit position of the participating ROM numbers
10 : There are only 1s in the current bit position of the participating ROM numbers
11 : No device participating in the search (atypical situation)
*/
if((val == 0) && (val_cmp == 0)) {
/*
pos < brn_chk : take the same path as last time (from last ROM number found)
pos = brn_chk : take the "1" path
pos > brn_chk : take the "0" path
*/
if(pos < brn_chk)
dir = ((u8) (reg_id >> (pos - 1))) & 0x01;
else if(pos == brn_chk)
dir = 1;
else
dir = 0;
if(dir == 0)
brn_new = pos;
}
else if((val == 0) && (val_cmp != 0))
dir = 0;
else if((val != 0) && (val_cmp == 0))
dir = 1;
else {
printf("Search ROM : The device discovered is removed from the 1-wire bus during the search. (bit %d)\r\n", pos);
return 0;
}
cur_id = cur_id | ((dir == 0) ? 0x0000000000000000 : 0x8000000000000000);
onewire_write_bit(spd, dir);
}
brn_chk = brn_new;
reg_id = cur_id;
ids[num] = cur_id;
num ++;
}
else {
printf("Search ROM : No device on the bus.\r\n");
return 0;
}
} while (brn_chk > 0);
return num; // Returning zero means that no device was found
}
/*---------------------------------------------------------------------
Function : gx28e17_skip_rom
Description : execute SKIP_ROM command
Parameter 1 : 1-wire communication speed
Return : finish flag
---------------------------------------------------------------------*/
u8 gx28e17_skip_rom(u8 spd)
{
if(onewire_reset(spd) == ACK) {
onewire_write(spd, ROM_SKIP);
return DONE;
}
else {
printf("Skip ROM : No device on the bus.\r\n");
return ERROR;
}
}
/*---------------------------------------------------------------------
Function : gx28e17_skip_rom_od
Description : execute SKIP_ROM_OVERDRIVE command
Parameter 1 : 1-wire communication speed
Return : finish flag
---------------------------------------------------------------------*/
u8 gx28e17_skip_rom_od(u8 spd)
{
if(onewire_reset(spd) == ACK) {
onewire_write(spd, ROM_SKIP_OD);
return DONE;
}
else {
printf("Skip ROM (od) : No device on the bus.\r\n");
return ERROR;
}
}
/*---------------------------------------------------------------------
Function : gx28e17_resume_rom
Description : execute RESUME_ROM command
Parameter 1 : 1-wire communication speed
Return : finish flag
---------------------------------------------------------------------*/
u8 gx28e17_resume_rom(u8 spd)
{
if(onewire_reset(spd) == ACK) {
onewire_write(spd, ROM_RESUME);
return DONE;
}
else {
printf("Resume ROM : No device on the bus.\r\n");
return ERROR;
}
}
/*---------------------------------------------------------------------
Function : gx28e17_write_with_stop
Description : execute WRITE_DATA_WITH_STOP command
Parameter 1 : 1-wire communication speed
Parameter 2 : I2C slave address
Parameter 3 : I2C write length
Parameter 4 : I2C write data array
Return : finish flag
---------------------------------------------------------------------*/
u8 gx28e17_write_with_stop(u8 spd, u8 addr, u8 wlen, u8 * wdat)
{
u8 st = 0;
u8 wst = 0;
u8 cnt = 0;
uint16_t crc = 0;
u8 i;
// transmit 1-wire packet
onewire_write(spd, DEV_WR_STP);
onewire_write(spd, addr);
onewire_write(spd, wlen);
for( i = 0; i < wlen; i ++)
onewire_write(spd, wdat[i]);
// crc
crc = gx28e17_generate_crc(DEV_WR_STP, addr, wlen, wdat, 0);
onewire_write(spd, ((u8) crc));
onewire_write(spd, ((u8) (crc >> 8)));
// poll
while(onewire_read_bit(spd) != 0) {
delay_100us();
cnt ++;
if(cnt > POLL_MAX) {
printf("Write with stop : Exceed query limit.\r\n");
return ERROR;
}
}
// read return bytes
st = onewire_read(spd);
wst = onewire_read(spd);
switch(st) {
case ERR_STA : {
printf("Write with stop : Invalid start condition.\r\n");
return ERROR;
}
case ERR_ADR : {
printf("Write with stop : I2C slave device does not acknowledge the I2C address.\r\n");
return ERROR;
}
case ERR_CRC : {
printf("Write with stop : 1-Wire packet data does not match the corresponding CRC-16.\r\n");
return ERROR;
}
default : break;
}
if(wst == 0)
return DONE; // Done correctly
else {
printf("Write with stop : Byte %d is not acknowledged by the I2C slave device.\r\n", wst);
return ERROR;
}
}
/*---------------------------------------------------------------------
Function : gx28e17_write_no_stop
Description : execute WRITE_DATA_NO_STOP command
Parameter 1 : 1-wire communication speed
Parameter 2 : I2C slave address
Parameter 3 : I2C write length
Parameter 4 : I2C write data array
Return : finish flag
---------------------------------------------------------------------*/
//
u8 gx28e17_write_no_stop(u8 spd, u8 addr, u8 wlen, u8 * wdat)
{
u8 st = 0;
u8 wst = 0;
u8 cnt = 0;
uint16_t crc = 0;
u8 i;
// transmit 1-wire packet
onewire_write(spd, DEV_WR);//命令0x5A --》Write data no stop
onewire_write(spd, addr);//地址
onewire_write(spd, wlen);//长度
for( i = 0; i < wlen; i ++)//0x02
onewire_write(spd, wdat[i]);
// crc
crc = gx28e17_generate_crc(DEV_WR, addr, wlen, wdat, 0);
onewire_write(spd, ((u8) crc));
onewire_write(spd, ((u8) (crc >> 8)));
// poll---》这里实现方式有三种:主机等待一个预定的时间,检测BUSY pin的状态,读取非0
while(onewire_read_bit(spd) != 0) {
delay_100us();
cnt ++;
if(cnt > POLL_MAX) {
printf("Write no stop : Exceed query limit.\r\n");
return 0;
}
}
// read return bytes
st = onewire_read(spd);
wst = onewire_read(spd);
switch(st) {
case ERR_STA : {//0x08
printf("Write no stop : Invalid start condition.\r\n");
return ERROR;
}
case ERR_ADR : {//0x02
printf("Write no stop : I2C slave device does not acknowledge the I2C address.\r\n");
return ERROR;
}
case ERR_CRC : {//0x01
printf("Write no stop : 1-Wire packet data does not match the corresponding CRC-16.\r\n");
return ERROR;
}
default : break;
}
if(wst == 0)
return DONE; // Done correctly
else {
printf("Write no stop : Byte %d = %02X is not acknowledged by the I2C slave device.\r\n", wst,wst);
return ERROR;
}
}
/*---------------------------------------------------------------------
Function : gx28e17_write_only_no_stop
Description : execute WRITE_DATA_ONLY command
Parameter 1 : 1-wire communication speed
Parameter 2 : I2C write length
Parameter 3 : I2C write data array
Return : finish flag
---------------------------------------------------------------------*/
u8 gx28e17_write_only_no_stop(u8 spd, u8 wlen, u8 * wdat)
{
u8 st = 0;
u8 wst = 0;
u8 cnt = 0;
uint16_t crc = 0;
u8 i;
// transmit 1-wire packet
onewire_write(spd, DEV_WR_OLY);
onewire_write(spd, wlen);
for( i = 0; i < wlen; i ++)
onewire_write(spd, wdat[i]);
// crc
crc = gx28e17_generate_crc(DEV_WR_OLY, 0, wlen, wdat, 0);
onewire_write(spd, ((u8) crc));
onewire_write(spd, ((u8) (crc >> 8)));
// poll
while(onewire_read_bit(spd) != 0) {
delay_100us();
cnt ++;
if(cnt > POLL_MAX) {
printf("Write only no stop : Exceed query limit.\r\n");
return ERROR;
}
}
// read return bytes
st = onewire_read(spd);
wst = onewire_read(spd);
switch(st) {
case ERR_STA : {
printf("Write only no stop : Invalid start condition.\r\n");
return ERROR;
}
case ERR_ADR : {
printf("Write only no stop : I2C slave device does not acknowledge the I2C address.\r\n");
return ERROR;
}
case ERR_CRC : {
printf("Write only no stop : 1-Wire packet data does not match the corresponding CRC-16.\r\n");
return ERROR;
}
default : break;
}
if(wst == 0)
return DONE; // Done correctly
else {
printf("Write only no stop : Byte %d is not acknowledged by the I2C slave device.\r\n", wst);
return ERROR;
}
}
/*---------------------------------------------------------------------
Function : gx28e17_write_only_with_stop
Description : execute WRITE_DATA_ONLY_WITH_STOP command
Parameter 1 : 1-wire communication speed
Parameter 2 : I2C write length
Parameter 3 : I2C write data array
Return : finish flag
---------------------------------------------------------------------*/
u8 gx28e17_write_only_with_stop(u8 spd, u8 wlen, u8 * wdat)
{
u8 st = 0;
u8 wst = 0;
u8 cnt = 0;
uint16_t crc = 0;
u8 i ;
// transmit 1-wire packet
onewire_write(spd, DEV_WR_OLY_STP);
onewire_write(spd, wlen);
for( i = 0; i < wlen; i ++)
onewire_write(spd, wdat[i]);
// crc
crc = gx28e17_generate_crc(DEV_WR_OLY_STP, 0, wlen, wdat, 0);
onewire_write(spd, ((u8) crc));
onewire_write(spd, ((u8) (crc >> 8)));
// poll
while(onewire_read_bit(spd) != 0) {
delay_100us();
cnt ++;
if(cnt > POLL_MAX) {
printf("Write only with stop : Exceed query limit.\r\n");
return ERROR;
}
}
// read return bytes
st = onewire_read(spd);
wst = onewire_read(spd);
switch(st) {
case ERR_STA : {
printf("Write only with stop : Invalid start condition.\r\n");
return ERROR;
}
case ERR_ADR : {
printf("Write only with stop : I2C slave device does not acknowledge the I2C address.\r\n");
return ERROR;
}
case ERR_CRC : {
printf("Write only with stop : 1-Wire packet data does not match the corresponding CRC-16.\r\n");
return ERROR;
}
default : break;
}
if(wst == 0)
return DONE; // Done correctly
else {
printf("Write only with stop : Byte %d is not acknowledged by the I2C slave device.\r\n", wst);
return ERROR;
}
}
/*---------------------------------------------------------------------
Function : gx28e17_read_with_stop
Description : execute READ_DATA_WITH_STOP command
Parameter 1 : 1-wire communication speed
Parameter 2 : I2C slave address
Parameter 3 : I2C read length
Parameter 4 : I2C read data array
Return : finish flag
---------------------------------------------------------------------*/
u8 gx28e17_read_with_stop(u8 spd, u8 addr, u8 rlen, u8 * rdat)
{
u8 st = 0;
u8 cnt = 0;
uint16_t crc = 0;
u8 i;
// transmit 1-wire packet
onewire_write(spd, DEV_RD_STP);
onewire_write(spd, addr);
onewire_write(spd, rlen);
// crc
crc = gx28e17_generate_crc(DEV_RD_STP, addr, 0, 0, rlen);//读数据的CRC16
onewire_write(spd, ((u8) crc));
onewire_write(spd, ((u8) (crc >> 8)));
// poll
while(onewire_read_bit(spd) != 0) {
delay_100us();
cnt ++;
if(cnt > POLL_MAX) {
printf("Read with stop : Exceed query limit.\r\n");
return ERROR;
}
}
// read return bytes
st = onewire_read(spd);
switch(st) {
case ERR_STA : {
printf("Read with stop : Invalid start condition.\r\n");
return ERROR;
}
case ERR_ADR : {
printf("Read with stop : I2C slave device does not acknowledge the I2C address.\r\n");
return ERROR;
}
case ERR_CRC : {
printf("Read with stop : 1-Wire packet data does not match the corresponding CRC-16.\r\n");
return ERROR;
}
default : break;
}
for( i = 0; i < rlen; i ++)
rdat[i] = onewire_read(spd);
return DONE; // Done correctly
}
/*---------------------------------------------------------------------
Function : gx28e17_write_read_with_stop
Description : execute WRITE_READ_DATA_WITH_STOP command
Parameter 1 : 1-wire communication speed
Parameter 2 : I2C slave address
Parameter 3 : I2C write length
Parameter 4 : I2C write data array
Parameter 5 : I2C read length
Parameter 6 : I2C read data array
Return : finish flag
---------------------------------------------------------------------*/
u8 gx28e17_write_read_with_stop(u8 spd, u8 addr, u8 wlen, u8 * wdat, u8 rlen, u8 * rdat)
{
u8 st = 0;
u8 wst = 0;
u8 cnt = 0;
uint16_t crc = 0;
u8 i;
// transmit 1-wire packet
onewire_write(spd, DEV_WR_RD_STP);
onewire_write(spd, addr);
onewire_write(spd, wlen);
for( i = 0; i < wlen; i ++)
onewire_write(spd, wdat[i]);
onewire_write(spd, rlen);
// crc
crc = gx28e17_generate_crc(DEV_WR_RD_STP, addr, wlen, wdat, rlen);
onewire_write(spd, ((u8) crc));
onewire_write(spd, ((u8) (crc >> 8)));
// poll
while(onewire_read_bit(spd) != 0) {
delay_100us();
cnt ++;
if(cnt > POLL_MAX) {
printf("Write read with stop : Exceed query limit.\r\n");
return ERROR;
}
}
// read return bytes
st = onewire_read(spd);
wst = onewire_read(spd);
switch(st) {
case ERR_STA : {
printf("Write read with stop : Invalid start condition.\r\n");
return ERROR;
}
case ERR_ADR : {
printf("Write read with stop : I2C slave device does not acknowledge the I2C address.\r\n");
return ERROR;
}
case ERR_CRC : {
printf("Write read with stop : 1-Wire packet data does not match the corresponding CRC-16.\r\n");
return ERROR;
}
default : break;
}
if(wst == 0) {
for( i = 0; i < rlen; i ++)
rdat[i] = onewire_read(spd);
return DONE; // Done correctly
}
else {
printf("Write read with stop : Byte %d is not acknowledged by the I2C slave device.\r\n", wst);
return ERROR;
}
}
/*---------------------------------------------------------------------
Function : gx28e17_write_config
Description : execute WRITE_CONFIGURATION command
Parameter 1 : 1-wire communication speed
Parameter 2 : configuration byte
Return : none
---------------------------------------------------------------------*/
void gx28e17_write_config(u8 spd, u8 cfg)
{
onewire_write(spd, DEV_WR_CFG);
onewire_write(spd, cfg);
}
/*---------------------------------------------------------------------
Function : gx28e17_read_config
Description : execute READ_CONFIGURATION command
Parameter 1 : 1-wire communication speed
Return : configuration byte
---------------------------------------------------------------------*/
u8 gx28e17_read_config(u8 spd)
{
u8 cfg = 0;
onewire_write(spd, DEV_RD_CFG);
cfg = onewire_read(spd);
return cfg;
}
/*---------------------------------------------------------------------
Function : gx28e17_enable_sleep
Description : execute ENABLE_SLEEP_MODE command
Parameter 1 : 1-wire communication speed
Return : none
---------------------------------------------------------------------*/
void gx28e17_enable_sleep(u8 spd)
{
onewire_write(spd, DEV_EN_SLP);
}
/*---------------------------------------------------------------------
Function : gx28e17_read_revision
Description : execute READ_DEVICE_REVISION command
Parameter 1 : 1-wire communication speed
Return : revision byte
---------------------------------------------------------------------*/
u8 gx28e17_read_revision(u8 spd)
{
u8 rev = 0;
onewire_write(spd, DEV_RD_REV);
rev = onewire_read(spd);
return rev;
}
/*---------------------------------------------------------------------
Function : gx28e17_generate_crc
Description : generate CRC-16 of 1-wire packet
Parameter 1 : device command
Parameter 2 : I2C slave address
Parameter 3 : I2C write length
Parameter 4 : I2C write data array
Parameter 5 : I2C read length
Return : calculated CRC-16
---------------------------------------------------------------------*/
uint16_t gx28e17_generate_crc(u8 dcmd, u8 addr, u8 wlen, u8 * wdat, u8 rlen)
{
u8 dat_in = 0; // data input bit
u8 crc_in = 0; // crc input bit
uint16_t crc_reg = 0; // crc register
u8 i;
u8 j;
for( i = 0; i < 8; i ++) {
dat_in = (dcmd >> i) & 0x01;
crc_in = ((u8) (crc_reg & 0x0001)) ^ dat_in;
crc_reg = (crc_reg >> 1) ^ ((crc_in != 0) ? CRC_POLY : 0x0000);
}
if((dcmd == DEV_WR_STP) || (dcmd == DEV_WR) || (dcmd == DEV_WR_RD_STP) || (dcmd == DEV_RD_STP)) {
for( i = 0; i < 8; i ++) {
dat_in = (addr >> i) & 0x01;
crc_in = ((u8) (crc_reg & 0x0001)) ^ dat_in;
crc_reg = (crc_reg >> 1) ^ ((crc_in != 0) ? CRC_POLY : 0x0000);
}
}
if((dcmd == DEV_WR_STP) || (dcmd == DEV_WR) || (dcmd == DEV_WR_RD_STP) || (dcmd == DEV_WR_OLY) || (dcmd == DEV_WR_OLY_STP)) {
for( i = 0; i < 8; i ++) {
dat_in = (wlen >> i) & 0x01;
crc_in = ((u8) (crc_reg & 0x0001)) ^ dat_in;
crc_reg = (crc_reg >> 1) ^ ((crc_in != 0) ? CRC_POLY : 0x0000);
}
for( i = 0; i < wlen; i ++) {
for( j = 0; j < 8; j ++) {
dat_in = (wdat[i] >> j) & 0x01;
crc_in = ((u8) (crc_reg & 0x0001)) ^ dat_in;
crc_reg = (crc_reg >> 1) ^ ((crc_in != 0) ? CRC_POLY : 0x0000);
}
}
}
if((dcmd == DEV_WR_RD_STP) || (dcmd == DEV_RD_STP)) {
for( i = 0; i < 8; i ++) {
dat_in = (rlen >> i) & 0x01;
crc_in = ((u8) (crc_reg & 0x0001)) ^ dat_in;
crc_reg = (crc_reg >> 1) ^ ((crc_in != 0) ? CRC_POLY : 0x0000);
}
}
return (~crc_reg);
}
GX28E17.h
#ifndef __GX28E17_HEADER_FILE
#define __GX28E17_HEADER_FILE
// library reference
#include "stdio.h"
#include "stdint.h"
// CRC-16 generator polynomial
#define CRC_POLY 0xA001
// I2C speed definition
#define SPD_SM 0x00
#define SPD_FM 0x01
#define SPD_PM 0x02
// max times of poll
#define POLL_MAX 50
// ROM command definition
#define ROM_READ 0x33
#define ROM_MATCH 0x55
#define ROM_SEARCH 0xF0
#define ROM_SKIP 0xCC
#define ROM_RESUME 0xA5
#define ROM_SKIP_OD 0x3C
#define ROM_MATCH_OD 0x69
// device command definition
#define DEV_WR_STP 0x4B
#define DEV_WR 0x5A
#define DEV_WR_OLY 0x69
#define DEV_WR_OLY_STP 0x78
#define DEV_RD_STP 0x87
#define DEV_WR_RD_STP 0x2D
#define DEV_WR_CFG 0xD2
#define DEV_RD_CFG 0xE1
#define DEV_EN_SLP 0x1E
#define DEV_RD_REV 0xC3
// finish flag
#define ERROR 0x00
#define DONE 0x01
// error definition
#define ERR_STA 0x08
#define ERR_ADR 0x02
#define ERR_CRC 0x01
// function declaration
uint64_t gx28e17_read_rom (uint8_t spd);
uint8_t gx28e17_match_rom (uint8_t spd, uint64_t id);
uint8_t gx28e17_match_rom_od (uint8_t spd, uint64_t id);
uint8_t gx28e17_search_rom (uint8_t spd, uint64_t * ids);
uint8_t gx28e17_skip_rom (uint8_t spd);
uint8_t gx28e17_skip_rom_od (uint8_t spd);
uint8_t gx28e17_resume_rom (uint8_t spd);
uint8_t gx28e17_write_with_stop (uint8_t spd, uint8_t addr, uint8_t wlen, uint8_t * wdat);
uint8_t gx28e17_write_no_stop (uint8_t spd, uint8_t addr, uint8_t wlen, uint8_t * wdat);
uint8_t gx28e17_write_only_no_stop (uint8_t spd, uint8_t wlen, uint8_t * wdat);
uint8_t gx28e17_write_only_with_stop (uint8_t spd, uint8_t wlen, uint8_t * wdat);
uint8_t gx28e17_read_with_stop (uint8_t spd, uint8_t addr, uint8_t rlen, uint8_t * rdat);
uint8_t gx28e17_write_read_with_stop (uint8_t spd, uint8_t addr, uint8_t wlen, uint8_t * wdat, uint8_t rlen, uint8_t * rdat);
void gx28e17_write_config (uint8_t spd, uint8_t cfg);
uint8_t gx28e17_read_config (uint8_t spd);
void gx28e17_enable_sleep (uint8_t spd);
uint8_t gx28e17_read_revision (uint8_t spd);
uint16_t gx28e17_generate_crc (uint8_t dcmd, uint8_t addr, uint8_t wlen, uint8_t * wdat, uint8_t rlen);
void Read_Rom(uint8_t spd);
#endif