📄 tuner.c
字号:
#include "reg52.h"
#include "intrins.h"
#include "..\..\inc\globedef.h"
#include "..\..\inc\keydef.h"
#include "..\..\inc\keyproc.h"
#include "..\..\inc\vfddef.h"
#include "..\..\inc\delay.h"
#include "..\..\inc\i2c.h"
#include "..\..\inc\tuner.h"
/************************************************
* MCU向TUNER发送一个字节数据 *
* 输入: ucData 要发送的无符号字节 *
* 无返回值 *
* 注意:是低位选发送 *
************************************************/
void SendByte_ToTuner(BYTE ucData)
{
BYTE i;
for(i=0; i<8; i++)
{
CLEAR_TUNER_CLK;
if(ucData & 0x01)
SET_TUNER_DATA;
else
CLEAR_TUNER_DATA;
Delay5US();
SET_TUNER_CLK; //上升沿发送数据
ucData >>= 1;
}
}
/************************************************
* MPU自TUNER读一个字节数据职 *
* 无输入值 *
* 返回值读入的无符号字节 *
* 注意:是高位先读入 *
************************************************/
BYTE ReadByte_FromTuner(void)
{
BYTE i, ucData = 0;
//TRI_TUNER_DATA;
for(i=0; i<8; i++)
{
CLEAR_TUNER_CLK;
Delay5US();
SET_TUNER_CLK;
Delay5US();
ucData <<= 1;
if(TUNER_DATA_HIGH)
ucData++; //高电平置1
}
return(ucData);
}
/****************************************************
* MCU向TUNER指定地址发送多个字节数据 *
* 输入: *ucData 要发送的无符号字节数据组 *
* unN 发送数据个数 *
* unAddr CCB地址 *
* 无返回值 *
* 注意:是低位先发送 *
****************************************************/
void SendString_ToTuner(BYTE ucAddr, BYTE ucN, BYTE *ucData)
{
BYTE i;
CLEAR_TUNER_CS;
SendByte_ToTuner(ucAddr);
SET_TUNER_CS;
for(i=0; i<ucN; i++)
SendByte_ToTuner(ucData[i]); //发送数据
CLEAR_TUNER_CS;
}
/************************************************
* MPU自CCB指定地址读多个字节数据 *
* 输入: unN 要求读入数据个数 *
* unAddr CCB地址 *
* 返回值 *ucData所读入的无符号字节数据组 *
* 注意:每个字节的高位先读入 *
************************************************/
void ReadString_FromTuner(BYTE ucAddr, BYTE ucN, BYTE *ucData)
{
BYTE i;
CLEAR_TUNER_CS; //准备发送CCB地址
SendByte_ToTuner(ucAddr); //发送CCB地址
SET_TUNER_CS;
for(i=0; i<ucN; i++)
ucData[i] = ReadByte_FromTuner(); //接收数据
CLEAR_TUNER_CS; //结束
}
/****************************************
* 收音模块的初始化 *
ucRadioControl[0] 的各位代表值
ucRadioControl[0].7 = STSW; = 0, MONO; =1, stereo
ucRadioControl[0].6 = BDSW1; = 0, AM; =1, FM
ucRadioControl[0].5 = B02;
ucRadioControl[0].4 = IFSW; =1, MUTED, =0 RECEIVED
ucRadioControl[0].3 = B01;
ucRadioControl[0].2 = 0;
ucRadioControl[0].1 = 1;
ucRadioControl[0].0 = 0;
*******************************************/
void RadioInit(void)
{
if(FM_AM_Select == FM_MODE)
{
//FM state
ucRadioControl[0]=0xc2;//STEREO, FM MODE
//设置DEAD BAND WIDTH 为DZC, 检测到立体声Tuner_DATA_OUT变低
ucRadioControl[1]=0x8c;
//一般操做模式,设置中频计数的计算时间为32ms和等待时间为4ms左右
ucRadioControl[2]=0x17;//
}
else
{
//AM state
ucRadioControl[0]=0x02;//MONO, AM mode
ucRadioControl[1]=0x8c;//81;
ucRadioControl[2]=0x17;//12;
}
SendString_ToTuner(IN2_MODE,3,ucRadioControl);
}
/****************************************
*收音头静音 *
****************************************/
void RadioMute(void)
{
if(FM_AM_Select == FM_MODE)
{
//FM state ucRadioControl[0].4的IFSW位控制静音
ucRadioControl[0]=0xd2;//0a;
ucRadioControl[1]=0x8c;//80;
ucRadioControl[2]=0x17;//12;
}
else
{
//AM state
ucRadioControl[0]=0x12;//62;
ucRadioControl[1]=0x8c;//81;
ucRadioControl[2]=0x17;//12;
}
SendString_ToTuner(IN2_MODE,3,ucRadioControl);
}
/****************************************
*STRERO/MONO *
****************************************/
void SetRadioMono(void)
{
if(FM_AM_Select == FM_MODE)
{
//ucRadioControl[0].7控制立体声或者单声道
ucRadioControl[0]=0x42;//aa;
ucRadioControl[1]=0x8c;//80;
ucRadioControl[2]=0x17;//12;
SendString_ToTuner(IN2_MODE,3,ucRadioControl);
}
}
/****************************************
*收音头打开声音, 其实是针对FM的操做 *
****************************************/
void RadioOpen(void)
{
if(Mono_Stereo_Select == Tuner_MONO)
SetRadioMono();
else
RadioInit();
}
/****************************************
* 写入收音频率值 (IN1 Mode) *
* 输入:uiFreq 要写入的频率值 *
****************************************/
void RadioFreq(WORD uiFreq)
{
if(FM_AM_Select == FM_MODE)
{
//设置参考频率为25KHZ, 设置PLL的divisor = P[15:0] * 2;
//reset中频计数
ucRadioControl[2]=0x2a;
}
else
{
//设置参考频率为 5KHZ,设置PLL的divisor = P[15:4];
ucRadioControl[2]=0x98;
uiFreq<<=4;//移位是因为P[3:0]是被忽略的
}
ucRadioControl[0]=(BYTE)(uiFreq&0x00ff);
ucRadioControl[1]=(BYTE)((uiFreq&0xff00)>>8);
SendString_ToTuner(IN1_MODE,3,ucRadioControl); //写入CCB总线
DelayX1ms(60);
//GTE = 1; START中频计数
ucRadioControl[2]|=0x04;
SendString_ToTuner(IN1_MODE,3,ucRadioControl);
}
/****************************************
*读中频计数和状态 *
*返回值为状态字节 *
*中频计数值去后4个BIT保存在uiIFCount *
****************************************/
void RadioCountIF(void)
{
//BYTE TEMP[3];
ReadString_FromTuner(OUT_MODE,3,ucRadioControl); //自CCB上读3个字节
//计算读出的中频值,忽略低4个BIT
//最高位STINT =1代表立体声, =0代表单声道
Mono_Stereo_Select = ucRadioControl[0] & 0x80;
if(Mono_Stereo_Select != 0)
Mono_Stereo_Select = Tuner_STEREO;
else
Mono_Stereo_Select = Tuner_MONO;
Mono_Stereo_Select = ((ucRadioControl[0] & 0x80) >> 7);
uiIFCount = (WORD)(ucRadioControl[2] >> 4) + (WORD)(ucRadioControl[1] << 4)
+ (WORD)(ucRadioControl[0] << 12);
}
/****************************************
*判断是否锁到台 *
*返回:TRUE 锁到 *
* FALSE 未锁到 *
****************************************/
BYTE RadioLock(void)
{
if(Wait_Lock_40ms < Wait_Timer_Out)
return 0xFF;
else
{
Wait_Lock_40ms = 0;
RadioCountIF();
if( FM_AM_Select == FM_MODE )
{
//FM,中频频率为10.7MHz在32ms内的计数值应为0x53980
if((uiIFCount>=(FMIFS-FMDELTA))&&(uiIFCount<=(FMIFS+FMDELTA)))
{
return TRUE;
}
}
else
{
//AM,中频是450KHZ,在32MS内的计数为0x3840
if((uiIFCount>=(AMIFS-AMDELTA))&&(uiIFCount<=(AMIFS+AMDELTA)))
{
return TRUE;
}
}
return FALSE;
}
}
/********************************************
* 频率加1,如果超过范围,则自动从最小开始 *
* 返回当前频率值 *
********************************************/
void RadioUp(void)
{
//WORD idata uiFreqTemp;
//当前频率加1个步长
if(FM_AM_Select == FM_MODE )
{
//加50KHz
if(DeltFMFreq >= (FMFREQMAX - FMFREQSTEP))
{
DeltFMFreq = 0;
if(Auto_Scan_Enable == 1)
Auto_Is_Reach = 1;
}
else
DeltFMFreq += FMFREQSTEP; //
Current_Freq=(WORD)DeltFMFreq+(WORD)FMFREQMIN;
}
else
{
if(DeltAMFreq >= (AMFREQMAX-AMFREQSTEP))
{
DeltAMFreq = 0;
if(Auto_Scan_Enable == 1)
Auto_Is_Reach = 1;
}
else
DeltAMFreq += AMFREQSTEP;
Current_Freq=(WORD)DeltAMFreq+AMFREQMIN;
}
//RadioFreq(Current_Freq);
//return Current_Freq;
}
/********************************************
* 频率减1,如果超过范围,则自动从最大开始 *
* 返回当前频率 *
********************************************/
void RadioDown(void)
{
//WORD uiFreq;
//当前频率减1个步长
if(FM_AM_Select == FM_MODE)
{
if(DeltFMFreq < FMFREQSTEP) //如果当前的偏差小于步长, 那么设置最大值
DeltFMFreq = FMFREQMAX;
else
DeltFMFreq -= FMFREQSTEP;
Current_Freq=FMFREQMIN+DeltFMFreq;
}
else
{
if(DeltAMFreq < AMFREQSTEP)
DeltAMFreq = AMFREQMAX;
else
DeltAMFreq -= AMFREQSTEP;
Current_Freq=AMFREQMIN+(WORD)DeltAMFreq;
}
}
/*****************************************************************
* TUNER 处理函数 *
包括全自动扫描, 手动向下扫描, 手动向上扫描, 记忆存储
数字键的处理,
****************************************************************/
void Tuner_Proc(void)
{
BYTE Lock_Flag;
BYTE TEMP1;
BYTE TEMP2;
if(Auto_Scan_Enable == Auto_Scan_Go)
{
//刚开始第一次自动扫描扫描
if(Auto_Scan_Start == 0)
{
if(FM_AM_Select == FM_MODE)
Current_Freq = FMFREQMIN; //在FM模式,置FM的频率为最小值
else
Current_Freq = AMFREQMIN; //AM模式的频率最小值
DeltFMFreq = 0; //FM的增量为0
DeltAMFreq = 0; //AM的增量为0
RadioMute(); //RADIO静音
RadioFreq(Current_Freq); //送当前频率到TUNER PLL
Auto_Scan_Start = 1; //自动扫描起始标志位置位
Scan_Channel = 0;
Wait_Lock_40ms = Wait_Timer_Start; //
}
else
{
Lock_Flag = RadioLock(); //看是否到达中频锁定时间
if( Lock_Flag != Timer_Not_Reach)
{
if(Lock_Flag == TRUE)
{
//如果有台锁定,那么保存台值,继续下一个扫描
//Scan_Channel,扫描的台的频率
if(FM_AM_Select == FM_MODE)
{
TEMP1 = FM_Start + (Scan_Channel * 2);
I2C_PutByte(A24C02, TEMP1, DeltFMFreq & 0xFF );
DelayX1ms(2);
TEMP2 = (DeltFMFreq & 0xFF00) >> 8;
I2C_PutByte(A24C02, TEMP1 + 1, TEMP2);
}
else
{
I2C_PutByte(A24C02, (AM_Start + Scan_Channel - 1), (BYTE)(DeltAMFreq & 0xFF) );
}
Scan_Channel++;
}
//如果还没有到频率的最大值和存储的台没有超过30,那么继续扫描
if((Auto_Is_Reach == 0)&& (Scan_Channel < 30))
{
RadioMute(); //中频静音
RadioUp(); //频率加加
RadioFreq(Current_Freq); //设置改变后的频率
Wait_Lock_40ms = Wait_Timer_Start;
}
else
{
//假如已经搜索到最大频率或者存储的台超过30
if(FM_AM_Select == FM_MODE)
{
//从24C02中取出第一个存储的频率
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -