1.准备工作
1.1.前言
- 最近在学习
ADF4159
, 感觉受益匪浅, 有必要记录下来, 以免日后忘记. 也是为了帮助后人. - 我默认读者你, 已经掌握了单片机的使用方法, 包括不限于熟用
寄存器
, 了解时钟树
. - 另外, 因为我对
雷达/高频/傅里叶
等了解不深, 所以本文对专业术语的表达解释很可能不够严谨, 甚至是错的. 如果有大佬发现, 请理性清楚地在评论区提出, 我看到后会立刻修改. 提前谢谢. - 因此,本笔记止步于基础应用,更多高级应用并未涉及!
1.2.资料
-
主页 : ADF4159 | 小数N分频PLL | 亚德诺(ADI)半导体 : https://www.analog.com/cn/products/adf4159.html
-
中文手册 : ADF4159_cn.pdf : https://www.analog.com/media/cn/technical-documentation/data-sheets/ADF4159_cn.pdf
-
官方例程 : ADF4159参考代码 : https://www.analog.com/media/cn/example-code/PLL/ExampleCode_PLL_ADF4159.zip
-
参考电路 : RF至13 GHz超快速建立PLL : https://www.analog.com/cn/design-center/reference-designs/circuits-from-the-lab/CN0302.html#rd-overview
-
仿真设计软件 : ADIsimPLL | 设计资源 | 亚德诺半导体 : https://www.analog.com/cn/design-center/adisimpll.html
-
上面内容都要下载,下面笔记会用到.
1.3.介绍
- 官方介绍
ADF4159
是直接调制/快速波形产生13 GHz小数N分频频率合成器
,由低噪声数字鉴频鉴相器(PFD),精密电荷泵和可编程参考分频器组成
. 调制
? 专业术语,具体百度, 这里我简单理解就是调频/相/幅
.快速波形产生
? 这里我简单理解就是可以快速产生周期波形
.小数N分频
?一般分频都是整数,而且还是2个倍数,简单理解就是分频系数可以是小数
.鉴频鉴相器(PFD)
?专业术语,具体百度,这里我简单理解,输入2个信号a与b,输出a与b的频/相差值
,一般输入为参考信号和采集信号,如果采集信号不等于参考信号就有差值,把这个频率差值和相位差值返回.就是一个闭环系统中最重要的反馈部分,精密电荷泵
,这个是我完全没概念,就不比喻了.应用中有参考值,我是直接用参考值.可编程参考分频器
,这里我简单理解就是输入的参考频率可以分频
.这个功能貌似挺基本的.
1.4.应用
- 手册介绍了一堆,我也没看懂到底是干嘛的.因为很多专业术语没看懂.
- 我这里简单理解一下, 其实就是一个
信号发生器
,可以生成指定信号,这个信号可以是固定幅值
,也可以是周期变化幅值
.这个信号可以是固定频率
,也可以是周期变化频率
. - 也就是
PPL(锁相回路或锁相环)
,专业术语,具体百度.如果你熟用配置单片机时钟树,应该不对这个词不陌生.单片机的系统时钟一般可由外/内的高/低速时钟提供,但这些都是固定的,正常更加希望不一样的时钟频率,这时就用到PLL
,将固定的时钟通过分频得到想要的时钟频率. - 总结:简单理解就是
ADF4159
的功能就是可以将参考频率按小数分频输出,同时支持反馈,形成闭环.
1.5.应用电路
- 上图是官网下载的参考应用电路框图.左上就是
ADF4159
,用于产生频率信号并输出CP
.右上就是环路滤波器
,最简单的滤波电路就是电容电阻,上图使用的是运放组合.下中就是VCO(压控振荡器)
.频率信号走一圈后返回输入RFIN
,作闭环反馈. 环路滤波器
?专业术语,具体百度.这里我简单理解,就是滤波用的,不然信号噪声
会很大.简单点理解就是有助于信号稳定.问题就是这个滤波电路怎么设计和选择.手册里对于这部分的设置与设计有较多的说明,但我看不懂,所以是直接抄典型方案的.VCO(压控振荡器)
?专业术语,具体百度.之前只接触过晶振(晶体振荡器)
,可以类比理解.根据图来理解,它的作用就是接受一个输入VTUNE
,然后输出RFOUT
,同时返回输出的n分频RFOU0T/2
.因为ADF4159
最大工作频率在13GHz以内,如果临近或超过这个数值的,就需要有分频功能的VCO
.- 比如
ADF4159
工作在1GHz,输出CP
和输入RFIN
都是1GHz的信号,这时用2分频VCO
,那输出RFOUT
就是2GHz. - 调频(变化频率)同理. 比如
ADF4159
工作在12GHz,`输出CP`和`输入RFIN`都是12GHz的信号,这时用2分频VCO
,那输出RFOUT
就是2~4GHz. 因为我的电路和高频知识不足,对.本教程着重环路滤波器
,VCO(压控振荡器)
的解释并不完全正确,我只能从应用角度解释.我也不会设计电路方案.所以下面都是照抄官方提供的例子ADF4159
的应用,主要还是寄存器配置讲解.
2.ADF4159
2.1.功能框图
- 先从手册的第一页的功能框图理解,
ADF4159
的工作过程.
- 输入参考频率, 然后进行
5位分频
,在分频前可选择进行一次2倍频
,在分频后
可选择进行一次2除频
; - 通讯输出引脚, 可以选择输出不同内容,包括正负极电压,各个频率,和寄存器内容.
- 通讯输入引脚, 包括功能控制,使能,数据,时钟等.用于和模块内的32位寄存器读写通讯.
- 输出频率信号. 利用参考频率和反馈频率,生成输出频率.就是上面提到的
鉴频鉴相器(PFD=PHASE FREQUENCY DETECTOR)
; - 输入反馈信号, 将反馈信号小数分频,然后输入到
PFD
中.
- 寄存器中主要需要配置的内容,基本都在上面的框图中了.其他属于
特殊高级功能
或是VCO
和环路滤波器
用到的,我一律采用例程参考值,也就是0
,设置为不开启或是默认.
2.2.通信协议时序
- 手册有贴出时序图,想研究的可以自己看.我就不解释了.
- 官方参考例程有驱动代码,直接复制粘贴就可以了,如果没通讯上改一下软件延时就好了.
- 这个模块读数据有点特殊,就是固定37位的(?)上面的读取时序示意图.不过使用时比较少读取它的寄存器数据,而是读时钟之类的触发信号.
- 可以直接把官方例程修改后烧进去测试板,测试能不能读取ADF4159的返回数据,且输出有没有波形.如果都正常就代表驱动这部分没有问题.
// 下面内容为官方例程,我修改了小部分排版等内容.
void GET_MUXOUT(){} // 获取数据输出引脚的电平
void SET_CE(){} // 和使能引脚的控制
void CLR_CE(){}
void Delay(){} // 可有可无的软件延时
void SET_SCLK(){} // 时钟
void CLR_SCLK(){}
void SET_LE(){} // 读写控制
void CLR_LE(){}
void SET_DATA(){} // 写数据
void CLR_DATA(){}
void SET_TxDATA(){} // 读数据控制
void CLR_TxDATA(){}
// Write
void ADF4159_Write(unsigned long ulDACValue)
{
unsigned long SendValue = 0;
unsigned int i = 0;
CLR_SCLK();
SendValue = ulDACValue;
CLR_LE(); //bring LE low
Delay(0x5);
for(i=0;i<32;i++)
{
if(SendValue&0x80000000)
SET_DATA(); //Send 1 to DATA pin
else
CLR_DATA(); //Send 0 to DATA pin
Delay(0x50);
SET_SCLK(); //SCLK rising
Delay(0x50);
CLR_SCLK(); //SCLK falling
SendValue <<= 1; //Rotate data
}
SET_LE(); //bring LE high again
Delay(0x50);
}
// Read. Return 40-bit, the 37-bit MSB includes the 12-bit integer word and 25-bit FRAC word.
unsigned long long ADF4159_Read(void)
{
unsigned long long ulValue = 0;
unsigned long long ulData = 0;
unsigned long long BitIN = 0;
unsigned int i = 0;
CLR_TxDATA();
CLR_SCLK();
Delay(0x20);
SET_LE();
SET_TxDATA();
Delay(0x50);
CLR_TxDATA();
for(i=0;i<37;i++)
{
SET_SCLK(); //SCLK rising
Delay(0x5);
BitIN=GET_MUXOUT(); // 例程这里是读取单片机的gpio寄存器以获取引脚电平,我规范一下
ulValue+=BitIN;
Delay(0x45);
CLR_SCLK(); //SCLK falling
Delay(0x50);
if(i==36)
{}
else
ulValue <<= 1;
}
CLR_LE();
ulData = ulValue<<3; //ulData is 40-bit
return ulData;
}
2.2.寄存器
- 确认通讯没有问题就开始理解寄存器配置了. 总共有7个寄存器,需要配置的不多,所以我讲解一遍.
2.2.0.注意
-
寄存器中有很多没有使用的
保留位RESERVED
,手册会说明需要配置为0或1,大部分都是0. -
寄存器的选择,是通过32位的低3位决定.
- 模块(上电)初始化时,需要对7个寄存器都配置一遍.特别是
R6/5/4
,这3个寄存器需要发送2次数据.而这个STEP/DEV/CLKDIV SEL
位,在手册的寄存器说明中,很奇葩是这样描述的:位DB23置0时,选择步进字1.位DB23置1时,选择步进字2
;位DB23置0时,选择第一个偏差字.位DB23置1时,选择第二个偏差字
;将位DB6设为0后,CLK2便用作标准斜坡的CLK2值.将位DB6设为1后,CLK2便用作快速斜坡或双斜坡功能的第二斜坡CLK2值
.导致我一开始看得一头雾水,找半天找不到所指的内容.回来才知道改变不是描述的那回事.并不是用于选择内容,而是用于固定初始化的.
- 除了初始化很奇怪外,再初始化之后,如果希望单独修改某个寄存器的数据,也有特殊操作,也需要连续写入2次,参考官方例程中的代码.一般我使用是固定使用场景,即只会配置一次初始化参数,这样就不用考虑初始化后还要修改了.
// 截取例程中的一部分
R6=0x406; //R6-Ramp 1
ADF4159_Write(R6);
R6=0x800006; //R6-Ramp 2
ADF4159_Write(R6);
R5=0xC400805;
ADF4159_Write(R5);
R5=0xC800005;
ADF4159_Write(R5);
R4=0x580184;
ADF4159_Write(R4);
R4=0x580144;
ADF4159_Write(R4);
R0=0xF81E0000; //Set Muxout as READBACK TO MUXOUT
ADF4159_Write(R0);
2.2.1.延迟寄存器(R7)映射
- 如其名,这个寄存器主要配置一些延时功能.启动延时之类的.
- 我使用时没有这个需求.所以全部配置0.
#define DIV_ADF4159_R7() (0x00000007)
2.2.2.步进寄存器(R6)映射
- 主要是配置
步进数
,当设置输出信号
是周期变动频率
时,就需要设置. - 就是指每个周期中,从最小频率到最大频率,分为几段.如果分的越多,步进数越大,那频率变化就越平缓.
- 不要忘记还有个
STEP SEL
需要单独设置.
#define DIV_ADF4159_R6(STEP) (0x00000006|(((STEP)&0xFFFFF)<<3))
#define DIV_ADF4159_R62() (0x00800006)
2.2.3.偏差寄存器(R5)映射
- 主要是配置
偏差
,当设置输出信号
是周期变动频率
时,就需要设置. - 这里的偏差指每次变动的频率范围,即每次步进时跳变的频率,如果越小则代表变化越平滑.
- 该寄存器的其他值属于特殊功能使用,我没有用到,所以全部设置0.
- 不要忘记还有个
DEV SEL
需要单独设置.
#define DIV_ADF4159_R5(DEV_OFFSET, DEV) (0x00000005|(((DEV_OFFSET)&0xF)<<19)|(((DEV)&0xFFFF)<<3))
#define DIV_ADF4159_R52() (0x00800005)
2.2.4.时钟寄存器(R4)映射
- 主要是配置
时钟
,用于设置超时间隔,代表每两次步进之间的间隔,也就是每次频率保持多久后就改变. - 另外,根据功能需要,要配置
斜坡状态 位DB[25:21]
和时钟分频器模式位DB[20:19]
,我要讲解连续变频三角波,所以这里我设定为0x0
和0x3
. - 不要忘记还有个
CLK DIV SEL
需要单独设置.
#define DIV_ADF4159_R4(CLK2) (0x00180004|(((CLK2)&0xFFF)<<7))
#define DIV_ADF4159_R42(CLK2) (0x00180044|(((CLK2)&0xFFF)<<7))
2.2.5.功能寄存器(R3)映射
- 主要是配置
功能
,比如斜坡模式
,关断
等. 其他一堆我也不会解释的专业术语和功能,略过.我们直接参考例程的设定值. - 根据手册描述,虽然部分功能没看懂,但是手册里会有一句:
如需使工作更稳定, 请将 xxx 设为1
,这时一般就配置为1,其他不懂的用不到的功能都设置为0.又或者会有这样一句:正常工作时, 此位应设置为0
.这时就要配置0,一般就是作为使能开启的功能(?). - 注意:正常工作时, 除位
DB17
外的所有保留位必须设置为0. 位DB17
必须置1才能正常工作.
#define DIV_ADF4159_R3(RAMP_MODE) (0x000280C3|(((RAMP_MODE)&0x3)<<10))
2.2.6.R分频器寄存器(R2)映射
- 主要设置
分频系数R
,这个是用于设置PFD
的正输入频率,也就是固定频率.这个频率由参考频率分频得到,这个分频系数就是R
. - 回顾一下上面的框图①,就能更加生动的理解了.
- 还有其他功能位我没用到,就不解释了,全部设置0.
#define DIV_ADF4159_R2(I_CP, P, D, R, CLK1) (0x00000002|(((I_CP)&0xF)<<24)|(((P)&0x1)<<22)|(((D)&0x1)<<20)|(((R)&0x1F)<<15)|(((CLK1)&0xFFF)<<3))
2.2.7.LSB FRAC寄存器(R1)映射
- 主要设置
低13位小数(LSB FRAC)
, 用于设置最终的输出频率,有个分频系数,是由整数和小数组成.小数共25位,这里记录了低13位.
#define DIV_ADF4159_R1(FRAC_LSB) (0x00000001|(((FRAC_LSB)&0x1FFF)<<15))
2.2.8.FRAC/INT寄存器(R0)映射
- 对应上一个寄存器,主要就是设置最终输出频率的分频系数,设置小数剩余的高12位,和整数12位.
- 另外还有设置
MUXOUT
引脚的返回内容,和使能输出.
#define DIV_ADF4159_R0(RAMP_ON, MUXOUT, INT_12, FRAC_MSB) (0x00000000|(((RAMP_ON)&0x1)<<31)|(((MUXOUT)&0xF)<<27)|(((INT_12)&0xFFF)<<15)|(((FRAC_MSB)&0xFFF)<<3))
2.2.9.总结
功能框图
和寄存器描述
, 对照着看可以加深理解, 结合手册的公式描述明白到底设置了什么.- 最后结合实际的仿真例子,再自己计算一遍,基本就能掌握基础应用了.就是这样一个学习思路.
- 题外话, 安利(记录)一下,推荐几个宏定义使用,在GD32库中看到的,感觉很实用.
/* 枚举定义 */
typedef enum {DISABLE = 0, ENABLE = !DISABLE} EventStatus, ControlStatus; // 失能和使能
typedef enum {RESET = 0, SET = !RESET} FlagStatus; // 复位和置位
typedef enum {ERROR = 0, SUCCESS = !ERROR} ErrStatus; // 错误和成功
/* 位操作 */
#define VAR32(var) (REG32(&var)) // 按32位读取,值的地址
#define VAR16(var) (REG16(&var))
#define VAR8(var) (REG8(&var))
#define REG32(addr) (*(volatile uint32_t *)(uint32_t)(addr)) // 按32位读取,地址
#define REG16(addr) (*(volatile uint16_t *)(uint32_t)(addr))
#define REG8(addr) (*(volatile uint8_t *)(uint32_t)(addr))
#define BIT(x) ((uint32_t)((uint32_t)0x01U<<(x))) // 返回指定x位为1的数据,x从0开始
#define BITS(start, end) ((0xFFFFFFFFUL << (start)) & (0xFFFFFFFFUL >> (31U - (uint32_t)(end)))) // 返回指定(end-start+1)位为1的数据,包含end和start,end大于或等于start,end和start从0开始
#define GET_BIT(regval, x) (((regval) & BIT(x)) >> (x)) // 返回指定x位的数据,x从0开始
#define GET_BITS(regval, start, end) (((regval) & BITS((start),(end))) >> (start)) // 返回指定(end-start+1)位的数据,包含end和start,end大于或等于start,end和start从0开始
3.ADIsimPLL
- 找到官方推出的仿真软件,如下.
- 初次安装软件第一次打开会有一个软件介绍和新手教程,快速下一步跳过即可.
- 我刚开始学时全网只找到这篇仿真教程,贴出来感谢作者;
基于ADISimPLL的ADF4159连续调频波仿真: https://ez.analog.com/cn/other/f/forum/56433/adisimpll-adf4159
3.1.RF频率合成器: 一个成功范例
- 手册里有一段最简单的范例,只介绍了输出频率的计算方法.
- 我们在仿真软件中实现,先看看GIF图的设置过程;大部分都是默认下一步,
- 第一页是选择模块,选择
ADF4159
; - 第二页是设置模块功能,第一个是选择输出周期变动频率,还是固定频率; 第二个是选择分频类型是整数还是小数,ADF4159支持小数,默认选择小数.
- 第三页是设置固定的输出频率,设置
PDF
的固定输入频率,然后下面2个勾选项分别是,第一个是vco
是否分频,目前不需要; 第二个是设置参考时钟频率,后面再设置也可以. - 第四页是选择
vco
,可以选择官方提供的模型库,但没必要,选择最下面的勾选项,代表理想vco
,不设置参数. - 第五页是模块参数,默认,略过;
- 第六页是过滤器的选择和设置,默认,略过;仿真认为信号都是理想的;
- 第七页是
vco
参数设置,默认即可; - 第八页是参考时钟频率的设置;
- 第九页是滤波器的性能参数设置,最下面有个勾选项,用不到的,去掉;翻译是调制的意思,专业术语,自行百度.
- 最后就完成了,然后打开下方的
TimeDomain
选项卡页面就能看到频率-时间图
的输出效果图;默认x坐标范围可能太小,拉长到能看到稳定输出; - 最后的重点,打开左方的
FreqDomain
选项卡设置,能看到Analysis at - Int(N) Frac(F)
的参数设置.这个就是手册算出来的整数和小数, 这里显示的是25位小数,使用计算器,拆分前12位,后13位,就对上手册里的数值了. - 可以尝试修改分频系数
Int(N) Frac(F)
,能看到输出频率Analysis at
也发生了变化.仿真软件会自动实时计算. - 最后,我们再从代码的角度复刻这个例子的计算.
// 考虑到变量溢出截断,这里规定传参频率单位相同即可,不必一定是Hz.
// 计算分频系数,输入:基准频率输入(/k/M/GHz),RF频率输出(/k/M/GHz),RF基准分频系数;输出:整数部分,小数部分;
void int_frac_value(float REF_IN, float RF_OUT, float R, uint32_t *N, uint32_t *FRAC)
{
float f_PFD = REF_IN * ((1+0)/(R*(1+0))); // PFD频率
printf("f_PFD = %f\n",f_PFD);
float N_FRAC = RF_OUT / f_PFD; // 包含整数和小数部分的分频系数
printf("N_FRAC = RF_OUT / f_PFD\n%f = %f / %f\n", N_FRAC, RF_OUT, f_PFD);
N[0] = (uint32_t)N_FRAC; // 只取整数部分
printf("N = %d\n",N[0]);
FRAC[0] = (uint32_t)((N_FRAC - N[0]) * 33554432.0f); // 只取小数部分的前25位
printf("FRAC = %d\n",FRAC[0]);
}
PFD频率(f_PFD )
的公式中,D
和T
我都默认设置为0,只开放一个R
分频的设置.- 注意程序的变量储存最大4字节,32位,所以当变量过大时会截取.切记!因此程序设置允许传参为同数量级单位即可.
3.2.FMCW雷达斜坡设置成功范例
- 紧接着开始第二个范例的仿真,这个范例是生成
频率会周期变动
的,幅值也会周期变动
的,信号.
- 接下来看仿真设置过程:
- 一开始的基本设置和上一个范例差不多,就是固定频率改成了变动频率;
- 然后设置最大最小频率,和PDF固定输入频率,和参考时钟频率,其他设置一样.
- 然后进入到细节参数设置:
- 注意,修改参数之前,建议手动修改一次
TimeDomain - Stop Time
和TimeDomain - Max Time Step
的值,它代表了仿真输出的时间范围,如果不修改,默认会随着你的参数修改而自动改变,越大仿真需要的时间就越长,整个软件未响应卡死很久, TimeDomain - Type
选择Modulation
,就可以自定义频率变动参数,TimeDomain - Type - Modulation
就选择Sawtooth
,代表连续锯齿波,- 然后就能看到
TimeDomain - Type - Modulation - Ramp Dev
和TimeDomain - Type - Modulation - Mod Period
里可以填写偏差值和分频值了. - 直接照抄手册里计算好的答案,就能看到
Ramp Dev
和Mod Period
变成了题目要求的50MHz范围,和2ms周期间隔. - 最后再设置浮点数分频值,找到
FreqDomain - Analysis at
,这里填写的是最小输出频率.(目前的理解,根据公式和配置反推得到,但是仿真软件默认这个是中间值,而不是最小值.所以我也不确定.我尝试修改但是波形却没有变化?) - 手册里没有给出
Int(N)
和Frac(F)
,所以自己算一下,使用vc6.0
,输入参数,计算得到整数为232,小数为0是,正好输出5.8GHz,而整数为233时输出5.825GHz;直接修改仿真软件上的FreqDomain - Analysis at
值,也会自动计算整数和小数,可以相互校验一下. - 注意:数值
5800*1000*1000
已经超过了32位长度,属于溢出截取的情况.这种情况一定要注意,不然会计算错误,最后我采用kHz
的单位传参5800*1000
. - 所有参数修改完毕后,就能在输出仿真的
频率-时间图
看到效果;在200us
范围内,能看到阶梯效果的斜坡频率,保持一段时间后就步进,增加频率,依次循环.和手册的描述一直.然后修改仿真时间为5ms
,就能看到两个半的连续锯齿波了. - 到此仿真结束.总结,对于基本功能的寄存器配置,只需要计算以下几个参数即可;
- 第一个范例已经打包好计算
Int
和Frac
,接下来,只需要剩余的Ramp Dev
和Mod Period
即可完成对寄存器的配置.看看我下面的代码
// 范例代码被我吃了,
// 懒得写了,
// 授人以鱼不如授人以渔,我已经讲解到这了,应该都会写吧.
// 如果之后无聊再补上,
3.3.总结
- 在网上的一些教程中,会用到很多专业术语,对于零基础的我来说看得一头雾水.
- 比如啥是
带宽
?后来才明白,是指周期变动的频率范围,即最大频率减去最小频率. - 所以本篇教程尽量不采用专业术语,用很口头的预言简述应用中的实际效果.
- 希望本篇教程能帮助到你,如果你发现有错误的地方,请理性且详细的在评论区指出.我会立刻更正.谢谢.
4.补充.2024-1-19
- 推荐几篇论文,是我在知网搜到的,
- 详解ADF4159的功能与原理: 车载防撞雷达线性调频源的研究与设计_杨博_2011年
- 详解FMCW雷达测距原理: 24G调频连续波雷达收发前端的设计_刁攀_2020年
- 详解频率相位差细化原理: 一种提高相位测距精度的方法_曾真_2012年