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

  • 8
    点赞
  • 51
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
前言: 是德科技(NYSE:KEYS)是全球领先的电子测量公司,通过在无线、模块化和软件解决方案等领域的不断创新,为您提供全新的测量体验。是德科技专注于测量技术,旨在帮助科学家、研究人员和工程师精准和充满信心地应对最严苛的测量挑战。 越来越多的工程师开始选择是德科技示波器,因为它们能够帮助您: 利用屡获殊荣的示波器执行测试,从而加速将您的产品推向市场。这些示波器可以提供最快的更新速率、最深的存储器、独特的电容触摸屏,以及最广泛的示波器软件选件 利用可以信赖的测量生产出性能最高的产品。这些测量由具有业界领先信号完整性的示波器和最广泛的示波器探头提供 通过在一台主机中集成多种仪器以及轻松进行升级,实现最低的拥有成本 同时本文重点介绍了基于单片机STM32控制、Android显示的便携式数字示波器的毕业设计 数字示波器毕业设计概述: 基于单片机STM32控制的、并在Android上进行显示的便携式数字示波器。STM32单片机是一款性价比非常之高的处理器,最高时钟可达72M,完全能满足本设计的要求。采用Android设备作为显示平台,是本设计最大的一个特点。本设计的基本思路是,由单片机对ADC采样到的数据进行处理,再通过蓝牙把波形数据发送到Android设备上进行显示。同时由于Android设备都采用触摸屏,因此示波器的参数可以很方便的通过触摸屏进行设置。本设计采用Android设备取代液晶屏,并使用蓝牙进行数据传输,充分利用了Android设备的硬件资源。 由于A/D转换器的输入范围一般都比较小(低于2Vpp),不可能直接测量几十伏甚至是几百伏的信号。而且由于A/D转换器的分辨率有限,对于幅值很低的信号测量误差将会很大甚至是无法测量。所以在输入级必须要设计一个程控放大电路,以现实对信号进行不失真的处理,而后再送至A/D数模转换器,以达到A/D数模转换器的输入要求。基于本设计便携小巧的宗旨,和电路复杂度的考虑,本设计使用专用PGA芯片AD603,可以通过MCU来控制AD603的基准,进而实现不同放大倍数的调节。该电路优点是控制比较简单,且增益调节范围大,外围电路简单。缺点是成本稍微偏高。 AD603它是美国ADI公司的专利产品,是一个低噪、90MHz带宽增益可调的集成运放,如增益用分贝表示,则增益与控制电压成线性关系,压摆率为275V/μs。管脚间的连接方式决定了可编程的增益范围,增益在-11~+30dB时的带宽为90Mhz,增益在+9~+41dB时具有9MHz带宽,改变管脚间的连接电阻,可使增益处在上述范围内。该集成电路可应用于射频自动增益放大器、视频增益控制、A/D转换量程扩展和信号测量系统。 AD603封装引脚图: Android示波器电路原理图 电路城语:此资料为卖家免费分享,不提供技术支持,请大家使用前验证资料的正确性!如涉及版权问题,请联系管理员删除! 附件包含以下资料:

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值