|
发表于 2006-10-9 09:07:00
|
显示全部楼层
首先声明这个程序是经过我验证的,我现在正在使用这段程序,我用的是AVR M16 单片机,参考一下这个程序,这个程序是可以自动搜索的
/*
****************************************************************************
Copyright 2001 Philips Semiconductors Limited,
35/F,Panglin Plaza, No. 2002,Jia BIn Road,Luo Hu District,Shenzhen 518001, PRC.
All rights are reserved. Reproduction in whole or in part is prohibited
without the prior written consent of the copyright owner.
COMPANY CONFIDENTIAL
***************************************************************************
Filename : Tuner.c
Rev Date Author
____________________________________________________________________________
1.0 2002/01/13 Tenon Mao
TEA5767 basic control
*/
#define XTAL32K
#define LowestFM 87500 //87.5MHz for EUR only for USA 87.9M
#define HighestFM 108000 //108.Mhz
#define InitVCO 98000 // 98.00 MHz for reset Freq
#define STEP 100 //setp size =100KHz.
#define AST_STEP 200 //200
#define MAX_STATION 20
#define TUNER_DELAY 250000 //250MS
#ifdef XTAL32K
#define REFERENCE_FREQ 32.768
#else
#define REFERENCE_FREQ 50.000
#endif
/**********************
* INCLUDE FILES *
**********************/
/* Standard include files */
/* Project include files */
#include "global.h"
#include "tuner.h"
#include "util.h"
#include "lcd.h"
#include "key.h"
/**********************
* LOCAL TYPEDEFS *
**********************/
/**********************
* EXPORTED DATA *
**********************/
BYTE data SearchLevel=3;
BYTE idata WriteDataWord[5]; // write tea5767H dataword
BYTE idata ReadDataWord[5]; // read tea5767H dataword
unsigned long idata TunerStation[20]; //save radio station FM Value HEX format
///For assembly data
BIT data FlagMute = False; // flag to Mute R&L
BIT data FlagSearch = False; // flag to search or preset mode
BIT data FlagSearchtUp =True; // flag for search direction
BYTE data FlagLevel =2; // flag for current search level
BIT data FlagHighInjection=False;
BIT data FlagMono = False; // flag to force mono
//Mute L
//Mute R
//SWPORT1 for GPIO out
BIT data FlagSWPORT2=Low; // flag for level of pin15
//standy_by
//Japan or ther area
//XTAL selecton 1 for 32k
BIT data FlagSoftMute = True;//False; // flag to force mono
//HCC
//SNC
BIT data FlagSWPORT1=True; // 1= confige as indication of found!!
//PLL selection 0
//Deem 1.
BYTE data NowStation=0;
BYTE data Max_Station=0;
unsigned long gdwSearchedVCO; // vco frequency after search command
unsigned long gdwPresetVCO=89800; // target vco frequency for Preset
unsigned long gdwWorkingVCO; // displayed vco frequency
BIT data NotFound = True;
BIT data BandLimit = False; // Indicate the end of band
//unsigned char TunerSearchTimer; //Timeout for serach
/**********************
* STATIC DATA *
**********************/
/**********************
* LOCAL MACROS *
**********************/
/**********************
* FUNCTION PROTOTYPES *
**********************/
/****************************************************************************/
/* Command Delay */
/****************************************************************************/
void CMD_Delay(BYTE i)
{
for (; i!=0; i--) ;
}
void CMD_CheckHighSCL()
{
I2cSCL = 1;
}
void CMD_SendStart()
{
I2cSCL = 1;
CMD_Delay(CMD_DELAY);
I2cSDA = 0;
CMD_Delay(CMD_DELAY);
I2cSCL = 0;
CMD_Delay(CMD_DELAY);
}
void CMD_SendStop()
{
I2cSDA = 0;
CMD_CheckHighSCL();
CMD_Delay(CMD_DELAY);
I2cSDA = 1;
CMD_Delay(CMD_DELAY);
}
BYTE CMD_SendByte(BYTE bByte)
{
BYTE i;
BIT Acknowledge=1;
for(i=0;i<8;i++)
{
if(bByte&0x80)
I2cSDA=1;
else
I2cSDA=0;
bByte<<=1;
CMD_Delay(CMD_DELAY);
CMD_CheckHighSCL();
I2cSCL =0;
}
I2cSDA=1;
I2cSCL=1;
CMD_Delay(CMD_DELAY);
if (I2cSDA) Acknowledge=0;
I2cSCL=0;
CMD_Delay(CMD_DELAY);
return Acknowledge;
}
BYTE CMD_GetByte(BYTE Acknowledge)
{
BYTE i,bByte=0, bMask=0x80;
for(i=0;i<8;i++)
{
CMD_Delay(CMD_DELAY);
I2cSCL=1;
if(I2cSDA)bByte|=bMask;
bMask >>= 1;
I2cSCL =0;
}
I2cSDA =(Acknowledge)?1:0;
CMD_CheckHighSCL();
CMD_Delay(CMD_DELAY);
I2cSCL =0;
I2cSDA =1;
CMD_Delay(CMD_DELAY);
return bByte;
}
//////////////////////////////////////////////
void WriteSTR()
{
BYTE i;
EA=0;
CMD_SendStart();
if (CMD_SendByte(0x0c0)) //chip addr of write data to driver
{
for (i=0; i<5; i++)
{
if (!CMD_SendByte(WriteDataWord)) //0 err
{
break;
}
}
}
CMD_SendStop(); //???
EA=1;
CMD_Delay(CMD_DELAY);
CMD_Delay(CMD_DELAY);
}
Byte SearchRead1=0; //for test only!!!
Byte SearchRead2=0;
Byte SearchRead3=0;
Byte SearchRead4=0;
Byte SearchRead5=0;
void ReadSTR() //get datd../
{
BYTE i;
#if 1 //test only!!
for (i=0; i<=4; i++)
{
ReadDataWord=0; //init the read buffer.
}
SearchRead1=ReadDataWord[0]; //byte 0 --4 .byte 0 first.
SearchRead2=ReadDataWord[1]; //byte 0 --4 .byte 0 first.
SearchRead3=ReadDataWord[2]; //byte 0 --4 .byte 0 first.
SearchRead4=ReadDataWord[3]; //byte 0 --4 .byte 0 first.
SearchRead5=ReadDataWord[4]; //byte 0 --4 .byte 0 first.
Delay10us(2);
#endif
CMD_SendStart();
if (CMD_SendByte(0x0c1)) //chip addr of read data
{
for (i=0;i<5;i++)
ReadDataWord =(i==4)? CMD_GetByte(1):CMD_GetByte(0); //the last byte with ACK.
CMD_SendStop();
}
else CMD_SendStop();
#if 1 //test only!!
SearchRead1=ReadDataWord[0]; //byte 0 --4 .byte 0 first.
SearchRead2=ReadDataWord[1]; //byte 0 --4 .byte 0 first.
SearchRead3=ReadDataWord[2]; //byte 0 --4 .byte 0 first.
SearchRead4=ReadDataWord[3]; //byte 0 --4 .byte 0 first.
SearchRead5=ReadDataWord[4]; //byte 0 --4 .byte 0 first.
Delay10us(2);
#endif
}
/////////////////////////
/*********************************************************
* NAME : SearchOver
* CHK if the search Finished accoding the SWPORT1
*
* Returns : none
*
* Parameter Description
* --------------------------------------------------------
* none
*
* Externals Usage
* --------------------------------------------------------
*
*
* Additional information:
* Local subfunction
*********************************************************/
BYTE data LowCount=0; //for test only
static BIT SearchOver(void)
{
LowCount++;
return(SWPORT1) ; //PIN from low to high. Then tuning over
}
/*********************************************************
* NAME : TuneOver
* CHK if the PreeSet or search Finished according
* the read byte1.7
*
*
* Returns : none
*
* Parameter Description
* --------------------------------------------------------
* none
*
* Externals Usage
* --------------------------------------------------------
*
*
* Additional information:
* Local subfunction
*********************************************************/
BYTE tbRead1;
BYTE tbRead2;
BIT Stereo=False;
BIT Ready=False;
static void TuneOver(void)
{
BIT Ready=False;
ReadSTR(); //how about continue read???? mao 0227
tbRead1=ReadDataWord[0];
tbRead2=ReadDataWord[2];
LowCount++; //for test only.
if((tbRead1&0x40) != 0) BandLimit=True; //limited
else BandLimit=False;
if((tbRead2&0x80) != 0) Stereo=True;
else Stereo=False;
tbRead1=ReadDataWord[0];
if((tbRead1&0x80) != 0) Ready=True; //Found
else Ready=False;
}
/*********************************************************
* NAME : AssembleFrequencyWord
* given a VCO frequency calculate and load the frequency databitsr
* and save the PLL Fre to DataWord[37-24] =14 bits
* 5757 have 15 bits and the bits location is different!
* Returns : none
*
* Parameter Description
* --------------------------------------------------------
* none
*
* Externals Usage
* --------------------------------------------------------
* WriteDataWord[37-24] the bits will be Set according cal result(out)
* gdwPresetVCO in
*
* Additional information:
* Local subfunction
* All the Frequency unit is KHz.!
* Test it is ok 02/26
*********************************************************/
static void AssembleFrequencyWord(void)
{
UINT16 twPLL =0; //Dec
UINT32 tdwPresetVCO =gdwPresetVCO; //Khz
BYTE tbTmp1;
BYTE tbTmp2;
// calcu1ate frequency dataword bits from given station frequency BCD:
if(FlagHighInjection)
twPLL =(unsigned int)((float)((tdwPresetVCO +225)*4)/(float)REFERENCE_FREQ);
else
twPLL =(unsigned int)((float)((tdwPresetVCO -225)*4)/(float)REFERENCE_FREQ);
//convert BCD to Hex.
tbTmp1 =(unsigned char)(twPLL%256); //6789=Hex1A85 -->133=Hex85
tbTmp2 =(unsigned char)(twPLL/256); // -->26=Hex1A
WriteDataWord[0]=tbTmp2; //high block
WriteDataWord[1]=tbTmp1;
}
/*********************************************************
* NAME : DisAssembleFrequencyWord
* given a frequency dataword and waveband,
* calculate the VCO frequency
* Get the PLL Freq BITs from DataWord[37-24] =14 bits
* 5757 have 15 bits and the bits location is different!
* Returns : none
*
* Parameter Description
* --------------------------------------------------------
* none
*
* Externals Usage
* --------------------------------------------------------
* ReadDataWord[37-24] the bits will be taken(in)
* gdwSearchedVCO the Freq (out)
*
* Additional information:
* Local subfunction
* Tested, It is Ok. 02/26
*********************************************************/
void DisAssembleFrequencyWord(void)
{
UINT16 twPLL =0; //Dec
UINT32 tdwPresetVCO =gdwPresetVCO; //Khz
BYTE tbTmp1=ReadDataWord[1];
BYTE tbTmp2=ReadDataWord[0];
tbTmp2&=0x3f;
twPLL=tbTmp2*256+tbTmp1;
// calculate searched station frequency from dataword bits
if(FlagHighInjection)
gdwSearchedVCO =(unsigned long)((float)twPLL*(float)REFERENCE_FREQ*(float)0.25-225);
else
gdwSearchedVCO =(unsigned long)((float)twPLL*(float)REFERENCE_FREQ*(float)0.25+225);
}
/*********************************************************
* NAME : AssembleData
* assemble a full data word based on global variables
*
* Returns : none
*
* Parameter Description
* --------------------------------------------------------
* none
*
* Externals Usage
* --------------------------------------------------------
* DataWord[39-0] the bits will be Set(out)
* The global Variable in as below list!!
*
* FlagSearch in, if search or preSet mode? StartSearch [38]
* FlagLevel in search stop level [21,22]
* FalgMono in.
* FlagSWPORT2 in
* FlagSearchtUp in
* gdwPresetVCO in
*
* WriteDataWord[] out.
*
* Additional information:
* Local subfunction
* Tested, It is Ok. 4/16
*********************************************************/
BYTE Write1;
static void AssembleData(void)
{
WriteDataWord[3] = 0x11; //32k /p1 found.
WriteDataWord[4] = 0x40;
if(FlagMute) WriteDataWord[0] |= 0x80;
else WriteDataWord[0] &= 0x7f ; //0111 1111
if (FlagSearch ) // search mode
{
WriteDataWord[0] |= 0x40; // Set to 1 for search start; other =0.
// Set the bits of BYTE3 of search
if(FlagSearchtUp) WriteDataWord[2] |= 0x80;
else WriteDataWord[2] &= 0x7f; //0111 1111
if ((FlagLevel & 0x02) == 0x02) WriteDataWord[2] |=0x40 ;
else WriteDataWord[2] &=0x0bf; //1011 1111
if ((FlagLevel & 0x01) == 0x01) WriteDataWord[2] |=0x20;
else WriteDataWord[2] &=0x0df; //1101 1111
Write1= WriteDataWord[0] ;
}
/////PreSet mode
else
{
AssembleFrequencyWord();
WriteDataWord[0] &= 0x0bf; // Set to 0 for Preset mode. 1011,1111
}
//set the public data bit of BYTE3
if(FlagHighInjection) WriteDataWord[2] |= 0x10 ;
else WriteDataWord[2] &= 0x0ef; //1110 1111
if(FlagMono) WriteDataWord[2] |= 0x08 ;
else WriteDataWord[2] &= 0x0f7 ; //1111 0111
//set the public data bit of BYTE4
if(FlagSWPORT2) WriteDataWord[3] |= 0x80;
else WriteDataWord[3] &= 0x7f ; //0111 1111
if(FlagSoftMute) WriteDataWord[3] |= 0x08;
else WriteDataWord[3] &= 0xf7 ; //1111 0111
if(FlagSWPORT1) WriteDataWord[3] |= 0x01;
else WriteDataWord[3] &= 0xfe ; //1111 1110
}
//////////////////////////////////////////////////////////////////////////////////
/* Above are local sub routine and called in this file */
/*********************************************************
* NAME : Tuner_Preset
* PreSet the 5767 to a Staion_FREQ
*
* Returns : none
*
* Parameter Description
* --------------------------------------------------------
* none
*
* Externals Usage
* --------------------------------------------------------
* Target VCO in
*
* Additional information:
* Local subfunction
* Tested, It is Ok. 4/16
*********************************************************/
void Tuner_Preset (BIT Mute, BIT SetMono,BIT Pin15,unsigned long VCO)
{
FlagSearch = False; // Set global parameters
FlagMono = SetMono;
FlagSWPORT2 = Pin15;
gdwPresetVCO = VCO;
FlagMute=Mute; //0301 mao
AssembleData();
WriteSTR();
Delay10us(50000); //200ms
ReadSTR(); //read data to ReadDataWord[] .
Delay10us(2);
#if 0
// while (SWPORT1);
while(!SearchOver() ) // waiting for station detected
{
Delay10us(2000);
WriteSTR();
}
#endif
}
/*********************************************************
* NAME : Tuner_Search
* Tea5767 to search a statioon.
*
* Returns : none
*
* Parameter Description
* --------------------------------------------------------
* none
*
* Externals Usage
* --------------------------------------------------------
* DataWord[37-24] the bits will be taken(in)
* gdwSearchedVCO the Freq (out)
*
* Additional information:
* Local subfunction
*********************************************************/
void Tuner_Search (BIT Direction,BYTE Level ) // target level to search for
{
if (Direction)
{
Tuner_Preset (False,False,Low,gdwPresetVCO+AST_STEP); // Preset to searched station 0301 mao
FlagHighInjection=False;
}
else
{
Tuner_Preset (False,False,Low,gdwPresetVCO-AST_STEP);
FlagHighInjection=True;
}
FlagSearch = True; // Set global parameters
FlagSearchtUp = Direction;
FlagLevel = Level;
FlagMute=True; //0301 mao
AssembleData();
WriteSTR();
// Delay10us(100000); //1s ms
///////////////////
#if 1
while (SWPORT1);
Delay10us(2);
while(!SearchOver() ) // waiting for station detected
{
NotFound = True;
}
FlagSearch = False; // Reset search flag
ReadSTR(); //read data to ReadDataWord[] .
Delay10us(2); //for test only
DisAssembleFrequencyWord(); // retrieve VCO frequency from ReadDataWord[]
Delay10us(2);
#else
/////////////////////////
do
{
Delay10us(10000); //0.1s ms
ReadSTR(); //how about continue read???? mao 0227
tbRead1=ReadDataWord[0];
tbRead2=ReadDataWord[2];
LowCount++; //for test only.
Delay10us(20);
if((tbRead1&0x80) != 0) Ready=True; //Found
else Ready=False;
Delay10us(20);
if((tbRead1&0x40) != 0) BandLimit=True; //limited
else BandLimit=False;
Delay10us(20);
if((tbRead2&0x80) != 0) Stereo=True;
else Stereo=False;
Delay10us(20);
if(Ready) break;
DisAssembleFrequencyWord(); // retrieve VCO frequency from ReadDataWord[]
Tuner_Preset (True,False,Low,gdwPresetVCO); // Preset to searched station 0301 mao
FlagSearch = True; // Set global parameters
AssembleData();
WriteSTR();
Delay10us(20000); //for test only
} while( !BandLimit ) ;
DisAssembleFrequencyWord(); // retrieve VCO frequency from ReadDataWord[]
#endif
///////////////////////////////
FlagSearch = False; // Reset search flag
if ( (gdwSearchedVCO > HighestFM )|| (gdwSearchedVCO < LowestFM ) )
{
BandLimit=True;
FlagSWPORT2=True;
LCD_ShowChar(LCD_ERR);
}
else
{
Tuner_Preset (False,False,Low,gdwSearchedVCO); // Preset to searched station 0301 mao
LCD_ShowFM(0x00,gdwSearchedVCO);
BandLimit=False;
}
Delay10us(20); //for test only
LowCount=0;
}
/*********************************************************
* NAME : Tuner_AST_Search
* Perform the AST function
*
* Returns : none
*
* Parameter Description
* --------------------------------------------------------
* none
*
* Externals Usage
* --------------------------------------------------------
*
* Additional information:
* To simplify the control,we only search one level of 3.
* in factly we should search 2 and 3 level.
*
*********************************************************/
BYTE station_num=0;
void Tuner_AST_Search(void)
{
UINT32 InitASTVCO=0;
//Mute(ON); //no sound out
//clear the sation buffer!!!
for(station_num=0;station_num<=MAX_STATION;station_num++)
{
TunerStation[station_num]=0;
}
station_num=0;
gdwPresetVCO = LowestFM-AST_STEP; // Lowest -SETP
Delay10us(20); // Test only
do
{
// Tuner_Preset (False,False,Low,gdwSearchedVCO+AST_STEP );
//Delay10us(50000); // 500ms delay
Tuner_Search(Up,SearchLevel);
if(!BandLimit)
{
Delay10us(2); // Test only
station_num++; //stion 0 not used.
TunerStation[station_num]=gdwSearchedVCO;
gdwPresetVCO =gdwSearchedVCO; //for next search use
//Tuner_Preset (False,False,Low,gdwSearchedVCO); //???? 0308 for test????
// LCD_ShowFM(station_num,gdwSearchedVCO);
Delay10us(100000); // 1s delay
}
else
{
SearchLevel--;
BandLimit=False;
break;
}
Delay10us(2); // 250ms delay
}while(station_num < MAX_STATION+1);
Max_Station=station_num;
////////////////////////////////////
if(Max_Station >0) //if found station!!!
{
Delay10us(100);
/* when exit AST, preset a fm station */
NowStation=1;
gdwWorkingVCO=TunerStation[NowStation];
Tuner_Preset (False,False,Low,gdwWorkingVCO);
//Mute(OFF); //sound out
// LCD_ShowFM(NowStation,gdwWorkingVCO);
}
else
LCD_ShowChar(LCD_ERR);
}
/*********************************************************
* NAME : Tuner_Init
* Tea5767 init. and preset it to a station.
*
* Returns : none
*
* Parameter Description
* --------------------------------------------------------
* none
*
* Externals Usage
* --------------------------------------------------------
* DataWord[37-24] the bits will be taken(in)
* gdwSearchedVCO the Freq (out)
*
* Additional information:
* Local subfunction
*********************************************************/
void Tuner_Init(void)
{
BYTE i;
for(i=0;i<5;i++) //Clear 5767 data buffer =0
{
ReadDataWord = False;
WriteDataWord =False;
}
WriteDataWord[0] = 0x2a; // init FM89.8MHz ok.
WriteDataWord[1] = 0x0b6;
WriteDataWord[2] = 0x41;
WriteDataWord[3] = 0x11; //soft Mute
WriteDataWord[4] = 0x40;
WriteSTR();
Delay10us(100);
WriteDataWord[0] = 0x2a; // init FM89.8MHz ok.
WriteDataWord[1] = 0x0b6;
WriteDataWord[2] = 0x41; //p1 high
WriteDataWord[3] = 0x11;
WriteDataWord[4] = 0x40;
WriteSTR();
Tuner_Preset( False, False,High,97100 ) ;
}
/*********************************************************
* NAME : Tuner_UIF
* According the key val to process the function!!
*
* Returns : none
*
* Parameter Description
* --------------------------------------------------------
* none
*
* Externals Usage
* --------------------------------------------------------
*
*
* Additional information:
* none
*********************************************************/
void Tuner_UIF(void)
{
if( gbNewKey != KEY_NONE )
{
//ClearDisplayDelay(); // clear display delay timer
Delay10us(8);
switch( gbNewKey )
{
case KEY_PREV_DIR: //25 Prev station 103.2
Tuner_Search (Down,SearchLevel );
Tuner_Preset (False,False,Low,gdwSearchedVCO); // Preset to searched station 0301 mao
break;
case KEY_NEXT_DIR: //next staion 103.2
Tuner_Search (Up,SearchLevel );
Tuner_Preset (False,False,Low,gdwSearchedVCO); // Preset to searched station 0301 mao
break;
case KEY_VOL_DOWN: //Tune down one step 100kHz
Tuner_Preset(False,False,High,gdwPresetVCO-STEP);
break;
case KEY_VOL_UP: //Tune up one step 100kHz
Tuner_Preset(False,False,High,gdwPresetVCO+STEP);
break;
case KEY_FR: //29H
Tuner_Preset(False,False,High,88300); //97100);
break;
case KEY_FF: //2aH
Tuner_Preset(False,False,High,100000); //89800);
break;
case KEY_SOUND_EFFECT: // prev station
Tuner_Preset(False,False,High,97100);
break;
case KEY_ESP: //Next station
Tuner_AST_Search(); //AST FUNCTION
break;
case KEY_PLAY: //
if( NowStation>0)
{
NowStation--;
gdwWorkingVCO=TunerStation[NowStation];
Tuner_Preset (False,False,Low,gdwWorkingVCO);
}
break;
case KEY_STOP: // 46
if(NowStation<MAX_STATION)
{
NowStation++;
gdwWorkingVCO=TunerStation[NowStation];
Tuner_Preset (False,False,Low,gdwWorkingVCO);
}
break;
}
gbNewKey = KEY_NONE;
}
}
-----此内容被_yu-ming于2006-10-09,09:09:55编辑过 |
|