STM32驅動TEA5767收音機模塊


Tea5767是飛利浦公司出的一款集成化的收音機芯片,大四的時候機緣巧合遇到了這個芯片,用了一下,寫點資料

 

主要特性

TEA5767HN是一款低功耗立體聲收音IC,廣泛應用於手機MP3 MP 4 播放器等便攜系統接收頻率 76 MHz 108MHz ( 日本/美國/歐洲頻段選擇) ,中頻頻率 225kHz采用鎖相環調諧系統,帶AG C電路,並可以使用軟件進行靜音和消除噪音。主要電性能指標工作電壓2.5 V5.0 V工作電流10 m A靈敏度1 5 V,立體聲分離度30dB,信噪比 6 0 d B輸出信號電平7 5mV 。總線通信界面i 2 C3 線總線可選,具有 R F信號強度ADC,軟件靜音。TEA5767HN采用HVQFN40封裝

 

模塊額示意圖如下


 

該芯片主要依靠IIC通訊,不支持SUB_CLASS模式,也就是說,這個芯片沒有內部寄存器的概念,一共有五個命令字節,每次讀取直接發送芯片地址然后就可以讀取或者寫入,如下

IICstartàsend device addràwait ackàsend commandàwait ackàrepeat 5àsend stop

可見,沒有寫入寄存器

 

那么這五個命令字節分別有什么含義呢?見下表

 



另外,讀和寫並不是相同的定義,見下表

 


另外,TEA5764的控制我們推薦每次寫入讀出都按照五個字節來做,因為這樣,在寫入完后,才能完全是我們設置的內容,但是,也可以發四個字節后直接停止,不影響,沒發的那個字節的數據在芯片內部保持不變(但是如果要修改第五個字節,就必須要發送第五位了.為了簡單起見,就發送五位吧)

 

另外,我們在芯片內部存放的是當前頻道的PLL,頻率值需要根據PLL計算出來,計算公式如下

射頻信號經由天線輸入並經過LNA放大后,經過混頻后產生固定的中頻225KHZ

采用高邊帶接收時換算公式( HISI = 1 )


采用低邊帶接收時換算公式(HISI = 0)


要接收 98 MHz頻率,采用高邊帶接收,晶體振盪器為32.768kHz,則對應PLL值為(十進制)

(4×98000000 + 225000))32768 =11990

換算為十六進制制為2ED6H

而如果采用低邊帶接收,對應PLL值為(十進制)

(4×98000000225000))/32768=11935

換算為十六進制為 2E9F

 

搜台的基本流程如下

設置搜索方向,當前頻率,通過SM啟動搜索,讀取數據(50MS一次),RF==1的時候停止了,此時BLF==0,說明不是因為到極限停止的,這就是一個台,查看IF6看是否正確調諧,是的話,就說明這是個真台

具體代碼如下

#ifndef __TEA5767_H
#define __TEA5767_H
#include "uart.h"
#include "delay.h"
#include "ioremap.h"

//不完善,但是可通信了
#define MAX_FREQ 108000
#define MIN_FREQ 87500

#define MAX_PLL 0x339b           //108MHz時的pll,
#define MIN_PLL 0x299d           //87.5MHz時的pll

#define F_IF	225000		//225KHZ中頻
#define F_RES	32768		//基准頻率

#define TEA_ACK_WAIT_TIME	200		//IIC ack等待時間 200us

#define TEA5767ADDR_W   0xc0

#define TEA5767ADDR_R   TEA5767ADDR_W+0X01

#define TEA_DEBUG	1

//初始化命令序列
#define TEA_INIT_CIMMAND1	0x2E
#define TEA_INIT_CIMMAND2	0xD6
#define TEA_INIT_CIMMAND3	0x01
#define TEA_INIT_CIMMAND4	0x07
#define TEA_INIT_CIMMAND5	0x00

extern u8 TeaSendBuffer[5];	//寫入命令序列
extern u8 TeaReadBuffer[5];	//讀出命令序列

//初始化,初始化參數在初始化宏中定義
u8 TeaInit(void);	

//讀取一次
u8 TeaReadStatus(void);

//獲取下一個電台的頻率
u32 TeaGetNextCh(u8 dir);

u32 TeaGetCurrentFreq(void);






#endif




#include "tea5767.h"


u8 TeaSendBuffer[5] = {0};	//寫入命令序列
u8 TeaReadBuffer[5] = {0};	//讀出命令序列

//IO方向設置
#define TEA_SDA_IN()  {GPIOC->CRH&=0XFFFF0FFF;GPIOC->CRH|=8<<12;}
#define TEA_SDA_OUT() {GPIOC->CRH&=0XFFFF0FFF;GPIOC->CRH|=3<<12;}

//IO操作函數	 
#define TEA_SCL    PCout(10) //TEA SCL
#define TEA_SDA    PCout(11) //TEA SDA	 
#define TEA_READ_SDA   PCin(11)  //輸入SDA 

static void TEAIoInit(void)
{
	
	GPIO_InitTypeDef GPIO_InitStructure;
    RCC_APB2PeriphClockCmd(	RCC_APB2Periph_GPIOC, ENABLE );	
    
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10|GPIO_Pin_11;//PC10 PC11
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP ;   //推挽輸出
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOC, &GPIO_InitStructure);
    
	
    TEA_SCL = 1;//初始化均為浮空狀態
    TEA_SDA = 1;
	TeaSendBuffer[0] = TEA_INIT_CIMMAND1;
	TeaSendBuffer[1] = TEA_INIT_CIMMAND2;
	TeaSendBuffer[2] = TEA_INIT_CIMMAND3;
	TeaSendBuffer[3] = TEA_INIT_CIMMAND4;
	TeaSendBuffer[4] = TEA_INIT_CIMMAND5;
}

//發送IIC起始信號
static void ComStart(void)
{
	TEA_SDA_OUT();     //sda線輸出
    TEA_SDA=1;	  	  
    TEA_SCL=1;
    DelayUs(5);
    TEA_SDA=0;//START:when CLK is high,DATA change form high to low 
    DelayUs(5);
    TEA_SCL=0;//鉗住I2C總線,准備發送或接收數據
}

//發送IIC停止信號
static void ComStop(void)
{
	TEA_SDA_OUT();//sda線輸出
    TEA_SDA=0;//STOP:when CLK is high DATA change form low to high
    TEA_SCL=1;
    DelayUs(5);
    TEA_SDA=1;//發送I2C總線結束信號
    DelayUs(5);		
}

//等待ACK,為1代表無ACK 為0代表等到了ACK
static u8 ComWaitAck(void)
{
	u8 waitTime = 0;
	TEA_SDA_OUT();//sda線輸出
	TEA_SDA = 1;
	DelayUs(5);
    TEA_SDA_IN();      //SDA設置為輸入
	TEA_SCL=1;
	DelayUs(5);
	while(TEA_READ_SDA)
	{
		waitTime++;
		DelayUs(1);
		if(waitTime > TEA_ACK_WAIT_TIME)
		{
			ComStop();
			return 1;
		}
	}
	TEA_SCL = 0;
	return 0;
	
}
static void ComSendAck(void)
{
	TEA_SCL = 0;
	TEA_SDA_OUT();
    TEA_SDA = 0;
	DelayUs(2);
    TEA_SCL = 1;
    DelayUs(5);
    TEA_SCL = 0;
    DelayUs(5);
}

static void ComSendNoAck(void)
{
	TEA_SCL = 0;
	TEA_SDA_OUT();
    TEA_SDA = 1;
	DelayUs(2);
    TEA_SCL = 1;
    DelayUs(5);
    TEA_SCL = 0;
    DelayUs(5);
}
//返回0 寫入收到ACK 返回1寫入未收到ACK
static u8 ComSendByte(u8 byte)
{
	u8 t;   
    TEA_SDA_OUT(); 	
    for(t=0;t<8;t++)
    {              
        TEA_SDA=(byte&0x80)>>7;
        byte<<=1; 	   
        TEA_SCL=1;
        DelayUs(5); 
        TEA_SCL=0;	
        DelayUs(5);
    }	 
    return ComWaitAck();
}

static void ComReadByte(u8* byte)
{
	u8 i,receive=0;
    TEA_SDA_IN();//SDA設置為輸入
    for(i=0;i<8;i++ )
    {
        receive <<= 1;
        TEA_SCL=1; 
        DelayUs(5);
        if(TEA_READ_SDA)receive++;
        TEA_SCL=0; 
        DelayUs(5); 
    }					  
    *byte = receive;
}

/********************************************************************************************************/

u8 TeaWriteCommand(void)
{
	u8 res = 0;
	u8 i = 0;
	ComStart();
	res = ComSendByte(TEA5767ADDR_W);//發送地址
	if(res)
	{
		#ifdef TEA_DEBUG
		printf("file=%s,func=%s,line=%d\r\n",__FILE__,__FUNCTION__,__LINE__);
		#endif
		return res;
	}
	for(i = 0; i < 5; i++)
	{
		res = ComSendByte(TeaSendBuffer[i]);//發送命令數據
		if(res)
		{
			#ifdef TEA_DEBUG
			printf("file=%s    ,func=%s    ,line=%d    \r\n",__FILE__,__FUNCTION__,__LINE__);
			#endif
			return res;
		}
	}
	ComStop();
	return 0;
}

//返回0成功 返回1失敗
u8 TeaReadStatus(void)
{
	u8 res = 0;
	u8 i = 0;
	ComStart();
	res = ComSendByte(TEA5767ADDR_R);//讀取地址
	if(res)
	{
		#ifdef TEA_DEBUG
		printf("file=%s,func=%s,line=%d\r\n",__FILE__,__FUNCTION__,__LINE__);
		#endif
		return res;
	}
	for(i = 0; i < 5; i++)
	{
		ComReadByte(TeaReadBuffer+i);//發送命令數據
		if(i == 4) ComSendNoAck();
		else ComSendAck();
	}
	ComStop();
	return 0;
}

//返回0成功 返回1失敗
u8 TeaInit(void)
{
	TEAIoInit();
	return TeaWriteCommand();
}

u32 TeaGetCurrentFreq(void)
{
	u8 hlsi;
	u32 pll = 0;
	u32 freq = 0;
	if(TeaReadStatus())return 0;
	hlsi = TeaSendBuffer[2]&0x10;  //HLSI位
	pll = TeaReadBuffer[0]&0x3f;
	pll<<=8;
	pll += TeaReadBuffer[1];
	if(hlsi)
	{
		freq = (pll*(F_RES/4)) - F_IF;
	}
	else
	{
		freq = (pll*(F_RES/4)) + F_IF;
	}
	return freq;
}

void TeaSetFreq(u32 freq)
{
	u8 hlsi;
	u32 pll = 0;
	u8 pllH,pllL;
	hlsi = TeaSendBuffer[2]&0x10;  //HLSI位
	if (hlsi)
		pll=(unsigned int)((float)((freq+F_IF)*4)/(float)F_RES);    //頻率單位:HZ
	else
		pll=(unsigned int)((float)((freq-F_IF)*4)/(float)F_RES);    //頻率單位:HZ
	pll &= 0x00003fff;
	pllL = (u8)pll;
	pllH = (u8)(pll>>8);//分別PLL
	TeaSendBuffer[0] &= 0xc0;
	TeaSendBuffer[0] |= pllH;
	TeaSendBuffer[1] = pllL;//插入發送序列
	TeaWriteCommand();//寫入芯片
}

//1向上搜索 0向下搜索
u32 TeaGetNextCh(u8 dir)
{
	if(dir)TeaSendBuffer[2] |= 0x80;
	else TeaSendBuffer[2] &= ~0x80;//確定方向
	TeaSendBuffer[0] |= 0x40;//啟動搜索
	DelayMs(50);
	do
	{
		TeaReadStatus();
	}while((TeaReadBuffer[0]&0x80) == 0);
	//已經結束
	if((TeaReadBuffer[0]&0x40) == 0)
	{
		//找到一個台
		return TeaGetCurrentFreq();
	}
	else
	{
		return 0;
	}
}


 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM