STM32F103ZET6+ADF4351+HMI串口屏
功能:
-
显示当前输出频率 -
100KHz步进,通过HMI屏幕触控修改 -
1MHz步进,通过HMI屏幕触控修改 -
实时修改输出频率,通过HMI屏幕触控修改
人机界面:
人机界面是通过陶晶驰串口屏来实现的,串口屏和单片机通过串口通信,只需设定相同的波特率,就可以实现通信。
HMI可以通过USART HMI软件来写界面,非常的简单方便。
具体界面如下:
- 输出频率:显示当前ADF4351输出频率
- 频率步进:如图所示,支持100KHz,1MHz的频率步进
- 频率校准:点击输入框,唤出数字键盘后,输入目标频率,点击OK, 按下校准键,修改成功,如下图:
STM32F103ZET6程序实现:
程序逻辑:
核心代码:
ADF4351.C
#include "ADF4351.h"
#include "delay.h"
#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;
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;
buf[0] = 0x05;
WriteToADF4351(4,buf);
buf[3] = 0x00;
buf[2] = 0xec;
buf[1] = 0x80;
buf[0] = 0x3C;
WriteToADF4351(4,buf);
buf[3] = 0x00;
buf[2] = 0x00;
buf[1] = 0x04;
buf[0] = 0xB3;
WriteToADF4351(4,buf);
buf[3] = 0x00;
buf[2] = 0x01;
buf[1] = 0x0E;
buf[0] = 0x42;
WriteToADF4351(4,buf);
buf[3] = 0x00;
buf[2] = 0x00;
buf[1] = 0x80;
buf[0] = 0x29;
WriteToADF4351(4,buf);
buf[3] = 0x00;
buf[2] = 0x2c;
buf[1] = 0x80;
buf[0] = 0x18;
WriteToADF4351(4,buf);
}
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;
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);
#endif
HMI.C
#include "HMI.h"
uint16_t trans = 0;
float fre_mhz = 300;
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];
fre_mhz = 0;
for ( i = 0; i < 4; i++)
{
fre_mhz = fre_mhz *10 + temp[i] - '0';
}
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();
delay_init(72);
uart_init(115200);
ADF4351Init();
ADF4351WriteFreq(fre_mhz);
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)]
工程源码已经上传,还在审核中。。。
|