前言
电赛已经结束啦!这一个多月以来,自己学到了很多东西,调试了很多模块,会点很简单的代码了。
AD9910(F103ZET6)
这里使用的是康威科技的dds模块,他家使用的是发f103rct6的主控,因为比赛最开始打算用的是f103zet6,所以进行了一个模块。我将他家的例程整理到一起了。此外,还有一些坑也可以注意一下。
GPIO初始化
/************************************************************
** 函数名称 :void AD9110_IOInit(void)
** 函数功能 :控制AD9910需要用到的IO口在此初始化
** 入口参数 :无
** 出口参数 :无
** 函数说明 :无
**************************************************************/
void AD9110_IOInit(void)
{
GPIO_InitTypeDef GPIO_InitStructure ;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOC, ENABLE); //使能PB,PE端口时钟
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz ;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP ;
GPIO_Init(GPIOB , &GPIO_InitStructure) ;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_8 | GPIO_Pin_2;
GPIO_Init(GPIOA , &GPIO_InitStructure) ;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_All ^ (GPIO_Pin_14 | GPIO_Pin_15);
GPIO_Init(GPIOC , &GPIO_InitStructure) ;
}
初始化代码比较多,我就不放在这里了。在文章末尾我放一个工程文件。
写频率和幅度
/************************************************************
** 函数名称 :void AD9910_FreWrite(void))
** 函数功能 :将需要的频率转换为对应的控制数据,保存进profile11并发送到芯片
** 入口参数 :目标频率,单位Hz,范围0~420000000
** 出口参数 :无
** 函数说明 :无
**************************************************************/
void AD9910_FreWrite(ulong Freq)
{
ulong Temp;
Temp = (ulong)Freq * 4.294967296; //将输入频率因子分为四个字节 主频1GHz,32位相位累加器,故每Hz在的控制字增量 delta = 4.294967296 = (2^32)/1000000000
profile11[7] = (uchar)Temp;
profile11[6] = (uchar)(Temp >> 8);
profile11[5] = (uchar)(Temp >> 16);
profile11[4] = (uchar)(Temp >> 24);
Txfrc();
}
/************************************************************
** 函数名称 :void AD9910_AmpWrite(void))
** 函数功能 :将幅度控制数据保存到profile11并写入芯片
** 入口参数 :幅度控制字,范围0~16383
** 出口参数 :无
** 函数说明 :14位幅度控制字,控制数据0~16383对应输出幅度0~800mV左右
**************************************************************/
void AD9910_AmpWrite(uint16_t Amp)
{
profile11[0] = (Amp % 16384) >> 8;
profile11[1] = (Amp % 16384) & 0xff;
Txfrc();
}
这里和他家的例程一样,没有改变。
扫频
第一个是开启自动扫频的函数,第二个可以设置扫频(可以进行往返扫频)。
这里注意一下!!!!最开始我以为对void AD9910_DRG_FreInit_AutoSet()这个函数设置disable以为可以在自动扫频一次后关闭扫频,但事实是这个函数是控制手动扫频的,也就是说你失能以后,这个模块还是处于扫频状态,如果需要写频率进去的话,可以重新初始化一遍,然后再write进去。
这里如果不想使用这个扫频的话,可以自己用简单的for循环进行扫频,此外还可以使用定时器进行扫频,定时器扫频的话等我有时间写另一篇ADF4351会提及。
/************************************************************
** 函数名称 :void AD9910_DRG_FreInit_AutoSet(FunctionalState autoSweepEn)
** 函数功能 :开启AD9910的数字斜坡模式DRG模式使能,使能数字斜坡控制频率,根据参数设置是否自动扫频
** 入口参数 :autoSweepEn:ENABLE,使能自动扫频,
此时无需外部控制,芯片自动从下限频率扫描到上限频率,再自动从上限频率扫描到下限频率,以此自动循环,实现上下双方向自动循环扫频
autoSweepEn:DISABLE,关闭自动扫频,
此时需外部引脚DRCTL脚控制扫频,不能自动扫频,扫频方向取决于DRCTL逻辑电平
DRCTL引脚置高(3.3V),AD9910从下限频率扫描到上限频率,扫描完成后保持在上限频率
DRCTL引脚置低( 0V),AD9910从上限频率扫描到下限频率,扫描完成后保持在下限频率
** 出口参数 :无
** 函数说明 :autoSweepEn设置为ENABLE时,自动扫频,扫描完成自动换向,扫频速率可极高;
autoSweepEn设置为DISABLE时,可由DRCTL脚程控或者外接线控,实现手动控制扫频
**************************************************************/
void AD9910_DRG_FreInit_AutoSet(FunctionalState autoSweepEn)
{
u8 CFR1[]={0x00,0x40,0x00,0x00}; // 使能AD9910反Sinc滤波
u8 CFR2[]={0x00,0x48,0x08,0x20}; // SYNC_CLK使能,数字斜坡使能 CFR2[21:20]= 00数字斜坡控制参数为频率(00:频率; 01:相位;1x:幅度)
int j;
if(autoSweepEn == ENABLE)
CFR2[1] |= 0X06;
CS = 0;
txd_8bit(0x00); // 将CFR1写入其地址0x00
for(j=0;j<4;j++)
{
txd_8bit(CFR1[j]);
}
CS = 1;
CS = 0;
txd_8bit(0x01); // 将CFR2写入其地址0x01
for(j=0;j<4;j++)
{
txd_8bit(CFR2[j]);
}
CS = 1;
UP_DAT = 0; // 更新AD9910
UP_DAT = 1;
UP_DAT = 0;
}
/************************************************************
** 函数名称 :void AD9910_DRG_FrePara_Set(u32 lowFre, u32 upFre, u32 posStep, u32 negStep, u16 posRate, u16 negRate)
** 函数功能 :按设定的频率上限,频率下限,上扫频步进,下扫频步进,及上扫频频点停留时间,下扫频频点停留时间,进行自动上下限循环扫频
** 入口参数 :
u32 lowFre:扫频下限频率 范围:1Hz~450000000Hz(450M Hz)
u32 upFre:扫频上限频率 范围:1Hz~450000000Hz(450M Hz)
u32 posStep:上扫频频率步进 范围:1Hz~450000000Hz(450M Hz)
u32 negStep:下扫频频率步进 范围:1Hz~450000000Hz(450M Hz)
u16 posRate:上扫频频点停留时间 范围:0~65535
u16 negRate:下扫频频点停留时间 范围:0~65535
** 出口参数 :无
** 函数说明 :扫频时间计算
上扫频,频点与频点间停留时间 dt_P = 4*pos_rate / Fsysclk
上扫频,总扫描频点数 N_P = (upper_limit - lower_limit) / inc_step
上扫频,扫频时间 T_P = dt_P * N_P
下扫频,频点与频点间停留时间 dt_N = 4*neg_rate / Fsysclk
下扫频,总扫描频点数 N_N = (upper_limit - lower_limit) / dec_step
下扫频,扫频时间 T_N = dt_N * N_N
故,总扫频时间T_ALL = T_P + T_N
= (4*pos_rate / Fsysclk)*( (upper_limit - lower_limit) / inc_step ) + (4*neg_rate / Fsysclk)*( (upper_limit - lower_limit) / dec_step )
其中,Fsysclk在本示例代码工程中,被配置为1GHz, Fsysclk = 1000000000
如以下配置 AD9910_DRG_Freq_set(400000, 300000000, 1200000, 2200000, 100,300);
T_ALL = (4*100 / 1000000000)*((300000000 - 400000) / 1200000) + (4*300 / 1000000000)*((300000000 - 400000) / 2200000)
= 263us
**************************************************************/
void AD9910_DRG_FrePara_Set(u32 lowFre, u32 upFre, u32 posStep, u32 negStep, u16 posRate, u16 negRate)
{
u32 upper , lower ,dec, inc;
u16 neg_rate , pos_rate;
int i;
u8 DRL[]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; // 数字斜坡限值
u8 DRS[]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; // 数字斜坡步长
u8 DRR[]={0x00,0x00,0x00,0x00}; // 数字斜坡速率
upper = (u32) upFre*4.294967296; // 频率字转换 4.294967296=(2^32)/1000000000
lower = (u32) lowFre*4.294967296;
dec = (u32)negStep*4.294967296;
inc = (u32)posStep*4.294967296;
neg_rate = negRate; // 时间 dt_N = 4*neg_rate / Fsysclk
pos_rate = posRate; // 时间 dt_P = 4*pos_rate / Fsysclk
DRL[7]=(u8) lower; //将上限下限频率、频率加减步进、频率加减速率写入u8数组方便写入相应的寄存器
DRL[6]=(u8)(lower>>8);
DRL[5]=(u8)(lower>>16);
DRL[4]=(u8)(lower>>24);
DRL[3]=(u8) upper;
DRL[2]=(u8)(upper>>8);
DRL[1]=(u8)(upper>>16);
DRL[0]=(u8)(upper>>24);
DRS[7]=(u8) inc;
DRS[6]=(u8)(inc>>8);
DRS[5]=(u8)(inc>>16);
DRS[4]=(u8)(inc>>24);
DRS[3]=(u8) dec;
DRS[2]=(u8)(dec>>8);
DRS[1]=(u8)(dec>>16);
DRS[0]=(u8)(dec>>24);
DRR[3]=(u8) pos_rate;
DRR[2]=(u8)(pos_rate>>8);
DRR[1]=(u8) neg_rate;
DRR[0]=(u8)(neg_rate>>8);
CS = 0;
txd_8bit(0x0B); // 将数字斜坡限值存入 0x0B
for(i=0;i<8;i++)
{
txd_8bit(DRL[i]);
}
CS = 1;
CS = 0;
txd_8bit(0x0C); // 将数字斜坡步长存入 0x0C
for(i=0;i<8;i++)
{
txd_8bit(DRS[i]);
}
CS = 1;
CS = 0;
txd_8bit(0x0D); // 将数字斜坡速率存入 0x0D
for(i=0;i<4;i++)
{
txd_8bit(DRR[i]);
}
CS = 1;
UP_DAT = 0; // 更新AD9910
UP_DAT = 1;
UP_DAT = 0;
}
结语
在比赛开始前,我跟老师一起做了下扫频测量电感,感觉还是挺准的,至少满足题目的百分之5的要求了,所以工程里面的主函数是画的电压曲线(当然仅仅是个雏形,最后我们选择了做H题,然后就是用了F4的板子,就又调试了一个F4版本的AD9910,有时间再更)
如果有问题的话,私信我就行了。
https://pan.baidu.com/s/1jnmIvCuC959W9htvFsUtcQ?pwd=ewkm
提取码:ewkm