📄 tea5767.c
字号:
/*
TEA5767驱动程序:
unsigned char TEA5767_INTI(void); //初始化TWI
unsigned char set5767(void); //写TEA5767寄存器
void read5767(void); //读TEA5767寄存器
void set_frequency(unsigned long frequency) //设定频率 (输入设定频率)
void frequency_UP_DOWN(unsigned char mode) //当前频率+/- 步进 0.1MHz
正点原子@SCUT
V1.2
/////////////////////////////////////////////////////////////////////////////////////////////////
TEA5767 FEATURES
FM band:
US/Europe (87.5 to 108 MHz)
Japanese (76 to 91MHz)
TEA5767 GENERAL DESCRIPTION
The TEA5767HN is a single-chip electronically tuned FM
stereo radio for low-voltage application with fully integrated
IF selectivity and demodulation. The radio is completely
adjustment-free and only requires a minimum of small and
low cost external components. The radio can be tuned to
the European, US and Japanese FM bands.
*/
#include "myiic.h"
#define TWINT 7
#define TWSTA 5
#define TWEN 2
#define TWSTO 4
#define TWEA 6
#define START 0x08 //TWI 状态指示
#define MT_SLA_ACK 0x18
#define MT_DATA_ACK 0x28
#define LowestFM_US 87500 //87.5MHz
#define HighestFM_US 108000//108Mhz
#define LowestFM_JA 76000 //76MHz
#define HighestFM_JA 91000 //91Mhz
#define LOW_US_H 0x69
#define LOW_US_L 0xD8 //87.5 &108 MHz
#define HIG_US_H 0x73
#define HIG_US_L 0x9E //PLL FOR US band
#define LOW_JA_H 0x64
#define LOW_JA_L 0x5C //76 & 91 MHz
#define HIG_JA_H 0x6B
#define HIG_JA_L 0x83 //PLL FOR JA band
#define SLA_W 0xC0 //write TEA5767 地址
#define SLA_R 0xC1 //read
#define JPS 0X32 //日本模式
#define USA 0X12 //美国模式
unsigned char TEA5767_INTI(void); //初始化TWI
unsigned char set5767(void); //写TEA5767寄存器
void read5767(void); //读TEA5767寄存器,并转化到相关变量
u8 search_station(unsigned char UP_DOWN);
void set_frequency(unsigned long frequency);
void frequency_UP_DOWN(unsigned char mode);
u8 senddata[5] ;//发送数据缓冲
u8 readdata[5] ;//接收数据缓冲
u8 RSIGNAL_STATUS=0;//信号状态 最高位:立体声标志,高三位:停止搜索的信号强度。低四位:信号强度
u8 JPUS;//欧美或者日本频段选择 0x12欧美 0x02日本
u8 sCh_Num=0; //搜索到的最大的电台个数
u8 sCh_Cho=0; //当前选择的电台号码 CHx
unsigned long Ch_Value[30]; //存储电台
unsigned long frequency_set=0;//Khz 从寄存器里面读出的 频率值
unsigned long set_freq=0;//自己设定的 最终频率
/*
可显示 当前频率
是否立体声
ADC电压强度(信号强度)
搜到电台
频率到达最大/最小值指示
*/
//////////////////////////////////////////////////////////////////
//设置TEA5767的寄存器
//CHECK OK 09/05/25
unsigned char set5767(void)
{
u8 i = 0;
if(RSIGNAL_STATUS&0x80)senddata[2]&=0xf7;//bit3=0,立体声
else senddata[2]|=0x08;//bit3=1,单声道
IIC_Start(); //发送起始信号
IIC_Send_Byte(SLA_W);//send address 写TEA5767的地址
IIC_Wait_Ack();
for (i=0;i<5;i++ )//连续发送5个字节
{
IIC_Send_Byte(senddata[i]);
IIC_Wait_Ack();
}
IIC_Stop();
return 1;//发送成功
}
//读tea5767的寄存器,并把相关参数计算出来
//CHECK OK 09/05/25
void read5767(void)
{
unsigned long nPLL =0;//PLL
u8 tbTmp1;//PLL7~PLL0
u8 tbTmp2;//PLL13~PLL8
u8 i = 0;
IIC_Start(); //发送起始信号
IIC_Send_Byte(SLA_R);// send address 发送地址&读
IIC_Wait_Ack();
for (i=0;i<5;i++ ) //接收5个字节
{
readdata[i]=IIC_Read_Byte(1);// read data
}
IIC_Stop();
//计算得到的结果值,具体到各个变量
tbTmp1=readdata[1];//PLL7~PLL0
tbTmp2=readdata[0];//PLL13~PLL8
tbTmp2&=0x3f;
nPLL=(unsigned long)tbTmp2*256+tbTmp1;//pll的数值 (0~8192)
if(senddata[2]&0x10)
frequency_set =(unsigned long)(nPLL*(float)8.192-225);
else
frequency_set =(unsigned long)(nPLL*(float)8.192+225);
RSIGNAL_STATUS&=0xf0;
RSIGNAL_STATUS|=(readdata[3]&0xF0)>>4;//得到adc值的大小
}
//初始化tea5767
//CHECK OK 09/05/25
unsigned char TEA5767_INTI(void)
{
//load 88.3MHz BIT6用于选择是否搜台模式1是/0否 0x29
//bit6 1搜索模式
//BIT7 MUTE1/NO MUTE0 PLL13...8
senddata[1] = 0xFF; // PLL7...0 F1
senddata[2] = 0x60; //bit7 0用于选择向上1/向下搜台0
//bit3 MS:1单声道 0:立体声
//bit 6&5ADC选择 0x20 ADC 5
//0x40 ADC 7
//0x60 ADC 10
senddata[3] = JPUS; //bit5 用于选择日本1/欧洲模式0
senddata[4] = 0x00; //不用改
return (set5767());
}
//自动搜索,并保存
//CHECK OK 09/05/25
void auto_search(void)
{
u8 ts;
if(senddata[3]&0x20)set_freq=LowestFM_JA;//设置到日本频段的最低端
else set_freq=LowestFM_US;//设置到美国频段的最低端
sCh_Num=0;//初始化为0
sCh_Cho=0;
while(1)//一旦执行,不可中断
{
ts=search_station(1);
if(ts==2) //搜索到一个电台
{
if(sCh_Num<30)sCh_Num++;//频道上升
sCh_Cho=sCh_Num-1;
Ch_Value[sCh_Cho]=set_freq;//保存电台
}
else if(ts==1)//搜索结束
{
if(sCh_Num==0)//没有搜索到任何电台,还原到初始化
{
if(JPUS==JPS)set_freq=76000;
else set_freq=87500;
}else //搜索到了电台
{
sCh_Cho=0;//回到第一个频道
set_freq=Ch_Value[sCh_Cho];
}
set_frequency(set_freq);//频段跳到指定点
Radio_Freq_Show(set_freq);//显示频率值,同时做延时用
//Signal_CH_Show();//显示信号强度,频道值
return;//搜索结束
}
}
}
//手动设置频率
//同时显示频率值
//CHECK OK 09/05/25
void set_frequency(unsigned long frequency) //设定频率KHz
{
unsigned int PLL;
if(senddata[2]&0x10)//根据充电电流HLSI计算
PLL=(unsigned int)((float)((frequency+225)*4)/(float)32.768);
else
PLL=(unsigned int)((float)((frequency-225)*4)/(float)32.768);
senddata[0]=PLL/256;
senddata[1]=PLL%256;
senddata[0]&=0x3F;
senddata[3] = JPUS;//bit5 用于选择日本1/欧洲模式0
set5767();
delay_ms(20);//等待设置生效
read5767(); //读取数据
}
//从当前频率向上或者向下搜台
//CHECK OK 09/05/25
u8 search_station(unsigned char UP_DOWN) //自动搜台程序
{
u8 mark=0; //标志位
u8 tempadc=0; //暂存adc值
u8 times=0; //偏移限制
u8 signal_adc;
u32 best_freq=0; //保存最好的频率
read5767(); //先读状态
if(UP_DOWN)set_freq+=200; //预偏移
else set_freq-=200;
while(1)
{
//if(READY&&key_process()==QUIT)return;//中断搜索
if(UP_DOWN)set_freq+=50;
else set_freq-=50;
if(senddata[3]&0x20) //日本频带
{
if(set_freq<LowestFM_JA) //到达最低频率
{
set_freq=HighestFM_JA;
return 0;//到达了最高频率
}
else if(set_freq>HighestFM_JA) //到达最高频率
{
set_freq=LowestFM_JA;
return 1;//到达了最低频率
}
}
else //美国频带
{
if(set_freq<LowestFM_US) //到达最低频率
{
set_freq=HighestFM_US;
return 0;
}
else if(set_freq>HighestFM_US)//到达最高频率
{
set_freq=LowestFM_US;
return 1;
}
}
set_frequency(set_freq);
Radio_Freq_Show(set_freq);//显示频率值,同时做延时用
//Signal_CH_Show();//显示信号强度,频道值
signal_adc=RSIGNAL_STATUS&0x0f;
if(signal_adc>=(((RSIGNAL_STATUS>>4)&0x07)+7)&&signal_adc>=tempadc)//得到强信号
{
tempadc=signal_adc;//记录最大值
best_freq=set_freq;//记录此次最好的频率
mark=1;
}
if(mark)times++; //统计次数增加
if(times>4&&signal_adc<=(((RSIGNAL_STATUS>>4)&0x07)+7))//有记录了,并且信号下降
{
set_frequency(best_freq);
set_freq=best_freq;
return 2;//搜索到一个台
}
}
}
// 手动找台 ,mode=1,+0.1MHz;mode=0:-0.1MHz
//CHECK OK 09/05/25
void frequency_UP_DOWN(unsigned char mode)// // 步进 0.1MHz
{
if(mode)set_freq+=100; //向上0.1MHz
else set_freq-=100; //向下0.1MHz
if(senddata[3]&0x20) //日本频带
{
if(set_freq<LowestFM_JA) //到达最低频率
set_freq=HighestFM_JA;
else if(set_freq>HighestFM_JA) //到达最高频率
set_freq=LowestFM_JA;
}
else //美国频带
{
if(set_freq<LowestFM_US) //到达最低频率
set_freq=HighestFM_US;
else if(set_freq>HighestFM_US) //到达最高频率
set_freq=LowestFM_US;
}
set_frequency(set_freq);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -