CMT2119A是一款常用的全频段单发无线发射芯片,我们使用外部MCU来控制CMT2119A。
1.配置连接图
我们利用MCU的IO来分别控制CMT2119A的DATA和CLK管脚。
2.2线接口(TWI)
2线接口(Two-Write Interface)包括时间接口CLK和双向数据接口DATA。一个完整的W/R过程有16个时钟周期。前8个周期,DATA是输入口;后8个周期,如果是写过程。DATA是输入口,如果是读过程,DATA是输出口。时序图如下(图来自官方数据手册,侵删)
注意:
1. 时钟应该运行在 1MHz 以下,上升沿发送数据,下降沿采样。
2. 前 8 个周期为读写控制和地址位 A[5:0]. 其中 W/R 为 1 的时候表示读,为 0 的时候表示写。
3. 写操作中 D[7:0]为待写入的数据,读操作中 D[7:0]为从芯片读出的数据。
4. DATA 同时被复用为数据发射的 DATA 脚。
5. TWI_RST (发送 32 个连续 0 和 0x8D00,总共 48 个时钟的数据,如下图所示)可用于复位 TWI电路,以便在遇到未知错误的时候恢复串口功能。 其中下图的命令适用于上升沿启动发射(默认设置)
6. SOFT_RST(发送 0xBD01, 总共 16 个时钟的数据, 如下图所示)可用于复位除了 TWI 电路以
外的芯片其他所有电路,整个复位时间约需 1 ms。
7. 方便起见,本文用 TWI_RDREG 表示 TWI 读操作,用 TWI_WRREG 表示 TWI 写操作。
a) TWI_RDREG(XX, YY)为发送 8b’ 11xx xxxx 读出 yyyy yyyy,其中 xx xxxx 为待读地址,范围 0x00 到 0x3F; yyyy yyyy 为读出值,范围为 0x00 到 0xFF。
b) TWI_WRREG(XX, ZZ)为发送 16’ 10xx xxxx zzzz zzzz,其中例如 xx xxxx 为待写地址,范围 0x00 到 0x3F; zzzz zzzz 为待写值,范围为 0x00 到 0xFF。
c) 例如:
i. 从地址 0x01 读取数据表示为 TWI_RDREG(0x1, DAT), 其中 DAT 表示从地址 0x1读出的数据。
ii. 对地址 0x2 写入数据 0xAA 表示为 TWI_WRREG(0x2, 0xAA)。
iii. SOFT_RST 可表示为 TWI_WRREG(0x3D, 0x01)。
8. DATA 是一个双向数据口,在读操作的后 8 个周期会被切换为输出口。为了避免潜在的电平冲突,当 DATA 切换为输出口的时候,主控(Master)相应的驱动端口要及时切换为输入口。
3.配置流程
4.示例程序
#define CMT2119A_WR_CMD (unsigned char )0x80
#define CMT2119A_RD_CMD (unsigned char )0xC0
void TWI_WrByte(unsigned char SendByte)
{
unsigned char i = 0;
for (i = 0; i < 8; i++)
{
TWI_SCK_H();
if (SendByte & 0x80) //MSB
TWI_SDA_H();
else
TWI_SDA_L();
SendByte <<= 1;
delay10Us(1);
TWI_SCK_L();
delay10Us(1);
}
}
unsigned char TWI_RdByte(void)
{
unsigned char i;
unsigned char ReceiveByte = 0xff;
for (i = 0; i < 8; i++)
{
TWI_SCK_H();
ReceiveByte <<= 1;
delay10Us(1);
TWI_SCK_L();
if (TWI_SDA_read())
ReceiveByte |= 0x01;
else
ReceiveByte &= 0xFE;
delay10Us(1);
}
return ReceiveByte;
}
unsigned char TWI_RDREG(unsigned char ReadAddress, unsigned char xdata * pData)
{
ReadAddress |= CMT211XA_RD_CMD;
TWI_SDA_H();
TWI_SDA_PUSH_PULL();
TWI_SCK_H();
TWI_SCK_PUSH_PULL();
TWI_WrByte(ReadAddress);
TWI_SDA_H();
TWI_SDA_OPEN_DRAIN();
*pData = TWI_RdByte();
TWI_SDA_H();
TWI_SDA_OPEN_DRAIN();
TWI_SCK_H();
TWI_SCK_OPEN_DRAIN();
return 1;
}
unsigned char TWI_WRREG(unsigned char WriteAddress, unsigned char SendByte)
{
WriteAddress |= CMT211XA_WR_CMD;
//TWI_SDA_PUSH_PULL();
TWI_SDA_H();
TWI_SDA_PUSH_PULL();
TWI_SCK_H();
TWI_SCK_PUSH_PULL();
TWI_WrByte(WriteAddress);
TWI_WrByte(SendByte);
TWI_SDA_H();
TWI_SDA_OPEN_DRAIN();
TWI_SCK_H();
TWI_SCK_OPEN_DRAIN();
return 1;
}
void TWI_RST(void)
{
TWI_SDA_H();
TWI_SDA_PUSH_PULL();
TWI_SCK_H();
TWI_SCK_PUSH_PULL();
// DATA pin low for 32 clock cycles and clocking in 0x8D00
TWI_WrByte(0x00);
TWI_WrByte(0x00);
TWI_WrByte(0x00);
TWI_WrByte(0x00);
TWI_WrByte(0x8D);
TWI_WrByte(0x00);
TWI_SCK_H();
TWI_SCK_OPEN_DRAIN();
TWI_SDA_H();
TWI_SDA_OPEN_DRAIN();
}
void TWI_OFF(void)
{
TWI_SDA_H();
TWI_SDA_PUSH_PULL();
TWI_SCK_H();
TWI_SCK_PUSH_PULL();
TWI_WrByte(0x8D);
TWI_WrByte(0x02);
TWI_SCK_H();
TWI_SCK_OPEN_DRAIN();
TWI_SDA_H();
TWI_SDA_OPEN_DRAIN();
}
void SOFT_RST(void)
{
TWI_SDA_L();
TWI_SDA_PUSH_PULL();
TWI_SCK_H();
TWI_SCK_PUSH_PULL();
TWI_WrByte(0xBD);
TWI_WrByte(0x01);
TWI_SCK_H();
TWI_SCK_OPEN_DRAIN();
TWI_SDA_H();
TWI_SDA_OPEN_DRAIN();
}
void FREQUENCY_CONFIG(void)
{
unsigned char low_data,high_data;
unsigned char regaddr;
unsigned short regdat;
unsigned char low_rd,high_rd;
// step1
TWI_RST();
// step2
SOFT_RST();
delayMs(1);
// step3
TWI_WRREG(0x02, 0x78);
// step4
TWI_WRREG(0x2F, 0x80);
TWI_WRREG(0x35, 0xCA);
TWI_WRREG(0x36, 0xEB);
TWI_WRREG(0x37, 0x37);
TWI_WRREG(0x38, 0x82);
TWI_WRREG(0x12, 0x10);
TWI_WRREG(0x12, 0x00);
TWI_WRREG(0x24, 0x07);
TWI_WRREG(0x1D, 0x20);
// step5
regaddr=0x07; // set frequency reg addr
regdat=0xB81F; // set frequency reg data
TWI_WRREG(0x18, regaddr);
low_data=regdat%0x100;
high_data=regdat/0x100;
TWI_WRREG(0x19,low_data);
TWI_WRREG(0x1A,high_data);
TWI_WRREG(0x25, 0x01);
// read register
TWI_RDREG(0x1B,&low_rd);
TWI_RDREG(0x1C,&high_rd);
//if want set more reg, repeat step5
// step6
TWI_WRREG(0x0D, 0x02);
// send data here
}