9. EBF-AD5689¶
9.1. 模块简介¶
EBF-AD5689 模块是野火电子推出的一款具有两路独立输出的 16 位 nanoDAC+ 数模转换模块,本模块使用亚德诺半导体 AD5689 芯片作为转换芯片, 具有低功耗高驱动能力的特性,具有最大正负 2LSB、偏置误差不超过正负 1.5mV、增益误差不超过 0.1%FSR 的特性,并可使用带回读或菊花链的最高 50MHz SPI, 能实现使用一个 SPI 外设一次对多个 DAC 模块进行数据读写。
9.2. 参数特性¶
特性 |
说明 |
---|---|
电压 |
5V |
电流 |
70mA |
可选增益 |
1 或 2 |
工作温度 |
-40℃-85℃ |
结构尺寸 |
644mmx448mm×124mm(包含插件原件引脚高度) |
输出通道 |
2 |
通信方式 |
与 SPI、QSPI 和 MICROWIRE 接口标准以及大多数 DSP 兼容 |
应用领域 |
光收发器、功率放大器、工业自动化、数据采集系统 |
9.3. 模块功能选择¶
功能选择跳线帽 |
说明 |
---|---|
J4 |
增益选择。接 GND 时 DAC 的输出 0V-10V。接 5V 时 DAC 输出 (-)10V-10V。 |
J5 |
上电复位选择。接 GND 时上电后输出零电平,接 5V 时上电后输出中间电平。 |
J6 |
A_OUT 输出基准选择 |
J7 |
B_OUT 输出基准选择 |
当增益选择 (J4) 接 GND 时,输出基准选择 (J6/J7) 应接 GND; 当增益选择接 5V 时,输出基准选择应 2V5。
9.4. 模块接口说明¶
特性 |
说明 |
---|---|
GND |
电源地 |
RESET |
异步复位输入 |
LDAC |
异步/同步模式选择 |
SYNC |
输入数据的帧同步信号 |
SCLK |
串行时钟输入 |
SDO |
串行数据输出 |
SDIN |
串行数据输入 |
5V |
电源 5V |
9.5. 硬件连接¶
配套开发板硬件连接方式如下,
模块引脚 |
GND |
SYNC |
SCLK |
SDO |
SDIN |
5V |
---|---|---|---|---|---|---|
F103MINI |
GND |
PA4 |
PA5 |
A6 |
A7 |
5V |
F103 指南者 |
GND |
PA4 |
PA5 |
A6 |
A7 |
5V |
F103 霸道 |
GND |
PA4 |
PA5 |
A6 |
A7 |
5V |
F407 霸天虎 |
GND |
PA3 |
PB3 |
PB4 |
PB5 |
5V |
F407 骄阳 |
GND |
PI0 |
PI1 |
PI2 |
PI3 |
5V |
F429 挑战者 |
GND |
PF6 |
PF7 |
PF8 |
PF9 |
5V |
F767 挑战者 |
GND |
PF6 |
PF7 |
PF8 |
PF9 |
5V |
H743 挑战者 |
GND |
PF6 |
PF7 |
PF8 |
PF9 |
5V |
H743_PRO |
GND |
PF6 |
PF7 |
PF8 |
PF9 |
5V |
H743 繁星 |
GND |
PI0 |
PI1 |
PI2 |
PI3 |
5V |
H750_PRO |
GND |
PF6 |
PF7 |
PF8 |
PF9 |
5V |
9.6. 单通道输出正弦波¶
9.6.1. 实验现象¶
这里以 STM32F103霸道 开发板为例,根据上面的硬件连接信息,将模块与开发板进行连接,再用USB线连接开发板与电脑,上电后打开野火多功能调试助手, 选择与开发板连接的端口号打开后将 单通道输出正弦波 例程编译下载至开发板。
上位机会打印如下信息,
用示波器测量 A_OUT 口会出现如下波形,
9.6.2. 例程介绍¶
本例程采用的硬件SPI,硬件SPI在《SPI基础知识》一文已经介绍,不再赘述,这里主要分析代码框架。
在编写AD5689模块驱动时,也要考虑更改硬件环境的情况。我们把AD5689模块引脚相关的宏定义到”bsp_ad5689.h”文件中, 在更改或移植的时候只用改宏定义就可以。
这里采用的SPI1,输入数据的帧同步信号引脚为A4,时钟引脚为A5,SDO引脚为A6,SDIN引脚为A7,具体定义如下,
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | // ... ...
#define AD5689_SPIx SPI1
#define AD5689_SPIx_CLK_ENABLE() __HAL_RCC_SPI1_CLK_ENABLE()
#define AD5689_GPIO_CLK_ENABLE() __HAL_RCC_GPIOA_CLK_ENABLE()
#define AD5689_SYNC_Pin GPIO_PIN_4 //SYNC
#define AD5689_SYNC_GPIO_Port GPIOA
#define AD5689_SCK_Pin GPIO_PIN_5 //SCLK
#define AD5689_SCK_GPIO_Port GPIOA
#define AD5689_MISO_Pin GPIO_PIN_6 //SDO
#define AD5689_MISO_GPIO_Port GPIOA
#define AD5689_MOSI_Pin GPIO_PIN_7 //SDIN
#define AD5689_MOSI_GPIO_Port GPIOA
// ... ...
|
AD5689_Init函数为ad5689模块的初始化函数,在这里调用了 AD5689_GPIO_Config 函数对硬件进行初始化,复位模块之后屏失能同步功能,
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | void AD5689_Init(void)
{
/* AD5689引脚和SPI初始化 */
AD5689_GPIO_Config();
/* 模块复位 */
AD5689_RESET_L;
HAL_Delay(5);
AD5689_RESET_H;
HAL_Delay(5);
AD5689_Reset();
/* LDAC屏蔽寄存器设置,失能LDAC,不采用同步功能 */
AD5689_LDAC_MASK(LDAC_Disable,LDAC_Disable);
}
|
AD5689_GPIO_Config函数主要是对引脚的初始化及SPI的配置,需要注意的是单片机的 MISO(主入从出)对应AD5689芯片是 SDO(输出), MOSI(主出从入)对应AD5689芯片的SDIN(输入)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 | void AD5689_GPIO_Config(void)
{
GPIO_InitTypeDef GPIO_InitStruct;
/* 使能SPI外设以及SPI引脚时钟 */
AD5689_SPIx_CLK_ENABLE();
AD5689_GPIO_CLK_ENABLE();
/* SCK */
GPIO_InitStruct.Pin = AD5689_SCK_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(AD5689_SCK_GPIO_Port, &GPIO_InitStruct);
/* MISO <--> SDO, MOSI <--> SDIN*/
GPIO_InitStruct.Pin = AD5689_MISO_Pin|AD5689_MOSI_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(AD5689_MISO_GPIO_Port, &GPIO_InitStruct);
/* SYNC */
GPIO_InitStruct.Pin = AD5689_SYNC_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(AD5689_SYNC_GPIO_Port, &GPIO_InitStruct);
/* SPI外设配置 */
hspi_AD5689.Instance = AD5689_SPIx;
hspi_AD5689.Init.Mode = SPI_MODE_MASTER; //主模式
hspi_AD5689.Init.Direction = SPI_DIRECTION_2LINES; //全双工
hspi_AD5689.Init.DataSize = SPI_DATASIZE_8BIT; //数据位为8位
hspi_AD5689.Init.CLKPolarity = SPI_POLARITY_LOW; //CPOL=0,LOW
hspi_AD5689.Init.CLKPhase = SPI_PHASE_2EDGE; //CPHA为数据线的第二个变化沿
hspi_AD5689.Init.NSS = SPI_NSS_SOFT; //软件控制NSS
hspi_AD5689.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_32; //32分频
hspi_AD5689.Init.FirstBit = SPI_FIRSTBIT_MSB; //最高位先发送
hspi_AD5689.Init.TIMode = SPI_TIMODE_DISABLE; //TIMODE模式关闭
hspi_AD5689.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE; //CRC关闭
hspi_AD5689.Init.CRCPolynomial = 7; //默认值,无效
HAL_SPI_Init(&hspi_AD5689); //初始化
}
|
再看一下main函数,同样先初始化系统时钟,初始化HAL库及串口配置,初始化按键和AD5689,在循环中不断输出变化的波形。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | int main(void)
{
/* 系统时钟初始化成72MHz */
SystemClock_Config();
/* HAL 库初始化 */
HAL_Init();
/* 配置串口1为:115200 8-N-1 */
DEBUG_USART_Config();
printf("欢迎使用野火 F103 AD5689单通道输出正弦波 例程\r\n");
/* 按键初始化 */
Key_GPIO_Config();
/* AD5689初始化 */
AD5689_Init();
while (1)
{
/* 输出波形 */
AD5689_Sine();
}
}
|
最后是 AD5689_Sine 函数中使用AD5689_WriteUpdate_DACREG函数改变AD5689输出的电压,Sine16bit 波形数据是有工程中的 正弦波表制作脚本 生成的。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | /* 波形数据 ---------------------------------------------------------*/
const uint16_t Sine16bit[128] = {
32768, 34388, 36005, 37614, 39210, 40791, 42353, 43891,
45401, 46881, 48326, 49733, 51099, 52420, 53693, 54914,
56081, 57192, 58242, 59230, 60154, 61010, 61797, 62513,
63157, 63726, 64219, 64635, 64974, 65233, 65413, 65513,
65533, 65473, 65333, 65113, 64814, 64437, 63982, 63451,
62844, 62164, 61412, 60590, 59700, 58744, 57724, 56644,
55505, 54310, 53062, 51765, 50422, 49035, 47608, 46145,
44650, 43125, 41575, 40003, 38414, 36811, 35198, 33578,
31958, 30338, 28725, 27122, 25533, 23961, 22411, 20886,
19391, 17928, 16501, 15114, 13771, 12474, 11226, 10031,
8892, 7812, 6792, 5836, 4946, 4124, 3372, 2692,
2085, 1554, 1099, 722, 423, 203, 63, 3,
23, 123, 303, 562, 901, 1317, 1810, 2379,
3023, 3739, 4526, 5382, 6306, 7294, 8344, 9455,
10622, 11843, 13116, 14437, 15803, 17210, 18655, 20135,
21645, 23183, 24745, 26326, 27922, 29531, 31148, 32768
};
uint32_t Idx = 0;
void AD5689_Sine(void)
{
uint16_t val;
val = Sine16bit[Idx];
Idx++;
/* 写入和更新DAC通道A */
AD5689_WriteUpdate_DACREG(DAC_A,val);
if(Idx==128)
Idx = 0;
HAL_Delay(5);
}
|