分享一个RDA5807驱动程序!!!
RDA5807的版本很多,寄存器也不大一样,我看了datasheeet 好多遍了,不明白其中的道理哦/*--------------------------------------------------------------------------*//**@file RDA5807P.C
@brief FM模块RDA5807P驱动
@details FM模块RDA5807P的驱动函数
@author LZZ
@date 2010-08-17
@note 本驱动支持模块,支持32K共晶振,支持P05输出时钟,三种方式时钟的程序一样
通过识别ID来区别各种版本
*/
/*----------------------------------------------------------------------------*/
#include "include.h"
#include "I2C_OTP.h"
#include "RDA5807P.h"
#include "fm_rx_api.h"
#include "key.h"
#define USE_P05_AS_FM_CLOCK 1
#define USE_CRYSTAL_AS_FM_CLOCK 2//共用晶振
#define USE_MODULE 3//使用模块,FM芯片自起振32.768K晶振的情况都属于这个模式
/*
此项宏定义说明是使用何种FM驱动方式
USE_P05_AS_FM_CLOCK,指使用P05作为时钟信号
USE_CRYSTAL_AS_FM_CLOCK,使用外部32K作为驱动信号
USE_MODULE,使用模块,FM芯片自起振晶振的情况都属于这个模式
*/
#define FM_CLOCK USE_CRYSTAL_AS_FM_CLOCK
//#define CS1000_MUTE dat|=0x80; //mute
#define CS1000_RD_CTRL 0x21
#define CS1000_WR_CTRL 0x20
bool fm_rx_stereo;
u16 rda5807_chipID;
u8 dat; //RDA5807与CL6017共用
u8 readdata; //RDA5807与CL6017共用
void FM_Write_3(u8 size);
void FM_Write_2(u8 size);
void FM_Read_2(u8 size);
#pragma constseg = RDA5807_RX_TABLE
#if 0
/*此初始化支持 RDA5807PERDA5807SP 版本*/
const u8 rad5807_init_tbl = // 原来的5807SP
{
#if(SYS_CRY == CRY_24M)
0x84, 0x51,
#elif(SYS_CRY == CRY_12M)
0xc4, 0x11,
#elif(SYS_CRY == CRY_32K)
0xC0, 0x01,
#endif
0x00, 0x10,
0x04, 0x00,
0x86, 0xad, //05H:
0x80, 0x00,
0x5F, 0x1A, //07H
0x5e, 0xc6,
0x00, 0x00,
0x40, 0x6e, //0AH:
0x2d, 0x80,
0x58, 0x03,
0x58, 0x04,
0x58, 0x04,
0x58, 0x04,
0x00, 0x47, //10H:
0x90, 0x00,
0xF5, 0x87,
0x7F, 0x0B, //13H:
0x04, 0xF1,
0x5E, 0xc0, //15H: 0x42, 0xc0
0x41, 0xe0,
0x50, 0x6f,
0x55, 0x92,
0x00, 0x7d,
0x10, 0xC0,//1AH
0x07, 0x80,
0x41, 0x1d,//1CH,
0x40, 0x06,
0x1f, 0x9B,
0x4c, 0x2b,//1FH.
0x81, 0x10, //20H:
0x45, 0xa0,// 21H
0x19, 0x3F, //22H
0xaf, 0x40,
0x06, 0x81,
0x1b, 0x2a, //25H
0x0D, 0x04,
0x80, 0x9F, //0x80, 0x2F,
0x17, 0x8A,
0xD3, 0x49,
0x11, 0x42,
0xA0, 0xC4, //2BH
0x3E, 0xBB,
0x00, 0x00,
0x58, 0x04,
0x58, 0x04, //2FH
0x58, 0x04,
0x00, 0x74,
0x3D, 0x00,
0x03, 0x0C,
0x2F, 0x68,
0x38, 0x77, //35H
};
/*此初始化支持 RDA5807HSRDA5807HP 版本*/
const u8 rad5807H_init_tbl = //更新后的5807,型号5807HP
{
#if(SYS_CRY == CRY_24M)
0x84, 0x51,
#elif(SYS_CRY == CRY_12M)
0xc4, 0x11,
#elif(SYS_CRY == CRY_32K)
0xc0,0x01,
#endif
0x00,0x10,
0x04,0x00,
0x88,0xB0, //05h://86 如打开20H寄存器,可在此调搜台个数,与SP版一样,0X80搜台最多
0x40,0x00,
0x7E,0xc6, //以下寄存器配置不可省去
0x00,0x00,
0x00,0x00,
0x00,0x00,//0x0ah
0x00,0x00,
0x00,0x00,
0x00,0x00,
0x00,0x00,
0x00,0x00,
0x00,0x06,//0x10h
0x00,0x19,// //0x00,0x09,//0830
0x2a,0x11,
0x00,0x2e,
0x2a,0x30,
0xb8,0x3c,//0x15h
0x90,0x00,
0x2a,0x91,
0x84,0x12,
0x00,0xa8,
0xc4,0x00,//0x1ah
0xe0,0x00,
0x30,0x1d,//0x24,0x9d,1ch
0x81,0x6a,
0x46,0x08,
0x00,0x86,//0x1fh
0x06,0x61,// 0x16,0x61, 20h//0X16为打开第05H寄存器,可在05H调搜台数
0x00,0x00,
0x10,0x9e,
0x25,0x4A,//0x24,0Xc9台多// 0x23,0x46 //0x25,0x4a //0x25,0xCB//0x26,0x4c台相对少,但清楚台更多,根据客户需求选择//23h搜台门限值调整
0x04,0x08,//0830
0x0c,0x16,//0x06,0x08,//0x06,0x08,//0830//0x25h
0xe1,0x05,
0x3b,0x6c,
0x2b,0xec,
0x09,0x0f,
0x34,0x14,//0x2ah
0x14,0x50,
0x09,0x6d,
0x2d,0x96,
0x01,0xda,
0x2a,0x7b,
0x08,0x21, //0x30h
0x13,0xd5,
0x48,0x91,
0x00,0xbc,
0x08,0x96,//08300x34h
0x15,0x3c,
0x0b,0x80,
0x25,0xc7,
0x00,0x00,
};
#endif
/*此初始化支持 RDA5807MPRDA5807M 版本*/
#if(SYS_CRY == CRY_12M)
const u8 rad5807M_init_tbl = //更新后的5807,型号5807MP
#else
const u8 rad5807M_init_tbl = //更新后的5807,型号5807MP
#endif
{
#if(SYS_CRY == CRY_24M)
0x84, 0x51,
#elif(SYS_CRY == CRY_12M)
0xc4, 0x11,
#elif(SYS_CRY == CRY_32K)
0xC0, 0x05,
#endif
0x00, 0x00,
0x04, 0x00,
0xC3, 0xab, //05h
0x60, 0x00,
0x42, 0x16,
0x00, 0x00,
0x00, 0x00,
0x00, 0x00,//0x0ah
0x00, 0x00,
0x00, 0x00,
0x00, 0x00,
0x00, 0x00,
0x00, 0x00,
0x00, 0x00,//0x10h
0x00, 0x19,
0x2a, 0x11,
0xB0, 0x42,
0x2A, 0x11,
0xb8, 0x31,//0x15h
0xc0, 0x00,
0x2a, 0x91,
0x94, 0x00,
0x00, 0xa8,
0xc4, 0x00,//0x1ah
0xF7, 0xcF,
0x2A, 0xDC,//0x1ch
0x80, 0x6F,
0x46, 0x08,
0x00, 0x86,
0x06, 0x61, //0x20H
0x00, 0x00,
0x10, 0x9E,
0x23, 0xC8,
0x04, 0x06,
#if(SYS_CRY == CRY_12M)
0x0E, 0x1C, //0x25H
#endif
};
#pragma constseg=default
/*----------------------------------------------------------------------------*/
/**@brief FM模块RDA5807P初始化
@param 无
@return 无
@note
*/
/*----------------------------------------------------------------------------*/
void rda5807p_init(void)@"RDA5807_RX"
{
u8 i;
#if 0
if (0x5804 == rda5807_chipID)
{
for(i=0;i<=11;i++)
dat = rad5807_init_tbl;
//power on
#if((SYS_CRY == CRY_24M) || (SYS_CRY == CRY_12M))
#if(FM_CLOCK != USE_CRYSTAL_AS_FM_CLOCK) //模块或独立晶振,P05使用的时钟还是32.768K
{
dat = 0xC0;
dat = 0x01;
}
#endif
#endif
FM_Write_2(2);
Delay5Ms(120);
//init
FM_Write_3(104);
Delay5Ms(1);
}
else if(0x5801 == rda5807_chipID)
{
for(i=0;i<=11;i++)
dat = rad5807H_init_tbl;
//power on
#if((SYS_CRY == CRY_24M) || (SYS_CRY == CRY_12M))
#if(FM_CLOCK != USE_CRYSTAL_AS_FM_CLOCK)
{
dat = 0xC0;
dat = 0x01;
}
#endif
#endif
FM_Write_2(2);
Delay5Ms(120);
//init
FM_Write_3(110);
Delay5Ms(1);
}
else if (0x5808 == rda5807_chipID)
{
for(i=0;i<=11;i++)
dat = rad5807M_init_tbl;
//power on
#if((SYS_CRY == CRY_24M) || (SYS_CRY == CRY_12M))
#if(FM_CLOCK != USE_CRYSTAL_AS_FM_CLOCK)
{
dat = 0xC0;
dat = 0x05;
}
#endif
#endif
FM_Write_2(2);
Delay5Ms(120);
//init
#if(SYS_CRY == CRY_12M)
FM_Write_3(72);
#else
FM_Write_3(70);
#endif
Delay5Ms(1);
}
#endif
for(i=0;i<=11;i++)
dat = rad5807M_init_tbl;
//power on
#if((SYS_CRY == CRY_24M) || (SYS_CRY == CRY_12M))
#if(FM_CLOCK != USE_CRYSTAL_AS_FM_CLOCK)
{
dat = 0xC0;
dat = 0x05;
}
#endif
#endif
FM_Write_2(2);
Delay5Ms(120);
//init
#if(SYS_CRY == CRY_12M)
FM_Write_3(72);
#else
FM_Write_3(70);
#endif
Delay5Ms(1);
}
void CS1000_Powerdown(void)@"RDA5807_RX"
{
dat &= ~(1<<0);
FM_Write_2(2);
Delay5Ms(100);
}
void CS1000_FMSeek_TuneMethod(u16 TunerFrequency,u8 diect)@"RDA5807_RX"
{
u16 ch;
ch = 0;
ch = (TunerFrequency - 8700)/10;
// dat |=0x40;
dat = ch>>2;
dat = ((ch&0x0003)<<6)|0x10;
FM_Write_2(4);
Delay5Ms(10);
}
void FM_Read_2(u8 size)
{
u16 i;
I2C_Start();
I2C_sendbyte(0x21);
ReceiveACK();
for (i=0;i<size-1;i++)
{
readdata = I2C_readbyte();
I2C_ack();
}
readdata = I2C_readbyte();
I2C_nack();
I2C_Stop();
}
void FM_Write_2(u8 size)
{
u8 i;
I2C_Start();
I2C_sendbyte(0x20);
ReceiveACK();
for (i=0;i<size;i++)
{
I2C_sendbyte(dat);
ReceiveACK();
}
I2C_Stop();
}
void FM_Write_3(u8 size)
{
u8 i;
I2C_Start();
I2C_sendbyte(0x20);
ReceiveACK();
for (i=0;i<size;i++)
{
#if 0
if(0x5804 == rda5807_chipID)
{
I2C_sendbyte(rad5807_init_tbl);
}
else if(0x5801 == rda5807_chipID)
{
I2C_sendbyte(rad5807H_init_tbl);
}
else if(0x5808 == rda5807_chipID)
{
I2C_sendbyte(rad5807M_init_tbl);
}
#endif
I2C_sendbyte(rad5807M_init_tbl);
ReceiveACK();
}
I2C_Stop();
}
/*----------------------------------------------------------------------------*/
/**@brief FM模块RDA5807P设置频率
@param freq 要设置的频率
@return 无
@note 频率范围为875~1080
*/
/*----------------------------------------------------------------------------*/
void rda5807p_set_freq(u16 freq)@"RDA5807_RX"
{
u8 try_cnt = 2;
while (try_cnt--)
{
CS1000_FMSeek_TuneMethod(freq*10,0);
}
}
/*----------------------------------------------------------------------------*/
/**@brief FM模块RDA5807P关闭
@param 无
@return 无
@note
*/
/*----------------------------------------------------------------------------*/
void rda5807p_off(void)@"RDA5807_RX"
{
CS1000_Powerdown();
}
/*----------------------------------------------------------------------------*/
/**@brief FM模块RDA5807P设置音量
@param vol 音量值
@return 无
@note 音量范围0~15
*/
/*----------------------------------------------------------------------------*/
void rda5807p_set_vol(u8 vol)@"RDA5807_RX"
{
if(vol > 15)
vol = 15;
dat &=~0x0F;
dat |= vol;
dat &= ~BIT(4);//03H.4=0,disable tune
if(vol == 0)
{
dat &= ~(1<<6);//MUTE ENABLE
}
else
{
dat |= (1<<6)|(1<<7);
dat |= (1<<0);
}
FM_Write_2(8);
}
/*----------------------------------------------------------------------------*/
/**@brief FM模块RDA5807P自动搜台
@param freq 要搜索的频率
@return 指定的频率下有台返回1,否则返回0
@note
*/
/*----------------------------------------------------------------------------*/
u8 rda5807p_seek(u16 freq)@"RDA5807_RX"
{
rda5807p_set_freq(freq);
Delay5Ms(10);
do
{
FM_Read_2(4);
Delay5Ms(4);
// fm_rx_rdy = (readdata>>7) & 0x01;
}
while (!((readdata>>7) & 0x01));
// if (flag)
// {
// rda5807p_set_freq(cur_freq);
// return cur_freq;
// }
// fm_rx_true = readdata & 0x01;
if (readdata & 0x01)//FM_TRUE
return true;
else
return false;
}
void rda5807p_mute(void)@"RDA5807_RX"
{
dat &= ~(1<<6);//MUTE ENABLE
FM_Write_2(2);
Delay5Ms(10);
}
void rda5807p_unmute(void)@"RDA5807_RX"
{
dat |= (1<<6)|(1<<7);
dat |= (1<<0);
FM_Write_2(2);
Delay5Ms(10);
}
/*----------------------------------------------------------------------------*/
/**@brief FM模块RDA5807P检测
@param 无
@return 检测到RDA5807P模块返回1,否则返回0
@note
*/
/*----------------------------------------------------------------------------*/
u8 rda5807p_online(void)@"RDA5807_RX"
{
dat = 0x00;
dat = 0x02;
FM_Write_2(2);
//read ID
FM_Read_2(10);
rda5807_chipID = (readdata << 8) | readdata;
if((rda5807_chipID == 0x5801) || (rda5807_chipID == 0x5804) || (rda5807_chipID == 0x5808))
return 1;
else
return 0;
}
哈哈#ifndef _RDA5807P_H_
#define _RDA5807P_H_
#include <include.h>
void CS1000_Write(u8 size);
void CS1000_Read(u8 size);
extern void rda5807p_init(void);
extern void rda5807p_set_freq(u16 freq);
extern void rda5807p_off(void);
extern void rda5807p_set_vol(u8 vol);
extern u8 rda5807p_seek(u16 freq);
extern void rda5807p_mute(void);
extern void rda5807p_unmute(void);
extern u8 rda5807p_online(void);
#endif
大家来讨论一下寄存器,为啥子那么多呢????? 几年了。。。楼主,这驱动程序好用吗?准备做一个RAD5807收音机,参考一下。 RDA5807不用读什么寄存器,太麻烦了,
直接写前4个寄存器就可以听广播了。
第一个字节发送$20,后面就是8个字节的数据,高字节在前,低字节在后。
页:
[1]