AD9850是一款DDS,驱动如下:
/******************************************************************************
* 文 件 名 称:BspAD9850.c
* 文件功能概述:实现AD9850接口
* 文 件 作 者:
* 版 本:V1.0.0.0
* 修 订 记 录:2017-6-30创建
******************************************************************************/
/***************************相关配置*******************************************
AD9850采用SPI串行通信时,在CLK的上升沿取数据,首先发送低位数据
******************************************************************************/
#include "BspAD9850.h"
#define AD9850DelayUs(x) DelayUs(x)
/*
* 数据类型-AD9850的端口信息
*/
typedef struct AD9850CtrlStruc
{
E_SPIx AD9850xSPIx;
S_GpioCtrl AD9850xCS;
S_GpioCtrl AD9850xFQ;
S_GpioCtrl AD9850xRST;
}S_AD9850Ctrl;
/*
* 用于记录AD9850的端口信息
*/
static S_AD9850Ctrl stAD9850Ctrl[E_AD9850_Max] =
{
{
E_SPI_3,
{RCC_AHB1Periph_GPIOI,GPIOI,GPIO_Pin_0}, //CS
{RCC_AHB1Periph_GPIOH,GPIOH,GPIO_Pin_15}, //FQ
{RCC_AHB1Periph_GPIOH,GPIOH,GPIO_Pin_14} //RST
}
};
/*
*SPI总线上挂接的设备类型不一样,每次使用前均需对总线进行初始化
*/
static void AD9850InitSPIModule(E_AD9850 eAD9850)
{
SPI_InitTypeDef SPIxInitStruct;
/* Initialize the SPI_Direction member */
SPIxInitStruct.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
/* initialize the SPI_Mode member */
SPIxInitStruct.SPI_Mode = SPI_Mode_Master;
/* initialize the SPI_DataSize member */
SPIxInitStruct.SPI_DataSize = SPI_DataSize_8b;
/* Initialize the SPI_CPOL member */
SPIxInitStruct.SPI_CPOL = SPI_CPOL_Low;
/* Initialize the SPI_CPHA member */
SPIxInitStruct.SPI_CPHA = SPI_CPHA_1Edge;
/* Initialize the SPI_NSS member */
SPIxInitStruct.SPI_NSS = SPI_NSS_Soft;
/* Initialize the SPI_FirstBit member */
SPIxInitStruct.SPI_FirstBit = SPI_FirstBit_MSB;
/* Initialize the SPI_CRCPolynomial member */
SPIxInitStruct.SPI_CRCPolynomial = 7;
SPIxUpdateModule(stAD9850Ctrl[eAD9850].AD9850xSPIx,&SPIxInitStruct);
}
static __inline void AD9850_FQ_SET(E_AD9850 eAD9850)
{
GPIOxWriteBit(stAD9850Ctrl[eAD9850].AD9850xFQ.GPIOx,
stAD9850Ctrl[eAD9850].AD9850xFQ.GPIOxPinx,
1);
}
static __inline void AD9850_FQ_CLEAR(E_AD9850 eAD9850)
{
GPIOxWriteBit(stAD9850Ctrl[eAD9850].AD9850xFQ.GPIOx,
stAD9850Ctrl[eAD9850].AD9850xFQ.GPIOxPinx,
0);
}
static __inline void AD9850_CS_UNSELECTED(E_AD9850 eAD9850)
{
GPIOxWriteBit(stAD9850Ctrl[eAD9850].AD9850xCS.GPIOx,
stAD9850Ctrl[eAD9850].AD9850xCS.GPIOxPinx,
0);
}
static __inline void AD9850_CS_SELECTED(E_AD9850 eAD9850)
{
GPIOxWriteBit(stAD9850Ctrl[eAD9850].AD9850xCS.GPIOx,
stAD9850Ctrl[eAD9850].AD9850xCS.GPIOxPinx,
1);
}
static __inline void AD9850_RST_SET(E_AD9850 eAD9850)
{
GPIOxWriteBit(stAD9850Ctrl[eAD9850].AD9850xRST.GPIOx,
stAD9850Ctrl[eAD9850].AD9850xRST.GPIOxPinx,
1);
}
static __inline void AD9850_RST_CLEAR(E_AD9850 eAD9850)
{
GPIOxWriteBit(stAD9850Ctrl[eAD9850].AD9850xRST.GPIOx,
stAD9850Ctrl[eAD9850].AD9850xRST.GPIOxPinx,
0);
}
/*******************************************************************************
* 函 数 名:static void AD9850xReverseData(uint8 *data)
* 参 数:uint8 *data :要操作的数据
* 返 回:无
* 创 建 人:
* 创建时间:2017-6-30
* 详 述:翻转AD9850的数据,依次对高低位数据进行互换
原因 :使用的SPI端口和AD8403产生复用,AD8403先发送MSB,
而AD9850先发送LSB,SPI配置为先发送MSB,故需要翻转数据
* 修改记录:2017-6-30创建
*******************************************************************************/
static void AD9850xReverseData(uint8 *data)
{
uint8 temp=*data, i=0;
*data = 0;
for(i=0; i<8; i++)
{
if(temp&0x80)
{
*data |= 0x80;
}
else
{}
if(i >= 7)
{
break;
}
else
{}
*data = *data >> 1;
temp = temp << 1;
}
}
/*******************************************************************************
* 函 数 名:static sint8 AD9850xUploadFreq(E_AD9850 eAD9850)
* 参 数:E_AD9850 eAD9850:E_AD9850_1
* 返 回:无
* 创 建 人:
* 创建时间:2017-6-30
* 详 述:AD8403加载更新后的频率值
在FQ引脚上产生一个方波脉冲即可,最小时间为7ns
* 修改记录:2017-6-30创建
*******************************************************************************/
static sint8 AD9850xUploadFreq(E_AD9850 eAD9850)
{
/*在FQ_UP上产生一个方波*/
AD9850_FQ_CLEAR(eAD9850);
AD9850DelayUs(40);
AD9850_FQ_SET(eAD9850);
AD9850DelayUs(40);
AD9850_FQ_CLEAR(eAD9850);
AD9850DelayUs(40);
return 0;
}
/*******************************************************************************
* 函 数 名:sint8 AD9850xWakeUp(E_AD9850 eAD9850)
* 参 数:E_AD9850 eAD9850:E_AD9850_1
* 返 回:0 :正常返回 -1 :发生错误
* 创 建 人:
* 创建时间:2017-9-1
* 详 述:复位之后,AD9850可能处于power down下,此时发送一次配置,频率值和相位值
可任意设置(不起作用),要求power down的位置0,故数据可以设置为全0,
该操作类似于一个唤醒设备的操作
* 修改记录:2017-9-1创建
*******************************************************************************/
static sint8 AD9850xWakeUp(E_AD9850 eAD9850)
{
uint8 data[5]={0,0,0,0,0};
AD9850InitSPIModule(eAD9850);
AD9850_CS_SELECTED(eAD9850);
if(SPIxWriteBytes(stAD9850Ctrl[eAD9850].AD9850xSPIx, data, 5) != 5)
{
AD9850_CS_UNSELECTED(eAD9850);
return -1;
}
else
{}
AD9850_CS_UNSELECTED(eAD9850);
AD9850xUploadFreq(eAD9850);
return 0;
}
/*******************************************************************************
* 函 数 名:static sint8 AD9850xInitModule(E_AD9850 eAD9850,float FreqHz, uint8 phase)
* 参 数: E_AD9850 eAD9850:E_AD9850_1
float FreqHz : 初始的的频率值,单位是赫兹
uint8 phase : 初始的的相位值
* 返 回:0 :正常返回 -1 :发生错误
* 创 建 人:
* 创建时间:2017-6-30
* 详 述:配置AD9850模块
配置AD9850的初始频率
固定相位phrase为0
* 修改记录:2017-6-30创建
*******************************************************************************/
static sint8 AD9850xInitModule(E_AD9850 eAD9850, float FreqHz, uint8 phase)
{
AD9850xReset(eAD9850);
AD9850xWakeUp(eAD9850);
return AD9850xUpdateFreq(eAD9850, FreqHz, phase);
}
/*******************************************************************************
* 函 数 名:sint8 AD9850xUpdateFreq(E_AD9850 eAD9850,float FreqHz, uint8 phase)
* 参 数: E_AD9850 eAD9850:E_AD9850_1
float FreqHz : 需要设置的频率值,单位是赫兹
uint8 phase : 需要设置的相位值
* 返 回:0 :正常返回 -1 :发生错误
* 创 建 人:
* 创建时间:2017-6-30
* 详 述:更新AD9850的频率和相位
* 修改记录:2017-6-30创建
*******************************************************************************/
sint8 AD9850xUpdateFreq(E_AD9850 eAD9850, float FreqHz, uint8 phase)
{
uint8 data[5]={0,0,0,0,0};
uint32 TuningWord = 0;
uint8 PhaseWord = 0;
float temp = 0;
AD9850InitSPIModule(eAD9850);
temp = FreqHz / AD9850_CLKIN / CONST_1M;
TuningWord = (uint32)roundf((float)(temp * 0xffffffff));
PhaseWord = (uint8)roundf(phase / AD9850_PHASE_DIV);
/*SPI的配置是先发MSB,所以数据要处理*/
data[0] = (TuningWord & 0xff);
AD9850xReverseData(&data[0]);
data[1] = ((TuningWord >> 8) & 0xff);
AD9850xReverseData(&data[1]);
data[2] = ((TuningWord >> 16) & 0xff);
AD9850xReverseData(&data[2]);
data[3] = ((TuningWord >> 24) & 0xff);
AD9850xReverseData(&data[3]);
/*ctrl = 0x00, powerdown = 0*/
data[4] = PhaseWord & 0xF8;
AD9850xReverseData(&data[4]);
AD9850_CS_SELECTED(eAD9850);
if(SPIxWriteBytes(stAD9850Ctrl[eAD9850].AD9850xSPIx, data, 5) != 5)
{
AD9850_CS_UNSELECTED(eAD9850);
return -1;
}
else
{}
AD9850_CS_UNSELECTED(eAD9850);
AD9850xUploadFreq(eAD9850);
return 0;
}
/*******************************************************************************
* 函 数 名:sint8 AD9850xInit(E_AD9850 eAD9850, float FreqHz, uint8 phase)
* 参 数:E_AD9850 eAD9850:详见E_AD9850
float FreqHz : 初始的的频率值,单位是赫兹
uint8 phase : 初始的的相位值
* 返 回:0 :正常返回 -1 :SPI初始化发生错误
-2 :端口初始化发生错误 -3 :模块初始化发生错误
* 创 建 人:
* 创建时间:2017-6-30
* 详 述:AD9850初始化
* 修改记录:2017-6-30创建
*******************************************************************************/
sint8 AD9850xInit(E_AD9850 eAD9850, float FreqHz, uint8 phase)
{
sint8 ret = 0;
if(eAD9850 < E_AD9850_Max)
{
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
/*配置FQ_UP引脚、CS引脚、RST引脚*/
RCC_AHB1PeriphClockCmd(stAD9850Ctrl[eAD9850].AD9850xCS.GPIOxSource
| stAD9850Ctrl[eAD9850].AD9850xFQ.GPIOxSource
| stAD9850Ctrl[eAD9850].AD9850xRST.GPIOxSource,
ENABLE);
/*配置FQ引脚*/
GPIO_InitStructure.GPIO_Pin = stAD9850Ctrl[eAD9850].AD9850xFQ.GPIOxPinx;
GPIO_Init(stAD9850Ctrl[eAD9850].AD9850xFQ.GPIOx, &GPIO_InitStructure);
/*配置CS引脚*/
GPIO_InitStructure.GPIO_Pin = stAD9850Ctrl[eAD9850].AD9850xCS.GPIOxPinx;
GPIO_Init(stAD9850Ctrl[eAD9850].AD9850xCS.GPIOx, &GPIO_InitStructure);
/*配置RST引脚*/
GPIO_InitStructure.GPIO_Pin = stAD9850Ctrl[eAD9850].AD9850xRST.GPIOxPinx;
GPIO_Init(stAD9850Ctrl[eAD9850].AD9850xRST.GPIOx, &GPIO_InitStructure);
AD9850_FQ_CLEAR(eAD9850);
AD9850_CS_UNSELECTED(eAD9850);
AD9850_RST_CLEAR(eAD9850);
AD9850xInitModule(eAD9850,FreqHz,phase);
}
else
{
ret = -1;
}
return ret;
}
/*******************************************************************************
* 函 数 名:sint8 AD9850xReset(E_AD9850 eAD9850)
* 参 数:无
* 返 回:无
* 创 建 人:
* 创建时间:2017-6-30
* 详 述:AD9850复位
* 修改记录:2017-6-30创建
*******************************************************************************/
sint8 AD9850xReset(E_AD9850 eAD9850)
{
sint8 ret = 0;
if(eAD9850 < E_AD9850_Max)
{
/*拉高RST引脚,最短为5个时钟周期*/
AD9850_RST_CLEAR(eAD9850);
AD9850DelayUs(10);
AD9850_RST_SET(eAD9850);
AD9850DelayUs(10);
AD9850_RST_CLEAR(eAD9850);
}
else
{
ret = -1;
}
return ret;
}
头文件如下:
/******************************************************************************
* 文 件 名 称:BspAD9850.h
* 文件功能概述:实现AD9850驱动接口声明
* 文 件 作 者:
* 版 本:V1.0.0.0
* 修 订 记 录:2017-6-30创建
******************************************************************************/
#ifndef __BSP_AD9850_H__
#define __BSP_AD9850_H__
/*----------------------------------------------*
* 包含头文件 *
*----------------------------------------------*/
#include "..\BspInterface.h"
/*----------------------------------------------*
* 宏定义 *
*----------------------------------------------*/
#define AD9850_CLKIN (16)
#define AD9850_PHASE_DIV (11.25)
#define CONST_1M (1000000)
/*----------------------------------------------*
* 常量定义 *
*----------------------------------------------*/
/*----------------------------------------------*
* 外部变量说明 *
*----------------------------------------------*/
/*----------------------------------------------*
* 全局变量 *
*----------------------------------------------*/
/*----------------------------------------------*
* 模块级变量 *
*----------------------------------------------*/
typedef enum
{
E_AD9850_1=0x00,
E_AD9850_Max,
E_AD9850_Invalid
}E_AD9850;
/*----------------------------------------------*
* 外部函数原型说明 *
*----------------------------------------------*/
/*----------------------------------------------*
* 内部函数原型说明 *
*----------------------------------------------*/
sint8 AD9850xInit(E_AD9850 eAD9850, float FreqHz, uint8 phase);
sint8 AD9850xUpdateFreq(E_AD9850 eAD9850, float FreqHz, uint8 phase);
sint8 AD9850xReset(E_AD9850 eAD9850);
#endif