STM32之AD9850驱动

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

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值