STM32驱动TEA5767收音机模块
Tea5767是飞利浦公司出的一款集成化的收音机芯片,大四的时候机缘巧合遇到了这个芯片,用了一下,写点资料
主要特性
TEA5767HN是一款低功耗立体声收音IC,广泛应用于手机MP3
、MP 4
播放器等便携系统。接收频率 76 MHz
~108MHz (
日本/美国/欧洲频段选择)
,中频频率 225kHz采用锁相环调谐系统,带有AG C电路,并可以使用软件进行静音和消除噪音。主要电性能指标工作电压:2.5
V~5.0 V,工作电流10 m A,灵敏度1
5 V,立体声分离度30dB,信噪比 6 0 d B,输出信号电平7
5mV 。总线通信界面i 2 C和3
线总线可选,具有 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×98000000—225000))/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;
}
}
STM32驱动TEA5767收音机模块的更多相关文章
- STM32—驱动BT-06蓝牙模块传输数据
文章目录 BT-06简介 数据透传 配置串口 USART1初始化函数 USART2初始化函数 USART2的NVIC配置 USART1串口重映射 BT-06简介 BT06蓝牙模块是专为智能无线数据传输 ...
- STM32—驱动GY85-IMU模块
GY85是一个惯性测量模块,内部集成了三轴加速度计.三轴陀螺仪.电子罗盘.气压传感器等芯片,用于测量和报告设备速度.方向.重力,模块可以将加速度计.陀螺仪.电子罗盘等传感器的数据进行综合,在上位机可以 ...
- STM32—驱动HC-SR04超声波测距模块
文章目录 超声波测距原理 HC-SR04工作原理 STM32实现驱动 1.引脚的配置 2.时序控制 3.时间差测量 4.如何将距离测出来 超声波测距原理 利用HC-SR04超声波测距模块可以实现比较精 ...
- stm32驱动超声波模块
下面是关于stm32驱动超声波模块的一段代码,有需要的朋友可以复制参考,希望对大家能够有所帮助和启发. #define HCSR04_PORT GPIOB #define HCSR04_CLK RCC ...
- STM32驱动ILI9341控制器控制TFTLCD显示
STM32驱动ILI9341控制器控制TFTLCD显示 一.用STM32控制TFTLCD显示的编程方法,在编程驱动TFTLCD液晶显示器之前,我们先熟悉以下概念: 1.色彩深度,这是一个与TFTLCD ...
- AMS5601的ardunio和STM32驱动开发
AMS5601的ardunio和STM32驱动开发 本文有麦粒电子撰写,并提供相应产品服务. 前言 目前ams关于磁编码芯片用的比较多的可能是ams5600,能够输出pwm信号,电压信号以及I2C通信 ...
- esp8266的STM32驱动
esp8266的STM32驱动,数据发送接收由DMA完成,释放CPU. 目前只能发送返回消息为成功或失败的AT命令,并判断是否成功,详见esp8266_cmd():其它返回消息不可预知的命令(如查看A ...
- STM32驱动DS18B20
DS18B20 是由 DALLAS 半导体公司推出的一种的“一线总线”接口的温度传感器.与传 统的热敏电阻等测温元件相比,它是一种新型的体积小.适用电压宽.与微处理器接口简单的 数字化温度传感器.一线 ...
- STM32驱动OV7725摄像头颜色识别
实验目的: 使用stm32驱动OV7725摄像头进行图像实时采集,在tft屏幕上实时显示并识别图像中的特定颜色,在颜色的周围画上框. 实验现象: 我的工程代码链接: http://download.c ...
随机推荐
- java复用类
java复用类英文名叫reusing classes ,重新使用的类,复用的意思就是重复使用的类,其实现方法就是我们平常使用的组合和继承: 1.组合: has-a 的关系 (自我理解:组合就是我们 ...
- html 7.28
1.HTML标记在没有添加任何样式的时候,默认是有间距的,所以我们要先把把所有标记归置内(padding)外(margin)边距归置为0 2.HTML5 中不支持 <acronym> 标签 ...
- magento 好好玩
Magento更换服务器的方法 1.把magento的整个目录打包.上传到新服务器,把magento数据库导出,然后在新服务器上导入.如果导不进去的是因为magento的数据库使用了外键约束,通过 ...
- nginx初级安装配置
nginx初级安装配置 转自:(lykyl原创)http://www.cnblogs.com/lykyl/archive/2012/11/21/2781077.html 实验环境:系统 CENTOS5 ...
- DP CF 319 div1B
http://codeforces.com/contest/319/problem/B 题目大意: 有删除操作,每次都删除数组右边比自己小的.且紧挨着自己的数字.问最小需要删除几次. 思路: 我们定义 ...
- rpm命令说明
RPM命令常用参数 RPM的常规使用方法为rpm-?package.rpm,其中-?为操作参数(更多信息,请查阅帮助$manrpm): -q在系统中查询软件或查询指定rpm包的内容信息-i在系统中安装 ...
- 用SqlBulkCopy批量插入数据 遇到的错误
在将txt文本格式的数据导入到数据库中时候,使用的是SqlBulkCopy.但是出现了多处错误,在网上查到得资料如下: 错误一:来自数据源的 String 类型的给定值不能转换为指定目标列的类型 nv ...
- TCP/IP网络协议栈(转载)
原文:http://www.cnblogs.com/xuanku/p/tcpip.html TCP/IP网络协议栈分为四层, 从下至上依次是: 链路层 其实在链路层下面还有物理层, 指的是电信号的传输 ...
- ntopng汉化记录
对应版本为 ntopng-1.2.0_r8116.tgz 1.
- Android apk反编译基础(apktoos)图文教程
本文主要介绍了Android apk反编译基础,使用的工具是apktoos,我们将用图文的方式说明apktoos工具的使用方式,你可以参考这个方法反编译其它APK试试看了 很久有写过一个广工图书馆主页 ...