有没有想过手机上或曾经的MP3上的收音机可以自己做了?TEA5767帮您圆梦~= ̄ω ̄=
TEA5767是个FM调频立体声收音模块,它可以用I2C或SPI来控制,而且内置75MHz的DSP让收音质量好到飞起(听说的~→_→)
参数规格
- 收音波段:
- FM日本频段 - 76MHz ~ 91MHz
- FM欧美频段 - 87.5MHz ~ 108MHz
- 中频频率: 225kHz
- 调谐系统: PLL
- 灵敏度: 15μA
- 工作电压: 2.5v~5.0v
- 信噪比: 60dB
- 声道: 立体声
- 声道分离度: 30dB
- 晶振:
- 32.768kHz
- 13MHz
电路连接
本例直接采用I2C的连线方式来连接线路,所以线路会很简洁。
电源会容易受到音频放大器电源的干扰,所以要做好隔离。如果音频放大器电源不超过5v时,也可以只在靠近TEA5767的电源端上接入一颗磁环抗干扰。
指令集
我们这里主讲I2C通信方式
I2C地址
- 读地址: 0xC0
- 写地址: 0xC1
写入数据
向TEA5767写入数据时,需要写入一个5个字节长的结构体
struct WriteBuffer {
bool isMute : 1; // 静音 = TRUE,正常 = FALSE
bool isSearchMode : 1; // 搜索模式 = TRUE,放音模式 = FALSE
int prePLL : 6; // 频率PLL值的前6bits
int postPLL : 8; // 频率PLL值的后8bits
int searchDirection : 1; // 向前搜索 = 0,向后搜索 = 1
int stopSearchLevel : 2; // 搜索模式不自动停止 = 0,搜索到微弱信号(信号强度ADC输出5)时中断搜索 = 1,搜索到中等信号(信号强度ADC输出7)时中断搜索 = 2,搜索到强烈信号(信号强度ADC输出10)时中断搜索 = 3
int sideBand : 1; // 上边带接收 = 1,下边带接收 = 0
bool isMono : 1; // 强制单声道输出 = TRUE,立体声输出 = FALSE
bool isMuteLeft : 1; // 立体声合成到右声道 = TRUE,正常声道输出 = FALSE
bool isMuteRight : 1; // 立体声合成到左声道 = TRUE,正常声道输出 = FALSE
int softwarePort1Output : 1; // SWP1作为可编程端口使用,SWP1口输出高电平 = 1,SWP1口输出低电平 = 0
int softwarePort2Output : 1; // SWP2作为可编程端口使用,SWP2口输出高电平 = 1,SWP2口输出低电平=0
bool isStandby : 1; // 待机模式 = TRUE,工作模式 = FALSE
int bandLimit : 1; // 日本调频制式 = 1,欧美调频制式 = 0
int xtal : 1; // 使用外置13MHz晶振 = 1,使用外置32.768kHz晶振 = 0
bool isSoftwareMute : 1; // 开启软件静音 = TRUE,关闭软件静音 = FALSE
bool isHighCutControl : 1; // 开启高频旁路 = TRUE,关闭高频旁路 = FALSE
bool isStereoNoiseCanceling : 1; // 开启立体声噪音消除 = TRUE,关闭立体声噪音消除 = FALSE
bool isEnableSearchIndicator : 1; // 搜索到频道是SWP1输出高电平 = TRUE,SWP1作为可编程端口使用 = FALSE
bool isEnablePLLReference : 1; // 启动6.5MHz锁相环参考频率 = TRUE,关闭6.5MHz锁相环参考频率 = FALSE
int DTC : 1; // 美国制去加重时间75μs = 1,其他国家去加重时间 50μs = 0
};
读取数据
从TEA5767读取数据时,需要使用另一个5个字节长的结构体
struct ReadBuffer {
bool isReady : 1; // 已搜索到频道或搜索到波段边界 = TRUE,否则 = FALSE
bool isBandLimit : 1; // 已搜索到波段边界 = TRUE,否则 = FALSE
int prePLL : 6; // 当前频率的PLL值的前6bits
int postPLL : 8; // 当前频率的PLL值的后8bits
bool isStereo : 1; // 当前信号为立体声 = TRUE,否则 = FALSE
int intermediateFrequency : 7; // 当前中频,正确调谐时在0x31~0x3E之间
int RFADClevel : 4; // ADC输出的RF信号等级
int chipID : 4; // 芯片ID
};
PLL值计算
- 频率转PLL
- 上边带接收:
PLL = (4 * (fRF + fIF)) / fREF - 下边带接收:
PLL = (4 * (fRF - fIF)) / fREF
- 上边带接收:
- PLL转频率
- 上边带接收:
fRF = (PLL * fREF) / 4 - fIF - 下边带接收:
fRF = (PLL * fREF) / 4 + fIF
- 上边带接收:
上式中各参数:
- fRF为当前频率,单位Hz
- fREF为参考频率,如果XTAL使用的是32.758kHz的晶振,那么参考频率取值32768,如果XTAL使用的是13MHz,则参考频率取值50000,单位Hz
- fIF为中频,这里取值为225000,单位Hz
代码实现
因为使用I2C和TEA5767通信,所以需要使用到Arduino内建的Wire库
I2C读写
#include <Wire.h>
#define I2C_CLOCK 400000 // TEA5767的I2C最大速率不超过400kHz
#define ADDRESS 0xC0 // TEA5767的I2C地址为0xC0
ReadBuffer readBuffer;
WriteBuffer writeBuffer;
void setup() {
Wire.begin();
Wire.setClock(I2C_CLOCK);
readDataFromTea5768();
setupWriteBuffer(); // 把对TEA5767的设置写入WriteBuffer
writeDataToTea5767();
}
void unsetup() {
Wire.end();
}
void readDataFromTea5767() {
int bufferSize = sizeof(ReadBuffer);
Wire.requestFrom(ADDRESS, bufferSize);
byte data[bufferSize];
byte counter = 0;
memset(data, 0, bufferSize);
memset(&readBuffer, 0, bufferSize);
while (Wire.available()) {
data[counter] = Wire.read();
counter++;
}
if (counter = bufferSize) {
memcpy(&readBuffer, data, bufferSize);
}
}
void writeDataToTea5767() {
Wire.beginTransmission(ADDRESS);
Wire.write(&writeBuffer, sizeof(WriteBuffer));
Wire.endTransmission();
}