RDA1846的驱动程序和频率设定

1 篇文章 0 订阅

关于RDA1846,RDA1846是一种用于V/U段的调频收发机芯片,与AT1846S兼容,可互换使用。支持DTMF和亚音等功能。可用于2米,1.25米或0.7米的业余频段。

The RDA1846 is a highly integrated single-chip 

transceiver for Walkie Talkie applications. It totally

realizes the translation from RF carrier to voice in

the RX path and from voice to RF carrier in the TX

path, requiring only one micro controller.

官方参考电路图:

头文件

/******************** (C) COPYRIGHT www.iotman.link ***************************
* File Name          : RDA1846.h
* Author             : glassine.zhang   www.iotman.link
* Email              : glassine@sina.com
* Version            : V0.0.1
* Date               : 2019/09/01
* Description        : RDA1846.c的头文件。
*******************************************************************************/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __RDA1846_H
#define __RDA1846_H
/* Includes ------------------------------------------------------------------*/

/* Exported define -----------------------------------------------------------*/

//#define Channel_25K_Hz
#define RF_Freq 	422995000
#define Chn_25K 	0x01
#define Chn_12K5 	0x00
#define SQ_On 		On
#define SQ_Off 		Off

/*lq 1846 MR_ID */
#define RDA1846_MRID_RDA1846    0x0007
#define RDA1846_MRID_AT1846S    0x003F

/* Exported types ------------------------------------------------------------*/
typedef struct tagRDA1846Freq
{
  U32 TX_Freq;		/* 发射频点 */
  U32 RX_Freq;		/* 接收频点 */
}stRDA1846Freq; 

typedef struct tagRDA1846SQ
{
  U8 	SQ_OnOff;
  U16 SQ_Open_Threhold;		/* 发射频点 */
  U16 SQ_Shut_Threhold;		/* 接收频点 */
}stRDA1846SQ;

typedef enum Rda1846TypeEnum
{
  RDA1846TYPE_OTHER = 0,
  RDA1846TYPE_RDA1846 = 1,
  RDA1846TYPE_AT1846S = 2,
}Rda1846TypeEnum;

typedef struct Rda1846SelfCheckStruct
{
  U8  PdnOkFlg;
  U8  SenOkFlg;
  U8  DataCommOkFlg;              //lq clk and SDI/SDO
  U8  TypeOkFlg;
  Rda1846TypeEnum Rda1846Type;    //lq... 暂时未用        
  U8  StartFlg;
  U8  CompleteFlg;
}Rda1846SelfCheckStruct;

typedef struct Rda1846Struct
{
  Rda1846TypeEnum Rda1846Type;        //lq 程序运行使用的1846类型
  Rda1846TypeEnum Rda1846TypeReal;    //lq 实际的1846类型    
}Rda1846Struct;

#ifndef On
#define On 1
#endif

#ifndef Off
#define Off 0
#endif
/* Exported variables --------------------------------------------------------*/
extern stRDA1846Freq RDA1846Freq; 
extern stRDA1846SQ RDA1846SQ;
extern Rda1846Struct Rda1846Instance;

/* Exported constants --------------------------------------------------------*/
/* Exported macro ------------------------------------------------------------*/
/* Exported functions ------------------------------------------------------- */

extern void Init_RDA1846(void);

void Init_RDA1846_Rx(U32 Hz);
void Init_RDA1846_Tx(U32 Hz);
void Init_RDA1846_SQ(U16 SQ_Open_threshold, U16 SQ_Shut_threshold);

U16 Rd_RDA1846reg(U8 address);	//读寄存器值函数

void RDA1846_Sleep(void);				//RF soc睡眠
void RDA1846_Wakeup(void);			//RF soc唤醒
void RDA1846_Reset(void);				//RF soc复位
#endif

程序内容

/******************** (C) COPYRIGHT www.iotman.link ***************************
* File Name          : RDA1846.c
* Author             : glassine.zhang   www.iotman.link
* Email              : glassine@sina.com
* Version            : V0.0.1
* Date               : 2019/09/01
* Description        : 这个文件对RDA1846进行配置,实现射频的控收/控发。
*******************************************************************************/

/* Includes ------------------------------------------------------------------*/
#include "stm32f10x_lib.h"
#include "def.h"
#include "RDA1846.h"
#include "sys.h"
#include "common.h"
#include "config.h"

/* Public variables ---------------------------------------------------------*/
Rda1846Struct Rda1846Instance;

/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
//SPI端口定义
#define SCLK PBout(11)	// PG12
#define SEN PBout(1)		// PG14	
#define SDI PBout(10)		// PG13
#define SDO PBin(10)		// PG13
//RDA1846 模式设置管脚
#define PDN PBout(12)		// PG11

/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
u16 Reg29_2A[2] = {0x0000, 0x0000};				//用于计算1846寄存器0x29 0x2A的值
u16 Reg30 = 0x0000;												//记录睡眠时 收发的状态
stRDA1846Freq RDA1846Freq = {0, 0};
stRDA1846SQ RDA1846SQ = {Off, 0, 0};

/* Private function prototypes -----------------------------------------------*/
void WriteRda1846(u8 address, u16 data);			//往Rda1846寄存器里写数据,子函数,通过IO口模拟的方式
void Wr_RDA1846reg(u8 address, u16 data);			//写寄存器值函数
u16 ReadRda1846(u8 address);									//读数据从Rda1846寄存器,子函数,通过IO口模拟的方式
void Cal_TxRx_Freq(u32 Hz,u16 *Reg29_2A);			//计算发送和接收的频点
void RDA1846_SetRegVal(u8 address, u16 data);	//向1846寄存器打入数据
void RDA1846_Port_Init(void);									//RDA1846控制管脚初始化
void RDA1846_ConfigTxPower(void);

/* Private functions ---------------------------------------------------------*/
/*******************************************************************************
* Function Name  : RDA1846_Port_Init
* Description    : RDA1846控制管脚初始化
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/
void RDA1846_Port_Init(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);	//使能PORTB时钟
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_10 | GPIO_Pin_11 | GPIO_Pin_12;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOB, &GPIO_InitStructure);
	
	SEN = 1;	//cs 无效
	SCLK = 0;	//在不用的时候,将时钟信号拉低
	SDI = 1;	//数据输出,在不用的时候拉高 
	PDN = 1;
}

/*******************************************************************************
* Function Name  : WriteRda1846
* Description    : 往Rda1846寄存器里写数据,子函数,通过IO口模拟的方式
* Input          : 8bit address, 16bit data
* Output         : None
* Return         : None
*******************************************************************************/
void WriteRda1846(u8 address, u16 data)
{
	u8 i;
	u32 tmp_rda;
	GPIO_InitTypeDef GPIO_InitStructure;
	
	// SDIO (O)
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);	//使能PORTG时钟
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //PG13推挽输出
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOB, &GPIO_InitStructure);
	
	tmp_rda = (((u32)address << 16) | data); // 写标志 + 地址 + 数据
	
	SEN = 0;	//cs 有效
	for(i=0; i<24; i++)
	{
		SCLK = 0;
		if((tmp_rda & 0x800000) == 0x800000)
		{
			SDI = 1;
		}
		else
		{
			SDI = 0;
		}
		SCLK = 1;
		tmp_rda <<=1;
	}
	SCLK = 0;
	SEN = 1;	//cs 无效
	SDI = 1;
}

/*******************************************************************************
* Function Name  : Wr_RDA1846reg
* Description    : 往Rda1846寄存器里写数据
* Input          : 8bit address, 16bit data
* Output         : None
* Return         : None
*******************************************************************************/
void Wr_RDA1846reg(u8 address, u16 data)	//写函数
{
	if(address>0x7F)	//如果地址大于0x7F
	{
		WriteRda1846(0x7F,0x0001);
		WriteRda1846((address-0x80),data);
		WriteRda1846(0x7F,0x0000);
	}
	else				//正常情况下
	{
		WriteRda1846(address,data);
	}
}

/*******************************************************************************
* Function Name  : ReadRda1846
* Description    : 读数据从Rda1846寄存器,子函数,通过IO口模拟的方式
* Input          : 8bit address
* Output         : 16bit data
* Return         : None
*******************************************************************************/
u16 ReadRda1846(u8 address)
{
	u8 i;
	u16 data;
	GPIO_InitTypeDef GPIO_InitStructure;
	
	// SDIO (O)
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);	//使能PORTG时钟
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //PG13推挽输出
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOB, &GPIO_InitStructure);
	
	//=====地址byte中的第一个bit代表读(1)或者写(0)====
	address |= 0x80;	// 读标志 + 地址
	SEN = 0;		//cs 有效
	for(i=0; i<8; i++)
	{
		SCLK = 0;
		if((address & 0x80) == 0x80)
		{
			SDI = 1;
		}
		else
		{
			SDI = 0;
		}
		address <<=1;
		SCLK = 1;
	}
	SCLK = 0;
	
	// SDIO (I)
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);	//使能PORTG时钟
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; //PG13浮空输入
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOB, &GPIO_InitStructure);
	
	data = 0x0000;	//将变量清零
	for(i=0; i<16; i++)	//获取数据
	{
	SCLK = 1;
	data <<= 1;
	if(SDO)
	{
	  data += 1;
	}
	SCLK = 0;
	}
	SEN = 1;	//cs 无效
	SDI = 1;
	return data;
}

/*******************************************************************************
* Function Name  : Rd_RDA1846reg
* Description    : 读数据从Rda1846寄存器
* Input          : 8bit address
* Output         : 16bit data
* Return         : None
*******************************************************************************/
u16 Rd_RDA1846reg(u8 address)	//读函数
{
	u16 temp=0x0000;
	if(address>0x7F)		//如果地址大于0x7F
	{
	WriteRda1846(0x7F,0x0001);
	temp=ReadRda1846(address-0x80);
	WriteRda1846(0x7F,0x0000);
	}
	else					//正常情况下
	{
	temp=ReadRda1846(address);
	}
	return temp;
}

/*******************************************************************************
* Function Name  : Cal_TxRx_Freq
* Description    : 计算发送和接收的频点
* Input          : 32bit XX Hz,16bit 数组指针
* Output         : 16bit 数组值
* Return         : None
*******************************************************************************/
void Cal_TxRx_Freq(u32 Hz,u16 *Reg29_2A)
{
#if CONFIG_RDA1846
#if (CONFIG_RDA1846 && CONFIG_AT1846S)
    if (Rda1846Instance.Rda1846Type == RDA1846TYPE_RDA1846)
    {
#endif    
        /*lq 写入寄存器的数据的单位为 1kHz/8 */
    	*(Reg29_2A++)=((u32)(Hz/125))>>16;
    	*Reg29_2A=((u32)(Hz/125))&0xFFFF;
#if (CONFIG_RDA1846 && CONFIG_AT1846S)
    }
#endif
#endif

#if CONFIG_AT1846S
#if (CONFIG_RDA1846 && CONFIG_AT1846S)
    if (Rda1846Instance.Rda1846Type == RDA1846TYPE_AT1846S)
    {
#endif    
        /*lq 写入寄存器的数据的单位为 1kHz/16 */
    	*(Reg29_2A++) = ((u32)(Hz * 2 / 125)) >> 16;
    	*Reg29_2A = ((u32)(Hz * 2 / 125)) & 0xFFFF;
#if (CONFIG_RDA1846 && CONFIG_AT1846S)
    }
#endif
#endif
}

/*******************************************************************************
* Function Name  : RDA1846_SetRegVal
* Description    : 输入寄存器值,再读回来 验证读写正确 测试版程序使用 正式版只使用Wr_RDA1846reg函数
* Input          : u8 address, u16 data
* Output         : 打印返回值
* Return         : None
*******************************************************************************/
void RDA1846_SetRegVal(u8 address, u16 data)
{
	Wr_RDA1846reg(address,data);
}

/*******************************************************************************
* Function Name  : Init_RDA1846
* Description    : 初始化RDA1846函数
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/
void Init_RDA1846(void)
{
  	U16 regVal;

	RDA1846_Port_Init();
    
    /*lq 复位并开启1846 */
    RDA1846_SetRegVal(0x30, 0x0001);    //lq reset register
	Delay_ms(50);
	RDA1846_SetRegVal(0x30, 0x0004);    //lq poweron 1846

	/*lq 判断1846型号 */
    regVal = Rd_RDA1846reg(0x01); 
	if (regVal == RDA1846_MRID_RDA1846)
    {
        Rda1846Instance.Rda1846TypeReal = RDA1846TYPE_RDA1846;
        Rda1846Instance.Rda1846Type = RDA1846TYPE_RDA1846;
    }
    else if (regVal == RDA1846_MRID_AT1846S)
    {
        Rda1846Instance.Rda1846TypeReal = RDA1846TYPE_AT1846S;
        Rda1846Instance.Rda1846Type = RDA1846TYPE_AT1846S;
    }
    else
    {
        Rda1846Instance.Rda1846TypeReal = RDA1846TYPE_OTHER;
        Rda1846Instance.Rda1846Type = RDA1846TYPE_AT1846S;      //lq 默认为AT1846S    
    }

#if CONFIG_RDA1846
#if (CONFIG_RDA1846 && CONFIG_AT1846S)
    if (Rda1846Instance.Rda1846Type == RDA1846TYPE_RDA1846)
    {
#endif
    	//25k
    	RDA1846_SetRegVal(0x02,0x0698);
    	RDA1846_SetRegVal(0x04,0x0FD0);
    	RDA1846_SetRegVal(0x08,0x02A0);
    	RDA1846_SetRegVal(0x0B,0x1A10);
    	RDA1846_SetRegVal(0x2B,0x32C8);
    	RDA1846_SetRegVal(0x2C,0x1964);
    	RDA1846_SetRegVal(0x32,0x627C);
    	RDA1846_SetRegVal(0x33,0x0AF2);
    	RDA1846_SetRegVal(0x47,0x2C2F);
    	RDA1846_SetRegVal(0x4E,0x293A);
    	RDA1846_SetRegVal(0x54,0x1D4C);
    	RDA1846_SetRegVal(0x56,0x0652);
    	RDA1846_SetRegVal(0x6E,0x062D);
    	RDA1846_SetRegVal(0x70,0x1029);
    	//If 0x85 is  0x001F, Rfoutput power is 8dBm , ACP is -63dB in 12.5KHz and -65dB in 25KHz
    	//If 0x85 is  0x0018, Rfoutput power is 6dBm , ACP is -64dB in 12.5KHz and -66dB in 25KHz
    	//If 0x85 is  0x0017, Rfoutput power is -3dBm , ACP is -68dBc in 12.5KHz and -68dBc in 25KHz
    	RDA1846_SetRegVal(0x85,0x0018);    	
#if 1	//高通normal  voice lpf bypass == normal
    	RDA1846_SetRegVal(0x58,0x03CF);
#else	//高通旁路
    	RDA1846_SetRegVal(0x58,0x03FF);
#endif
    	RDA1846_SetRegVal(0x1F,0x1000);	//set gpio sq on
    	
    	RDA1846_SetRegVal(0x30,0x30A4);
    	Delay_ms(50);
    	RDA1846_SetRegVal(0x30,0x30A6);
    	Delay_ms(100);
    	RDA1846_SetRegVal(0x30,0x3006);
    	Delay_ms(100);
    	
    	RDA1846_SetRegVal(0x0F,0x00E4);
    	Init_RDA1846_Tx(161975000);
    	RDA1846_Sleep();
    
#if (CONFIG_RDA1846 && CONFIG_AT1846S)
    }
#endif

#endif

#if CONFIG_AT1846S
#if (CONFIG_RDA1846 && CONFIG_AT1846S)
    if (Rda1846Instance.Rda1846Type == RDA1846TYPE_AT1846S)
    {
#endif	
        /*lq initial */
    	RDA1846_SetRegVal(0x04, 0x0FD0);    //lq select crystal frequency,26MHz
    	RDA1846_SetRegVal(0x31, 0x0031);
    	RDA1846_SetRegVal(0x33, 0x44A5);    //lq agc number
    	RDA1846_SetRegVal(0x34, 0x2B87);    //lq rx digital gain
    	RDA1846_SetRegVal(0x41, 0x470F);    //lq digital gain for Tx
    	RDA1846_SetRegVal(0x44, 0x0DFF);    //lq digital gain for Tx
    	RDA1846_SetRegVal(0x47, 0x7FFF);    //lq soft mute
    	RDA1846_SetRegVal(0x4F, 0x2C62);
    	RDA1846_SetRegVal(0x53, 0x0094);
    	RDA1846_SetRegVal(0x55, 0x0081);
    	RDA1846_SetRegVal(0x56, 0x0B22);    //lq SQ detection time(SQ setting)
    	RDA1846_SetRegVal(0x57, 0x1C00);    //lq bypass rssi_lpfilter
    	RDA1846_SetRegVal(0x5A, 0x0EDB);    //lq SQ detection time(SQ setting)
    	RDA1846_SetRegVal(0x60, 0x101E);    //lq noise2_th(SQ setting)
    	RDA1846_SetRegVal(0x63, 0x16AD);    //lq Pre_emphasis bypass th
    	RDA1846_SetRegVal(0x30, 0x40A4);    //lq calibration
    	Delay_ms(50);
    	RDA1846_SetRegVal(0x30, 0x40A6);
    	Delay_ms(100);
    	RDA1846_SetRegVal(0x30, 0x4006);
    	Delay_ms(10);
    
        /*lq initial mode 25kHz */
        RDA1846_SetRegVal(0x15, 0x1F00);    //lq tuning_bit
        RDA1846_SetRegVal(0x32, 0x7564);    //lq agc target power
#if 0
        RDA1846_SetRegVal(0x3A, 0x44C3);    //lq modu_det_sel(SQ setting )
#else
        RDA1846_SetRegVal(0x3A, 0x04C3);    //lq TX Voice Channel Select = Tx nothing
#endif
        RDA1846_SetRegVal(0x3C, 0x172C);    //lq Pk_det_th(SQ setting )
        RDA1846_SetRegVal(0x3F, 0x29D2);    //lq Rssi3_th(SQ setting )
        RDA1846_SetRegVal(0x48, 0x2141);    //lq noise1_th(SQ setting )
        RDA1846_SetRegVal(0x59, 0x0A50);    //lq Tx FM devitation 
        RDA1846_SetRegVal(0x62, 0x2346);    //lq modu_det_th(SQ setting )
        RDA1846_SetRegVal(0x65, 0x248A);    //lq setting th_sif for SQ rssi detect
        RDA1846_SetRegVal(0x66, 0xFF2E);    //lq rssi_comp and afc range
        RDA1846_SetRegVal(0x86, 0x0024);    //lq agc gain talbe
        RDA1846_SetRegVal(0x87, 0x0214);
        RDA1846_SetRegVal(0x88, 0x0224);
        RDA1846_SetRegVal(0x89, 0x0314);
        RDA1846_SetRegVal(0x8A, 0x0324);
        RDA1846_SetRegVal(0x8B, 0x0344);
        RDA1846_SetRegVal(0x8C, 0x0384);
        RDA1846_SetRegVal(0x8D, 0x1384);
        RDA1846_SetRegVal(0x8E, 0x1B84);
        RDA1846_SetRegVal(0x8F, 0x3F84);
        RDA1846_SetRegVal(0x92, 0xE0EB);
    
        RDA1846_ConfigTxPower();
    	Init_RDA1846_Tx(161975000);
    	RDA1846_Sleep();
    
#if (CONFIG_RDA1846 && CONFIG_AT1846S)
    }
#endif
#endif
}

/*******************************************************************************
* Function Name  : Init_RDA1846_Rx
* Description    : 控收
* Input          : 32bit Hz
* Output         : None
* Return         : None
*******************************************************************************/
void Init_RDA1846_Rx(u32 Hz)
{
  	U16 RegVal;

	Cal_TxRx_Freq(Hz,Reg29_2A);
	RDA1846_SetRegVal(0x29,Reg29_2A[0]);	
	RDA1846_SetRegVal(0x2A,Reg29_2A[1]);	

#if CONFIG_RDA1846
#if (CONFIG_RDA1846 && CONFIG_AT1846S)
    if (Rda1846Instance.Rda1846Type == RDA1846TYPE_RDA1846)
    {
#endif    
    	//25k,	AutoSQ off
    	RDA1846_SetRegVal(0x30,0x3006);
    	RDA1846_SetRegVal(0x30,0x3026);
#if (CONFIG_RDA1846 && CONFIG_AT1846S)
    }
#endif    
#endif

#if CONFIG_AT1846S      
#if (CONFIG_RDA1846 && CONFIG_AT1846S)
    if (Rda1846Instance.Rda1846Type == RDA1846TYPE_AT1846S)
    {
#endif    

        /*lq 13MHz/26MHzcrystal frequency, 25kHz mode */
    	RDA1846_SetRegVal(0x30, 0x7006);
    	RDA1846_SetRegVal(0x30, 0x7026);
    
    	Delay_ms(10);
    	
    	/*lq 查看PLL是否锁定 */
    	RegVal = Rd_RDA1846reg(0x0d);
    	RegVal = ((RegVal >> 15) & 0x01);
        
        /*lq 若未锁定,则重新校准PLL*/
    	if(RegVal == 0)	
    	{
    		/*lq 检测到失锁 */
    		RDA1846_SetRegVal(0x27, 0x74A4);
    		Delay_ms(1);					    //wait 1ms(时间可调) 
    		RDA1846_SetRegVal(0x27, 0x7CA4);
    		RDA1846_SetRegVal(0x27, 0x6CA4);
    	}
#if (CONFIG_RDA1846 && CONFIG_AT1846S)
    }
#endif
#endif

}

/*******************************************************************************
* Function Name  : Init_RDA1846_Tx
* Description    : 控发
* Input          : 32bit Hz
* Output         : None
* Return         : None
*******************************************************************************/
void Init_RDA1846_Tx(u32 Hz)
{
  	U16 RegVal;
	
	Cal_TxRx_Freq(Hz,Reg29_2A);

	RDA1846_SetRegVal(0x29,Reg29_2A[0]);	
	RDA1846_SetRegVal(0x2A,Reg29_2A[1]);

#if CONFIG_RDA1846
#if (CONFIG_RDA1846 && CONFIG_AT1846S)
    if (Rda1846Instance.Rda1846Type == RDA1846TYPE_RDA1846)
    {
#endif    
    	
        //25k,	AutoSQ off
    	RDA1846_SetRegVal(0x30,0x3006);
    	RDA1846_SetRegVal(0x30,0x3046);
    	
    	Delay_ms(10);//等待10ms
    	
    	//查看是否锁定
    	RegVal = Rd_RDA1846reg(0x5c);
    	RegVal = ((RegVal>>11) & 0x01);
    
    	if(RegVal == 0)	//重新校准PLL
    	{
    		//检测到失锁
    		RDA1846_SetRegVal(0x27,0x14A0);// 0x27H=0x14A0
    		Delay_ms(1);					//wait 1ms(时间可调) 
    		RDA1846_SetRegVal(0x27,0x1CA0);//0x27H=0x1CA0
    		RDA1846_SetRegVal(0x27,0x04A0);//0x27H=0x04A0 
    	}
#if (CONFIG_RDA1846 && CONFIG_AT1846S)
    }
#endif    
#endif

#if CONFIG_AT1846S      
#if (CONFIG_RDA1846 && CONFIG_AT1846S)
    if (Rda1846Instance.Rda1846Type == RDA1846TYPE_AT1846S)
    {
#endif    

        /*lq 13MHz/26MHzcrystal frequency, 25kHz mode */
    	RDA1846_SetRegVal(0x30, 0x7006);
    	RDA1846_SetRegVal(0x30, 0x7046);
    
    	Delay_ms(10);
    	
    	/*lq 查看PLL是否锁定 */
    	RegVal = Rd_RDA1846reg(0x0d);
    	RegVal = ((RegVal >> 15) & 0x01);
        
        /*lq 若未锁定,则重新校准PLL*/
    	if(RegVal == 0)	
    	{
    		/*lq 检测到失锁 */
    		RDA1846_SetRegVal(0x27, 0x74A4);
    		Delay_ms(1);					    //wait 1ms(时间可调) 
    		RDA1846_SetRegVal(0x27, 0x7CA4);
    		RDA1846_SetRegVal(0x27, 0x6CA4);
    	}
#if (CONFIG_RDA1846 && CONFIG_AT1846S)
    }
#endif    
#endif
}

/*******************************************************************************
* Function Name  : Init_RDA1846_SQ
* Description    : 初始化RDA1846的静噪
* Input          : u16 SQ_Open_threshold, u16 SQ_Shut_threshold
* Output         : None
* Return         : None
*******************************************************************************/
void Init_RDA1846_SQ(u16 SQ_Open_threshold, u16 SQ_Shut_threshold)
{
  RDA1846_SetRegVal(0x48,SQ_Open_threshold);
  RDA1846_SetRegVal(0x49,SQ_Shut_threshold);
}

/*******************************************************************************
* Function Name  : RDA1846_Sleep
* Description    : 休眠RDA1846
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/
void RDA1846_Sleep(void)
{
	u16 temp;
	
    Reg30 = Rd_RDA1846reg(0x30);
	temp = Reg30 & 0xFF9F;	//30H[5..6] == 00
	RDA1846_SetRegVal(0x30, temp);
	PDN = 0;
}

/*******************************************************************************
* Function Name  : RDA1846_Wakeup
* Description    : 唤醒RDA1846
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/
void RDA1846_Wakeup(void)
{
	PDN = 1;                                                                    //lq 唤醒RDA1846

#if CONFIG_RDA1846
#if (CONFIG_RDA1846 && CONFIG_AT1846S)
    if (Rda1846Instance.Rda1846Type == RDA1846TYPE_RDA1846)
    {
#endif    
    	Delay_ms(10);       //延时10ms
#if (CONFIG_RDA1846 && CONFIG_AT1846S)
    }
#endif    
#endif

#if CONFIG_AT1846S
#if (CONFIG_RDA1846 && CONFIG_AT1846S)
    if (Rda1846Instance.Rda1846Type == RDA1846TYPE_AT1846S)
    {
#endif    
    	Delay_ms(100);      //lq 延时100ms
#if (CONFIG_RDA1846 && CONFIG_AT1846S)
    }
#endif    
#endif

	RDA1846_SetRegVal(0x30, Reg30);
}

/*******************************************************************************
* Function Name  : RDA1846_Reset
* Description    : 复位RDA1846寄存器
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/
void RDA1846_Reset(void)
{
	RDA1846_SetRegVal(0x30,0x0001);	//软件复位
}

/*******************************************************************************
* Function Name  : RDA1846_ConfigTxPower
* Description    : 配置AT1846S发射功率
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/
void RDA1846_ConfigTxPower(void)
{
  	U16 regVal;
    
    regVal = Rd_RDA1846reg(0x0A);
    regVal &= (0x87FF);             //lq reset power bits
    regVal |= (0x000C << 11);       //lq config power bits, Tx power = 6.2dBm
	RDA1846_SetRegVal(0x0A, regVal);
}

/*******************************************************************************
* Function Name  : WriteRda1846
* Description    : 往Rda1846寄存器里写数据,子函数,通过IO口模拟的方式
* Input          : 8bit address, 16bit data
                   csFlg - 片选是否使能
* Output         : None
* Return         : None
*******************************************************************************/
void WriteRda1846SelfCheck(u8 address, u16 data, u8 csFlg)
{
	u8 i;
	u32 tmp_rda;
	GPIO_InitTypeDef GPIO_InitStructure;
	
	// SDIO (O)
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);	//使能PORTG时钟
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //PG13推挽输出
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOB, &GPIO_InitStructure);
	
	tmp_rda = (((u32)address << 16) | data); // 写标志 + 地址 + 数据

    if (csFlg == TRUE)	
    {
	    SEN = 0;	//cs 有效    
    }
    else
    {
	    SEN = 1;	//cs 无效        
    }

	for(i=0; i<24; i++)
	{
		SCLK = 0;
		if((tmp_rda & 0x800000) == 0x800000)
		{
			SDI = 1;
		}
		else
		{
			SDI = 0;
		}
		SCLK = 1;
		tmp_rda <<=1;
	}
	SCLK = 0;
	SEN = 1;	//cs 无效
	SDI = 1;
}

/*******************************************************************************
* Function Name  : ReadRda1846SelfCheck
* Description    : 读数据从Rda1846寄存器,子函数,通过IO口模拟的方式
* Input          : address - 8bit address
                   csFlg - 片选是否使能
* Output         : 16bit data
* Return         : None
*******************************************************************************/
u16 ReadRda1846SelfCheck(u8 address, u8 csFlg)
{
	u8 i;
	u16 data;
	GPIO_InitTypeDef GPIO_InitStructure;
	
	// SDIO (O)
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);	//使能PORTG时钟
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //PG13推挽输出
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOB, &GPIO_InitStructure);
	
	//=====地址byte中的第一个bit代表读(1)或者写(0)====
	address |= 0x80;	// 读标志 + 地址
	
    if (csFlg == TRUE)
    {
        SEN = 0;		//cs 有效    
    }
    else
    {
	    SEN = 1;	//cs 无效        
    }

	for (i=0; i<8; i++)
	{
		SCLK = 0;
		if ((address & 0x80) == 0x80)
		{
			SDI = 1;
		}
		else
		{
			SDI = 0;
		}
		address <<=1;
		SCLK = 1;
	}
	SCLK = 0;
	
	// SDIO (I)
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);	//使能PORTG时钟
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; //PG13浮空输入
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOB, &GPIO_InitStructure);
	
	data = 0x0000;	//将变量清零
	for (i=0; i<16; i++)	//获取数据
	{
    	SCLK = 1;
    	data <<= 1;
    	if (SDO)
    	{
    	    data += 1;
    	}
    	SCLK = 0;
	}
	SEN = 1;	//cs 无效
	SDI = 1;
	return data;
}

/*******************************************************************************
* Function Name  : Rd_RDA1846reg
* Description    : 读数据从Rda1846寄存器
* Input          : address - 8bit address
                   csFlg - 片选是否使能
* Output         : 16bit data
* Return         : None
*******************************************************************************/
u16 Rd_RDA1846regSelfCheck(u8 address, u8 csFlg)	//读函数
{
	u16 temp = 0x0000;
	if(address > 0x7F)		//如果地址大于0x7F
	{
    	WriteRda1846SelfCheck(0x7F, 0x0001, csFlg);
    	temp = ReadRda1846SelfCheck(address - 0x80, csFlg);
    	WriteRda1846SelfCheck(0x7F, 0x0000, csFlg);
	}
	else					//正常情况下
	{
	    temp = ReadRda1846SelfCheck(address, csFlg);
	}
	return temp;
}

/*******************************************************************************
* Function Name  : RDA1846_SelfCheck
* Description    : RDA1846自检
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/
void RDA1846_SelfCheck(Rda1846SelfCheckStruct *pRda1846SelfCheckStruct)
{
  	U16 regVal;

    if (pRda1846SelfCheckStruct->StartFlg == TRUE)
    {
        /*lq PDN使能 */
        RDA1846_Wakeup();
    
        /*lq SEN使能 */
        regVal = Rd_RDA1846regSelfCheck(0x00, TRUE);
    
        if (regVal == 0x1846)
        {
            pRda1846SelfCheckStruct->DataCommOkFlg = TRUE;

            /*lq 读芯片型号 */
            regVal = Rd_RDA1846regSelfCheck(0x01, TRUE);
            if (regVal == RDA1846_MRID_RDA1846)
            {
                pRda1846SelfCheckStruct->Rda1846Type = RDA1846TYPE_RDA1846;
                pRda1846SelfCheckStruct->TypeOkFlg = TRUE;
            }
            else if (regVal == RDA1846_MRID_AT1846S)
            {
                pRda1846SelfCheckStruct->Rda1846Type = RDA1846TYPE_AT1846S;
                pRda1846SelfCheckStruct->TypeOkFlg = TRUE;
            }
            else
            {
                pRda1846SelfCheckStruct->Rda1846Type = RDA1846TYPE_OTHER;
                pRda1846SelfCheckStruct->TypeOkFlg = FALSE;
            }
                
            /*lq SEN失能 */
            regVal = Rd_RDA1846regSelfCheck(0x00, FALSE);
            if (regVal == 0x1846)
            {
                pRda1846SelfCheckStruct->SenOkFlg = FALSE;           
            }
            else
            {
                pRda1846SelfCheckStruct->SenOkFlg = TRUE;
            }
#if 0    
            /*lq PDN失能 */
            RDA1846_Sleep();    //lq RDA1846即使sleep,仍可进行数据通信,无法验证PDN
            
            /*lq SEN使能 */
            regVal = Rd_RDA1846regSelfCheck(0x00, TRUE);
            if (regVal == 0x1846)
            {
                pRda1846SelfCheckStruct->PdnOkFlg = FALSE;           
            }
            else
            {
                pRda1846SelfCheckStruct->PdnOkFlg = TRUE;
            }
#endif
        }
        else
        {
            /*lq 无法进一步确定问题的准确原因 */
            pRda1846SelfCheckStruct->PdnOkFlg = FALSE;
            pRda1846SelfCheckStruct->SenOkFlg = FALSE;
            pRda1846SelfCheckStruct->DataCommOkFlg = FALSE;
            pRda1846SelfCheckStruct->TypeOkFlg = FALSE;
            pRda1846SelfCheckStruct->Rda1846Type = RDA1846TYPE_OTHER;
        }
            
        RDA1846_Sleep(); 
    
        pRda1846SelfCheckStruct->CompleteFlg = TRUE;               
        pRda1846SelfCheckStruct->StartFlg = FALSE;
    }        
}

/*******************************************************************************
* 名称  : EEPROM_EepromSelfCheckStructInit
* 描述  : 初始化结构体
* 输入  : pEepromSelfCheckStruct - EepromSelfCheckStruct结构体指针	  
* 输出  : 无
* 返回  : 无
*******************************************************************************/
void RDA1846_Rda1846SelfCheckStructInit(Rda1846SelfCheckStruct *pRda1846SelfCheckStruct)
{
    pRda1846SelfCheckStruct->PdnOkFlg = FALSE;
    pRda1846SelfCheckStruct->SenOkFlg = FALSE;
    pRda1846SelfCheckStruct->DataCommOkFlg = FALSE;
    pRda1846SelfCheckStruct->TypeOkFlg = FALSE;
    pRda1846SelfCheckStruct->Rda1846Type = RDA1846TYPE_OTHER;
    pRda1846SelfCheckStruct->StartFlg = TRUE;       
    pRda1846SelfCheckStruct->CompleteFlg = FALSE;       
}

  • 4
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
RDA5807FP是一款低功耗、单芯片、立体声FM收音机芯片。它能够用于各种电子设备中,如智能手机、平板电脑、音乐播放器等等。为了让RDA5807FP能够正常工作,需要编写相关的驱动程序。 RDA5807FP驱动程序的目的是将硬件和软件进行有效地连接。它通过控制相关的寄存器来配置和控制RDA5807FP芯片的各个功能模块。驱动程序需要对RDA5807FP的寄存器及其对应的值进行设置,以达到用户所需的功能。 首先,驱动程序需要初始化RDA5807FP芯片。它通过一系列的配置操作来设置芯片的初始状态。接下来,驱动程序需要控制RDA5807FP的频率调谐功能,使其能够收听不同的FM频率。这一过程涉及到对频率寄存器的操作,通过设置寄存器的值来实现频率的调节。 除了频率调谐,RDA5807FP还具有其他一些功能,如立体声/单声道切换、静音控制、信号强度检测等。驱动程序需要对这些功能进行设置和控制,以实现用户期望的效果。 最后,驱动程序还需要处理来自RDA5807FP芯片的中断,以及与其他设备的接口。它需要根据芯片的状态变化来作出相应的处理,以便及时更新相关的状态信息。 总的来说,RDA5807FP驱动程序负责控制RDA5807FP芯片的各个功能,实现对FM收音功能的控制和操作。它是硬件和软件之间的桥梁,确保RDA5807FP能够正常工作,并且满足用户的需求。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

glassine

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值