1059|1

1239

帖子

68

TA的资源

纯净的硅(中级)

楼主
 

【STM32H7S78-DK】测评+SPI应用之驱动AD9833 [复制链接]

由于STM32H7S78是没有DAC外设的,因此要想产生模拟信号,通常有2种方法,一是PWM加输出滤波器,二是专用DDS芯片。

AD9833是一款低功耗、可编程波形发生器,能够产生正弦波、三角波和方波输出。各种类型的检测、信号激励和时域反射(TDR)应用都需要波形发生器。输出频率和相位可通过软件进行编程,调整简单。无需外部元件。频率寄存器为28位宽,时钟速率为25 MHz时,可以实现0.1 Hz的分辨率;时钟速率为1 MHz时,AD9833可以实现0.004 Hz的分辨率。

AD9833通过一个3线串行接口写入数据。该串行接口能够以最高40 MHz的时钟速率工作,并且与DSP和微控制器标准兼容。该器件采用2.3 V至5.5 V电源供电。主页特性:

特性
  • 数字可编程频率和相位
  • 当供电电压为3 V时,功耗为12.65 mW
  • 输出频率范围:0 MHz至12.5 MHz
  • 28位分辨率(25 MHz基准时钟时为0.1 Hz)
  • 正弦波/三角波/方波输出
  • 2.3 V至5.5 V电源供电
  • 无需外部元件
  • 三线式SPI接口
  • 扩展温度范围: -40 ℃至+105 ℃
  • 掉电选项
  • 10引脚MSOP封装
  • 通过汽车应用认证

AD9833-EP支持防务和航空航天应用(AQEC标准)

  • 下载 AD9833-EP数据手册 (pdf)
  • 温度范围: −55 ℃至+125 ℃
  • 受控制造基线
  • 一个装配/测试厂
  • 一个制造厂
  • 增强型产品变更通知
  • 认证数据可应要求提供
  • V62/14619-01XE DSCC图纸号

 

 使用SPI接口即可与AD9833通信,通常可以使用GPIO模拟方式或者硬件SPI接口,本帖使用硬件SPI接口。查看原理图,得知arduino接口上的SPI接口是SPI4,片选使用的是PF8,不是硬件片选信号:

SPI接口配置如下:

 

 

PF8配置为GPIO作为片选:

 

 

然后在AD98333.h头文件定义相关寄存器:

#ifndef INC_AD9833_H_
#define INC_AD9833_H_

#include "main.h"

/*** Redefine if necessary ***/
#define AD9833_SPI_PORT 		hspi4
extern SPI_HandleTypeDef 		AD9833_SPI_PORT;

/*** Control Register Bits (DataSheet AD9833 p. 14, Table 6) ***/
#define B28_CFG					(1 << 13)
#define HLB_CFG		  			(1 << 12)
#define F_SELECT_CFG			(1 << 11)
#define P_SELECT_CFG			(1 << 10)
#define RESET_CFG				(1 << 8)
#define SLEEP1_CFG				(1 << 7)
#define SLEEP12_CFG				(1 << 6)
#define OPBITEN_CFG				(1 << 5)
#define DIV2_CFG				(1 << 3)
#define MODE_CFG				(1 << 1)

/*** Bitmask to register access ***/
#define FREQ0_REG				0x4000
#define PHASE0_REG				0xC000
//#define FREQ1_ACCESS  			0x8000
//#define PHASE1_ACCESS 			0xE000

/*** Waveform Types (DataSheet p. 16, Table 15) ***/
#define WAVEFORM_SINE         	0
#define WAVEFORM_TRIANGLE     	MODE_CFG
#define WAVEFORM_SQUARE       	OPBITEN_CFG | DIV2_CFG
#define WAVEFORM_SQUARE_DIV2  	OPBITEN_CFG

/*** Sleep Modes ***/
#define NO_POWERDOWN	  		0
#define DAC_POWERDOWN			SLEEP12_CFG
#define CLOCK_POWERDOWN			SLEEP1_CFG
#define FULL_POWERDOWN			SLEEP12_CFG | SLEEP1_CFG

#define FMCLK	 				25000000
#define BITS_PER_DEG 			11.3777777777778	// 4096 / 360

typedef enum {
	wave_triangle,
	wave_square,
	wave_sine,
} WaveDef;


/*
 * [url=home.php?mod=space&uid=159083]@brief[/url] Set signal generation frequency
 * @param Frequency value in uint32_t format
 */
void AD9833_SetFrequency(uint32_t freq);

/*
 * @brief Set signal generation waveform
 * @param Waveform in WaveDef Type declared in .h file
 */
void AD9833_SetWaveform(WaveDef Wave);

/*
 * @brief Set signal generation phase
 * @param Phase in degrees in uint16_t format. Value can be large then 360
 */
void AD9833_SetPhase(uint16_t phase_deg);

/*
 * @brief AD9833 Initial Configuration
 * @param Type of Waveform, Frequency, Phase in degrees
 */
void AD9833_Init(WaveDef Wave, uint32_t freq, uint16_t phase_deg);

/*
 * @brief Enable or disable the output of the AD9833
 * @param Output state (ON/OFF)
 */
void AD9833_OutputEnable(uint8_t output_state);

/*
 * @brief Set Sleep Mode Function (Explained in datasheet Table 14)
 * @param Mode of sleep function defined in title
 */
void AD9833_SleepMode(uint8_t mode);

#endif /* INC_AD9833_H_ */
 

源码AD9833.c实现初始化、频率、相位设置:


//Setup Hardware SPI to POLATRITY HIGH, PHASE 1 EDGE

#include "AD9833.h"

uint8_t _waveform = WAVEFORM_SINE;
uint8_t _sleep_mode = NO_POWERDOWN;
uint8_t _freq_source = 0;
uint8_t _phase_source = 0;
uint8_t _reset_state = 0;

/*
 * @brief Set Chip Select pin to LOW state
 */
static void AD9833_Select(void)
{
	HAL_GPIO_WritePin(AD9833_FSYNC_GPIO_Port, AD9833_FSYNC_Pin, GPIO_PIN_RESET);
}

/*
 * @brief Set Chip Select pin to HIGH state
 */
static void AD9833_Unselect(void)
{
	HAL_GPIO_WritePin(AD9833_FSYNC_GPIO_Port, AD9833_FSYNC_Pin, GPIO_PIN_SET);
}

/*
 * @brief Send data by SPI protocol
 * @param Data variable in uint16_t format
*/
static void AD9833_WriteRegister(uint16_t data)
{
	AD9833_Select();
	uint8_t LByte = data & 0xff;
	uint8_t HByte = (data >> 8) & 0xff;
	HAL_SPI_Transmit(&AD9833_SPI_PORT, &HByte, 1, HAL_MAX_DELAY);
	HAL_SPI_Transmit(&AD9833_SPI_PORT, &LByte, 1, HAL_MAX_DELAY);
	AD9833_Unselect();
}

/*
 * @brief Update Control Register Bits
 */
static void AD9833_WriteCfgReg(void)
{
	uint16_t cfg = 0;
	cfg |= _waveform;
	cfg |= _sleep_mode;
	cfg |= (_freq_source ? F_SELECT_CFG : 0);	//it's unimportant because don't use FREQ1
	cfg |= (_phase_source ? P_SELECT_CFG : 0);	//it's unimportant because don't use PHASE1
	cfg |= (_reset_state ? RESET_CFG : 0);
	cfg |= B28_CFG;
	AD9833_WriteRegister(cfg);
}

void AD9833_SetWaveform(WaveDef Wave)
{
	if (Wave == wave_sine) 			_waveform = WAVEFORM_SINE;
	else if (Wave == wave_square) 	_waveform = WAVEFORM_SQUARE;
	else if (Wave == wave_triangle)	_waveform = WAVEFORM_TRIANGLE;
	AD9833_WriteCfgReg();
}

void AD9833_SetFrequency(uint32_t freq)
{
	// TODO: calculate max frequency based on refFrequency.
	// Use the calculations for sanity checks on numbers.
	// Sanity check on frequency: Square - refFrequency / 2
	// Sine/Triangle - refFrequency / 4

	if (freq > (FMCLK >> 1))	//bitwise FMCLK / 2
		freq = FMCLK >> 1;
	else if (freq < 0) freq = 0;

	uint32_t freq_reg = (float)freq * (float)((1 << 28) / FMCLK); // Tuning word

	uint16_t LSB = FREQ0_REG | (freq_reg & 0x3FFF);
	uint16_t MSB = FREQ0_REG | (freq_reg >> 14);

	AD9833_WriteCfgReg();	// Update Config Register
	AD9833_WriteRegister(LSB);
	AD9833_WriteRegister(MSB);
}

void AD9833_SetPhase(uint16_t phase_deg)
{
	if(phase_deg < 0) phase_deg = 0;
	else if (phase_deg > 360) phase_deg %= 360;
	uint16_t phase_val  = ((uint16_t)(phase_deg * BITS_PER_DEG)) &  0xFFF;
	AD9833_WriteRegister(PHASE0_REG | phase_val);
}

void AD9833_Init(WaveDef Wave, uint32_t freq, uint16_t phase_deg)
{
	AD9833_OutputEnable(0);
	AD9833_SetWaveform(Wave);
	AD9833_WriteCfgReg();
	AD9833_SetFrequency(freq);
	AD9833_SetPhase(phase_deg);
	AD9833_OutputEnable(1);
}

void AD9833_SleepMode(uint8_t mode)
{
	_sleep_mode = mode;
	AD9833_WriteCfgReg();
}

void AD9833_OutputEnable(uint8_t output_state)
{
	_reset_state = !output_state;
	AD9833_WriteCfgReg();
}

最后调用接口初始化:

AD9833_Init(wave_sine, 100, 0);

将输出频率100Hz的正弦波。

接线:

AD9833模块:

 

 

波形效果如下,可见正确驱动了芯片:

 

此帖出自stm32/stm8论坛

最新回复

用硬件SPI接口,片选使用的是PF8,这个值得借鉴,收藏   详情 回复 发表于 2024-10-15 07:24
点赞 关注
 

回复
举报

6809

帖子

0

TA的资源

五彩晶圆(高级)

沙发
 

用硬件SPI接口,片选使用的是PF8,这个值得借鉴,收藏

此帖出自stm32/stm8论坛
 
 

回复
您需要登录后才可以回帖 登录 | 注册

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/8 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表