CMT2300A是一款国产的FSK、OOK射频收发器
它有专用的上位机便于生成寄存器参数,广泛运用与智能家居、无线控制方面
CMT2300A
CMT2300A 是一款超低功耗,高性能,适用于各种 140 至1020 MHz 无线应用的 OOK,(G)FSK 射频收发器。它是CMOSTEK NextGenRFTM 射频产品线的一部分,这条产品线包含完整的发射器,接收器和收发器。CMT2300A 的高集成度,简化了系统设计中所需的外围物料。高达+20 dBm 及-121dBm 的灵敏度优化了应用的链路性能。它支持多种数据包格式及编解码方式,使得它可以灵活的满足各种应用对不同数据包格式及编解码的需求。另外,CMT2300A 还支持 64-bytex/Rx FIFO, 丰富的 GPIO 及中断配置,Duty-Cycle 运行模式,信道侦听,高精度 RSSI,低电压检测,上电复位,低频时钟输出,手动快速跳频,静噪输出等功能,使得应用设计更加灵活,实现产品差异化设计。CMT2300A 工作于 1.8 V至 3.6 V。当达到-121 dBm 灵敏度的时候仅消耗 8.5 mA 电流,超低功耗接收模式可以进一步降低芯片的接收功耗;以13dBm 输出是仅消耗 23 mA 发射电流。
技术参数
● 频率范围:127至1020MHz
● 调制解调方式:OOK, (G)FSK 和(G)MSK
● 数据率: 0.5 至 300 kbps
● 灵敏度: -121 dBm 2.0kbps, F RF = 433.92 MHz;-111 dBm 50kbps, F RF = 433.92 MHz
● 电压范围:1.8 至 3.6 V
● 发射电流:23 mA @ 13 dBm, 433.92 MHz, FSK;72 mA @ 20 dBm, 433.92 MHz, FSK
● 接收电流:8.5 mA @ 433.92 MHz, FSK
● 支持超低功耗接收模式
● 睡眠电流
300 nA, DutyCycle = OFF 800 nA, DutyCycle = ON
● 3-wire SPI 接口
● 支持直通及包模式
● 可配置包处理机及 64-Byte FIFO
● 不归零,曼切斯特,数据白化编解码
● 支持前向纠错
● 16 管脚 QFN3x3 封装
应用电路
通信协议
MCU 和芯片之间的通讯是通过 4 线 SPI 接口进行的。低有效的 CSB 意味着 MCU 要访问芯片的寄存器。低有效的 FCSB 意 味着 MCU 要访问芯片的 FIFO。CSB 和 FCSB 不能同时为低。SCLK 是串口时钟。对于 MCU 和芯片,数据总是在 SCLK 的下降 沿发射,上升沿采样。SDIO 是一个双向的数据管脚。地址和数据总是从 MSB 开始发送。
读写寄存器时序
如果要发送还是接收数据,数据都要从FIFO当中写入或者读取,所以要写读写FIFO的时序:
底层驱动代码
SPI操作寄存器代码:
/********************************************************************************
**名字: vSpi3WriteByte
**作用: 写入一个字节
*********************************************************************************/
void vSpi3WriteByte(byte dat,bool sda_in)
{
byte bitcnt;
SetFCSB();
OutputSDIO();
SetSDIO();
ClrSDCK();
ClrCSB();
for(bitcnt = 8;bitcnt !=0;bitcnt--)
{
ClrSDCK();
if(dat &0x80)
SetSDIO();
else
ClrSDIO();
#if(SPI3_SPEED !=0)
DelayUs(SPI3_SPEED);
#endif
SetSDCK();
dat <<= 1;
#if(SPI3_SPEED !=0)
DelayUs(SPI3_SPEED);
#endif
}
if(sda_in) //转换到读
{
InputSDIO();
ClrSDCK();
}
else
{
ClrSDCK();
SetSDIO();
}
}
/**********************************************************
**名字: bSpi3ReadByte
**作用: 读一个字节
**********************************************************/
byte bSpi3ReadByte(void)
{
byte RdPara = 0;
byte bitcnt;
ClrSDCK();
InputSDIO();
ClrCSB();
DelayUs(SPI3_SPEED);
DelayUs(SPI3_SPEED);
for(bitcnt=8; bitcnt!=0; bitcnt--)
{
SetSDCK();
RdPara <<= 1;
#if (SPI3_SPEED!=0)
DelayUs(SPI3_SPEED);
#endif
if(SDIO_H())
RdPara |= 0x01;
else
RdPara |= 0x00;
ClrSDCK();
#if (SPI3_SPEED!=0)
DelayUs(SPI3_SPEED);
#endif
}
ClrSDCK();
return(RdPara);
}
/**********************************************************
**名字: vSpi3Write
**作用: 写一个字
**输入: Write word
**输出: none
**********************************************************/
void vSpi3Write(word dat)
{
vSpi3WriteByte(((byte)(dat>>8)&0x7F), FALSE);
vSpi3WriteByte(((byte)dat), FALSE);
SetCSB();
}
/**********************************************************
**名字: vSpi3WriteCmd
**作用: 写命令
**输入: dat byte
**输出: none
**********************************************************/
void vSpi3WriteCmd(byte dat)
{
vSpi3WriteByte((dat&0x7F), FALSE);
SetCSB();
}
/**********************************************************
**名字: vSpi3WriteTreable
**作用: 往寄存器写数据
**输入: byte addr word dat
**输出: none
**********************************************************/
void vSpi3WriteTreable(byte addr, word dat)
{
vSpi3WriteByte((addr&0x7F), FALSE);
vSpi3WriteByte(((byte)(dat>>8)), FALSE);
vSpi3WriteByte(((byte)dat), FALSE);
SetCSB();
}
/**********************************************************
**名字: vSpi3BurstWriteCmd
**作用: 往寄存器连续数据
**输入: byte addr byte ptr[] byte length
**输出: none
**********************************************************/
void vSpi3BurstWriteCmd(byte addr, byte ptr[], byte length)
{
byte i;
vSpi3WriteByte((addr&0x7F), FALSE);
for(i=0; i<length; i++)
vSpi3WriteByte(ptr[i], FALSE);
SetCSB();
}
/**********************************************************
**名字: bSpi3Read
**作用: 读一个字
**输入: readout addresss
**输出: readout byte
**********************************************************/
byte bSpi3Read(byte addr)
{
byte dat;
vSpi3WriteByte((addr|0x80), TRUE);
dat = bSpi3ReadByte();
OutputSDIO();
SetSDIO();
SetCSB();
return(dat);
}
/**********************************************************
**名字: wSpi3ReadTreable
**作用: 读寄存器中的一个字
**输入: readout addresss
**输出: readout word
**********************************************************/
word wSpi3ReadTreable(byte addr)
{
word dat;
vSpi3WriteByte((addr|0x80), TRUE);
dat = bSpi3ReadByte();
dat <<= 8;
dat |= bSpi3ReadByte();
OutputSDIO();
SetSDIO();
SetCSB();
return(dat);
}
/**********************************************************
**名字: vSpi3BurstReadCmd
**作用: 连续读寄存器中的字
**********************************************************/
void vSpi3BurstReadCmd(byte addr, byte ptr[], byte length)
{
byte i;
vSpi3WriteByte((addr|0x80), TRUE);
for(i=0; i<length; i++)
ptr[i] = bSpi3ReadByte();
OutputSDIO();
SetSDIO();
SetCSB();
}
SPI操作FIFO的代码
/**********************************************************
**Name: vSpi3WriteFIFO
**Func: SPI-3 send one byte to FIFO
**Input: one byte buffer
**Output: none
**********************************************************/
void vSpi3WriteFIFO(byte dat)
{
byte bitcnt;
SetCSB();
OutputSDIO();
ClrSDCK();
ClrFCSB();
for(bitcnt=8; bitcnt!=0; bitcnt--)
{
ClrSDCK();
if(dat&0x80)
SetSDIO();
else
ClrSDIO();
#if (SPI3_SPEED!=0)
DelayUs(SPI3_SPEED);
#endif
SetSDCK();
#if (SPI3_SPEED!=0)
DelayUs(SPI3_SPEED);
#endif
dat <<= 1;
}
ClrSDCK();
DelayUs(SPI3_SPEED); //Time-Critical
DelayUs(SPI3_SPEED); //Time-Critical
SetFCSB();
SetSDIO();
DelayUs(SPI3_SPEED); //Time-Critical
DelayUs(SPI3_SPEED); //Time-Critical
}
/**********************************************************
**Name: bSpi3ReadFIFO
**Func: SPI-3 read one byte to FIFO
**Input: none
**Output: one byte buffer
**********************************************************/
byte bSpi3ReadFIFO(void)
{
byte RdPara;
byte bitcnt;
SetCSB();
InputSDIO();
ClrSDCK();
ClrFCSB();
DelayUs(SPI3_SPEED); //Time-Critical
DelayUs(SPI3_SPEED); //Time-Critical
for(bitcnt=8; bitcnt!=0; bitcnt--)
{
SetSDCK();
#if (SPI3_SPEED!=0)
DelayUs(SPI3_SPEED);
#endif
RdPara <<= 1;
if(SDIO_H())
RdPara |= 0x01; //NRZ MSB
else
RdPara |= 0x00; //NRZ MSB
ClrSDCK();
#if (SPI3_SPEED!=0)
DelayUs(SPI3_SPEED);
#endif
}
ClrSDCK();
SetFCSB();
OutputSDIO();
SetSDIO();
return(RdPara);
}
/**********************************************************
**Name: vSpi3BurstWriteFIFO
**Func: burst wirte N byte to FIFO
**Input: array length & head pointer
**Output: none
**********************************************************/
void vSpi3BurstWriteFIFO(byte ptr[], byte length)
{
byte i;
if(length!=0x00)
{
for(i=0;i<length;i++)
vSpi3WriteFIFO(ptr[i]);
}
return;
}
/**********************************************************
**Name: vSpiBurstRead
**Func: burst wirte N byte to FIFO
**Input: array length & head pointer
**Output: none
**********************************************************/
void vSpi3BurstReadFIFO(byte ptr[], byte length)
{
byte i;
if(length!=0)
{
for(i=0;i<length;i++)
ptr[i] = bSpi3ReadFIFO();
}
return;
}
上层配置
这里我利用了官方的HAL库和寄存器文件,CMT2300的寄存器比较多,这里使用官方的上位机直接生成初始化配置头文件
官方上位机:
配置好频段,调制方式导出即可。
顶层API程序使用
笔者已经对底层函数经行了封装,如果改变控制器型号,只需更改my_spi.h里的引脚定义即可。
CMT2300_Init();
Cmt2300_Rx_Init();两个函数初始化接收模式,再调用读取FIFO函数读取——
bGetMessageByFlag(a),a为接收的字符串数据,每次接收后清除一下接收FIFO——vClearFifo(),
CMT2300_Init();
Cmt2300_Tx_Init();两个函数初始化发射模式,再调用写FIFO函数——
bSendMessageByFlag(“Hello”,16),发送“Hello”
笔者不太想用它的中断模式,所以接收读取采用的访问寄存器标识位判断接收或者发送成功。
最后工程链接(在IAR环境下)
源代码地址