zoukankan      html  css  js  c++  java
  • 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
    ",__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    
    ",__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
    ",__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;
    	}
    }
    


     

  • 相关阅读:
    JSP中 == 和equals的区别
    使用Cookie保存用户名密码,再次登陆时将Cookie用户名密码取出来并直接放置到用户名密码文本框中
    学习Java Web开发中遇到的问题,及其解决方法
    部署、测试、服务工作的经验记录
    Python基础--dict字典操作
    Python基础--dict字典
    Python基础--预留空 5
    Python基础--预留空 4
    Python基础--tuple 元组
    Python基础--预留3
  • 原文地址:https://www.cnblogs.com/dengxiaojun/p/4279433.html
Copyright © 2011-2022 走看看