caizhiwei 发表于 2013-9-22 17:42:18

分享一个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
大家来讨论一下寄存器,为啥子那么多呢?????

1125526801 发表于 2017-6-21 17:01:51

几年了。。。楼主,这驱动程序好用吗?准备做一个RAD5807收音机,参考一下。

HYLG 发表于 2017-6-22 01:25:45

RDA5807不用读什么寄存器,太麻烦了,
直接写前4个寄存器就可以听广播了。
第一个字节发送$20,后面就是8个字节的数据,高字节在前,低字节在后。
页: [1]
查看完整版本: 分享一个RDA5807驱动程序!!!