关于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;
}