STM32F103ZET6+ADF4351+HMI串口屏
目录
功能:
-
显示当前输出频率
-
100KHz步进,通过HMI屏幕触控修改
-
1MHz步进,通过HMI屏幕触控修改
-
实时修改输出频率,通过HMI屏幕触控修改
人机界面:
人机界面是通过陶晶驰串口屏来实现的,串口屏和单片机通过串口通信,只需设定相同的波特率,就可以实现通信。
HMI可以通过USART HMI软件来写界面,非常的简单方便。
具体界面如下:
- 输出频率:显示当前ADF4351输出频率
- 频率步进:如图所示,支持100KHz,1MHz的频率步进
- 频率校准:点击输入框,唤出数字键盘后,输入目标频率,点击OK, 按下校准键,修改成功,如下图:
STM32F103ZET6程序实现:
程序逻辑:
核心代码:
ADF4351.C
#include "ADF4351.h"
#include "delay.h"
//定义32位数据,每一个数字4位,要有8个数字
//这里的数字已经是配置好的了,直接调用就可以写入寄存器里面
#define ADF4351_R0 ((u32)0X2C8018)
#define ADF4351_R1 ((u32)0X8029)
#define ADF4351_R2 ((u32)0X10E42)
#define ADF4351_R3 ((u32)0X4B3)
#define ADF4351_R4 ((u32)0XEC803C)
#define ADF4351_R5 ((u32)0X580005)
#define ADF4351_R1_Base ((u32)0X8001)
#define ADF4351_R4_Base ((u32)0X8C803C)
#define ADF4351_R4_ON ((u32)0X8C803C)
#define ADF4351_R4_OFF ((u32)0X8C883C)
#define ADF4351_RF_OFF ((u32)0XEC801C)
#define ADF4351_PD_ON ((u32)0X10E42)
#define ADF4351_PD_OFF ((u32)0X10E02)
void ADF_Output_GPIOInit(void)
{
GPIO_InitTypeDef GPIO_InitStruct;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_8|GPIO_Pin_9|GPIO_Pin_10|GPIO_Pin_11;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIOB, &GPIO_InitStruct);
}
void ADF_Input_GPIOInit(void)
{
GPIO_InitTypeDef GPIO_InitStruct;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_8|GPIO_Pin_10|GPIO_Pin_11;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIOB, &GPIO_InitStruct);
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_9;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING ;
GPIO_Init(GPIOB, &GPIO_InitStruct);
}
void delay (int length)
{
while (length >0)
{
length--;
}
}
void WriteToADF4351(u8 count, u8 *buf)
{
u8 ValueToWrite = 0;
u8 i = 0;
u8 j = 0;
// ADF_Output_GPIOInit();
ADF4351_CE = 1;
delay_us(1);
ADF4351_CLK = 0;
ADF4351_LE = 0;
delay_us(1);
for(i = count; i>0; i--)
{
ValueToWrite = *(buf + i - 1);
for(j = 0; j < 8; j++)
{
if(0x80 == (ValueToWrite & 0x80))
{
ADF4351_OUTPUT_DATA = 1;
}
else
{
ADF4351_OUTPUT_DATA = 0;
}
delay_us(1);
ADF4351_CLK = 1;
delay_us(1);
ValueToWrite <<= 1;
ADF4351_CLK = 0;
}
}
ADF4351_OUTPUT_DATA = 0;
delay_us(1);
ADF4351_LE = 1;
delay_us(1);
ADF4351_LE = 0;
}
void ReadToADF4351(u8 count, u8 *buf)
{
u8 i = 0;
u8 j = 0;
u8 iTemp = 0;
u8 RotateData = 0;
ADF_Input_GPIOInit();
ADF4351_CE = 1;
delay_us(1);
ADF4351_CLK = 0;
ADF4351_LE = 0;
delay_us(1);
for(i = count; i > 0; i--)
{
for(j = 0; j < 8; j++)
{
RotateData <<= 1;
delay_us(1);
iTemp = ADF4351_INPUT_DATA;
ADF4351_CLK = 1;
if(0x01 == (iTemp & 0x01))
{
RotateData |= 1;
}
delay_us(1);
ADF4351_CLK = 0;
}
*(buf+i-1) = RotateData;
}
delay_us(1);
ADF4351_LE = 1;
delay_us(1);
ADF4351_LE = 0;
}
void ADF4351Init(void)
{
u8 buf[4] = {0,0,0,0};
ADF_Output_GPIOInit();
buf[3] = 0x00;
buf[2] = 0x58;
buf[1] = 0x00; //write communication register 0x00580005 to control the progress
buf[0] = 0x05; //to write Register 5 to set digital lock detector
WriteToADF4351(4,buf); //每次写入8位数据,共32位数据写入,因为每个寄存器有32位,每次控制一个寄存器
buf[3] = 0x00;
buf[2] = 0xec; //(DB23=1)The signal is taken from the VCO directly;(DB22-20:4H)the RF divider is 16;(DB19-12:50H)R is 80
buf[1] = 0x80; //(DB11=0)VCO powerd up;
buf[0] = 0x3C; //(DB5=1)RF output is enabled;(DB4-3=3H)Output power level is 5
WriteToADF4351(4,buf);
buf[3] = 0x00;
buf[2] = 0x00;
buf[1] = 0x04; //(DB14-3:96H)clock divider value is 150.
buf[0] = 0xB3;
WriteToADF4351(4,buf);
buf[3] = 0x00;
buf[2] = 0x01; //(DB6=1)set PD polarity is positive;(DB7=1)LDP is 6nS;
buf[1] = 0x0E; //(DB8=0)enable fractional-N digital lock detect;
buf[0] = 0x42; //(DB12-9:7H)set Icp 2.50 mA;
WriteToADF4351(4,buf); //(DB23-14:1H)R counter is 1
buf[3] = 0x00;
buf[2] = 0x00;
buf[1] = 0x80; //(DB14-3:6H)MOD counter is 6;
buf[0] = 0x29; //(DB26-15:6H)PHASE word is 1,neither the phase resync
WriteToADF4351(4,buf); //nor the spurious optimization functions are being used
//(DB27=1)prescaler value is 8/9
buf[3] = 0x00;
buf[2] = 0x2c;
buf[1] = 0x80;
buf[0] = 0x18; //(DB14-3:0H)FRAC value is 0;
WriteToADF4351(4,buf); //(DB30-15:140H)INT value is 320;
}
void WriteOneRegToADF4351(u32 Regster)
{
u8 buf[4] = {0,0,0,0};
buf[3] = (u8)((Regster>>24)&(0X000000FF));
buf[2] = (u8)((Regster>>16)&(0X000000FF));
buf[1] = (u8)((Regster>>8) &(0X000000FF));
buf[0] = (u8)((Regster)&(0X000000FF));
WriteToADF4351(4, buf);
}
void ADF4351_Init_some(void)
{
WriteOneRegToADF4351(ADF4351_R2);
WriteOneRegToADF4351(ADF4351_R3);
WriteOneRegToADF4351(ADF4351_R5);
}
void ADF4351WriteFreq(float Fre) //写入频率
{
u16 Fre_temp, N_Mul = 1, Mul_Core = 0;
u16 INT_Fre, Frac_temp, Mod_temp, i;
u32 W_ADF4351_R0 = 0, W_ADF4351_R1 = 0, W_ADF4351_R4 = 0;
float multiple;
if(Fre < 35.0) //频率限幅
{
Fre = 35.0;
}
if(Fre > 4400.0)
{
Fre = 4400.0;
}
Mod_temp = 1000;
Fre = ((float)((u32)(Fre * 10))) / 10;
Fre_temp = Fre;
for(i = 0; i < 10; i++)
{
if(((Fre_temp * N_Mul) >= 2199.9) && ((Fre_temp * N_Mul) <= 4400.1))
{
break;
}
Mul_Core++;
N_Mul = N_Mul * 2;
}
multiple = (Fre * N_Mul) / 25; //带宽出已固定为参考25M,若改参考频率,则应修改R4低字节 原本25 修改频率
INT_Fre = (u16)multiple;
Frac_temp = ((u32)(multiple * 1000)) % 1000;
while(((Frac_temp % 5) == 0) && ((Mod_temp % 5) == 0))
{
Frac_temp = Frac_temp / 5;
Mod_temp = Mod_temp / 5;
}
while(((Frac_temp % 2) == 0) && ((Mod_temp % 2) == 0))
{
Frac_temp = Frac_temp / 2;
Mod_temp = Mod_temp / 2;
}
Mul_Core %= 7;
W_ADF4351_R0 = (INT_Fre << 15) + (Frac_temp << 3);
W_ADF4351_R1 = ADF4351_R1_Base + (Mod_temp << 3);
W_ADF4351_R4 = ADF4351_R4_ON + (Mul_Core << 20);
WriteOneRegToADF4351(ADF4351_RF_OFF);
WriteOneRegToADF4351(W_ADF4351_R1);
WriteOneRegToADF4351(W_ADF4351_R0);
WriteOneRegToADF4351(W_ADF4351_R4);
}
ADF4351.H
#ifndef _ADF4351_H_
#define _ADF4351_H_
#include "sys.h"
#define ADF4351_CLK PBout(8)
#define ADF4351_OUTPUT_DATA PBout(9)
#define ADF4351_LE PBout(10)
#define ADF4351_CE PBout(11)
#define ADF4351_INPUT_DATA PBin(9)
void ADF4351Init(void);
void ReadToADF4351(u8 count, u8 *buf);
void WriteToADF4351(u8 count, u8 *buf);
void WriteOneRegToADF4351(u32 Regster);
void ADF4351_Init_some(void);
void ADF4351WriteFreq(float Fre); // (xxx.x) M Hz
#endif
HMI.C
#include "HMI.h"
uint16_t trans = 0;
float fre_mhz = 300; //adf4351输出300MHz
char buf[64];
/*****串口屏通信函数*****/
void HMI_choose(unsigned char ch)
{
char temp[4];
int i = 0;
switch (ch)
{
case 0x01:
LED0 = 0;
fre_mhz += 0.1;
ADF4351WriteFreq(fre_mhz);
sprintf(buf,"x0.val=%.0f",fre_mhz*10);
HMISends(buf);
HMISendb(0xff);
break;
case 0x02:
LED1 = 0;
fre_mhz -= 0.1;
ADF4351WriteFreq(fre_mhz);
sprintf(buf,"x0.val=%.0f",fre_mhz*10);
HMISends(buf);
HMISendb(0xff);
break;
case 0x03:
LED0 = 1;
fre_mhz += 1;
ADF4351WriteFreq(fre_mhz);
sprintf(buf,"x0.val=%.0f",fre_mhz*10);
HMISends(buf);
HMISendb(0xff);
break;
case 0x04:
LED1 = 1;
fre_mhz -= 1;
ADF4351WriteFreq(fre_mhz);
sprintf(buf,"x0.val=%.0f",fre_mhz*10);
HMISends(buf);
HMISendb(0xff);
break;
case 0x05:
temp[0] = USART_RX_BUF[1];
temp[1] = USART_RX_BUF[2];
temp[2] = USART_RX_BUF[3];
temp[3] = USART_RX_BUF[5]; //USART_RX_BUF[4]是小数点0x2e,我们跳过
fre_mhz = 0; //清零之前设定的频率,防止数据叠加
for ( i = 0; i < 4; i++)
{
fre_mhz = fre_mhz *10 + temp[i] - '0'; // 通过减去'0'可以将字符转换为int类型的数值
}
fre_mhz = fre_mhz * 0.1;
ADF4351WriteFreq(fre_mhz);
sprintf(buf,"x0.val=%.0f",fre_mhz*10);
HMISends(buf);
HMISendb(0xff);
break;
default :
break;
}
}
void HMIReceive(void)
{
if(USART_RX_STA & 0x8000)
{
trans = USART_RX_BUF[0];
HMI_choose(trans);
USART_RX_STA = 0;
}
}
void HMISends(char *buf1) //字符串发送函数
{
u8 i = 0;
while(1)
{
if(buf1[i] != 0)
{
USART_SendData(USART1, buf1[i]); //发送一个字节
while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET) {}; //等待发送结束
i++;
}
else
return ;
}
}
void HMISendb(u8 k) //字节发送函数
{
u8 i;
for(i = 0; i < 3; i++)
{
if(k != 0)
{
USART_SendData(USART1, k); //发送一个字节
while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET) {}; //等待发送结束
}
else
return ;
}
}
HMI.H
#ifndef __HMI_H
#define __HMI_H
#include "stm32f10x.h"
#include "usart.h"
#include "LED.h"
#include "adf4351.h"
extern uint16_t trans;
extern char buf[64];;
extern float fre_mhz;
void HMISends(char *buf1);
void HMISendb(u8 k);
void HMI_choose(unsigned char ch);
void HMIReceive(void);
#endif
MAIN.C
#include "delay.h"
#include "sys.h"
#include "string.h"
#include "usart.h"
#include "ADF4351.h"
#include "HMI.h"
#include "LED.h"
#include "stm32f10x.h"
void ADF4351Init(void);
void ReadToADF4351(u8 count, u8 *buf);
void WriteToADF4351(u8 count, u8 *buf);
void WriteOneRegToADF4351(u32 Regster);
void ADF4351WriteFreq(float Fre);
int main(void)
{
SystemInit(); //初始化RCC 设置系统主频为72MHZ
delay_init(72); //延时初始化
uart_init(115200);
ADF4351Init(); //ADF4351初始化函数
ADF4351WriteFreq(fre_mhz);//ADF4351芯片写入频率
LED_Init();
while(1)
{
HMIReceive();
}
}
硬件:
原理图
概述:
-
ADF4351结合外部环路滤波器和外部参考频率使用时,可实现小数N分频或整数N分频锁相环(PLL)频率合成器。
-
ADF4351具有一个集成电压控制振荡器(VCO), 其基波输 出频率范围为2200MHz至4400 MHz。
-
此外,利用1/2/4/8/ 16/32/64分频电路,用户可以产生低至35 MHz的RF输出频 率。
-
对于要求隔离的应用,RF输出级可以实现静音。静音 功能既可以通过引脚控制,也可以通过软件控制。
-
同时提供辅助RF输出,且不用时可以关断。 所有片内寄存器均通过简单的三线式接口进行控制。
-
该器件采用3.0 V至3.6 V电源供电,不用时可以关断。
连线
ADF4351 | STM32F103ZET6 |
---|---|
CLK | PB8 |
DATA | PB9 |
LE | PB10 |
CE | PB11 |
实物图:
[外链图片转存中…(img-6PzCE3yv-1628251825760)]
工程源码已经上传,点击我下载工程源码