目录
6.1.1.NOOP Register (offset = 0h) [reset = 0000h]
6.1.2.SYNC Register (offset = 2h) [reset = 0300h]
6.1.3.TRIGGER Register (offset = 5h) [reset = 0000h]
6.1.4.BRDCAST 寄存器(地址 = 6h)[当 RSTSEL 为逻辑低电平时复位 = 0000h,或者当 RSTSEL 为逻辑高电平时复位 = 8000h]
6.1.5.DAC-n 寄存器(地址 = 8h–9h)[当 RSTSEL 为逻辑低电平时复位 = 0000h,或者当 RSTSEL 为逻辑高电平时复位 = 8000h]
1.简述
16 位 DAC82002 是一款高精度、低功耗、双通道数模转换器 (DAC),具有无缓冲电压输出,DAC82002 包含一个上电复位电路,以确保 DAC 输出根据 RSTSEL 引脚的状态在零电平或中间电平上电,并保持在该电平,直到将有效代码写入器件。 RESET 引脚拉低后,所有内部寄存器都会异步复位。DAC82002 使用多功能三线串行外设接口 (SPI),运行时钟速率高达 50 MHz。
1.1.功能框图
注:有两路输出VOUTA和VOUTB
DAC参考电压来自外部输入
2.引脚配置和功能
3.DAC转换函数和寄存器结构
输入数据以直接二进制格式写入各个 DAC 数据寄存器。
上电或复位事件后,所有 DAC 寄存器均设置为零代码 (RSTSEL = AGND) 或中量程代码 (RSTSEL = VDD)
写入 DAC 数据寄存器的数据最初存储在 DAC 缓冲寄存器中。
DAC 输出的更新模式由 DAC_SYNC_EN 位(地址 2h)的状态决定。
在异步模式下(默认,DAC_SYNC_EN = 0),写入 DAC 缓冲寄存器会导致 DAC 活动寄存器立即更新。 DAC 输出(VOUTx 引脚)在 SYNC 的上升沿更新。
在同步模式下 (DAC_SYNC_EN = 1),写入 DAC 缓冲寄存器不会自动更新 DAC 活动寄存器。相反,更新仅在软件 LDAC 触发事件之后发生。软件 LDAC 触发通过 TRIGGER 寄存器(地址 5h)中的 LDAC 位生成。
DAC_DATA:加载到 DAC-A/B 寄存器(地址 8h/9h)的二进制代码的十进制等效值
4.复位
4.1.硬件复位
如果 RSTSEL = AGND,则 DAC 输出异步设置为零代码;如果 RSTSEL = VDD,则在 RESET 引脚拉低后立即将 DAC 输出异步设置为中刻度代码。 RESET 信号重置所有内部寄存器,这意味着所有寄存器都初始化为默认值。在写入序列开始之前将 RESET 引脚恢复为高电平。
4.2.软件复位
通过将保留代码 0x1010 写入 TRIGGER 寄存器(地址 5h)中的软复位位来启动器件软件复位事件。
5.编程
5.1.串行外设接口 (SPI)
DAC82002 通过使用 SYNC、SCLK 和 SDIN 的 3 线串行外设接口 (SPI) 进行控制。 串行接口的工作频率高达 50 MHz。输入移位寄存器宽度为 24 位
SPI 传输数据帧格式
串行时钟SCLK是连续时钟或门控时钟。 SYNC 的第一个下降沿启动操作周期。
当 SYNC 为高电平时,SCLK 和 SDIN 信号被阻止。器件内部寄存器在 SYNC 的上升沿从移位寄存器更新。
Register Address - Command Byte:7位来表示寄存器地址并且右对齐,参考下面寄存器映射。
16-Bit MSB-Aligned DAC Data:16 位 MSB 对齐 DAC 数据,对于不同寄存器写入不同的16位数据对应不同的操作,参考寄存器映射。
5.2.数据传输时序
对于 SPI 操作,SYNC 线在 SCLK 的至少 24 个下降沿保持低电平,并且寻址的 DAC 寄存器在 SYNC 上升沿更新。然而,如果 SYNC 线在第 24 个 SCLK 下降沿之前拉高,则该事件将充当写入序列的中断。移位寄存器复位并且写入序列被丢弃。如图 7-3 所示,数据缓冲区内容和 DAC 寄存器内容不会更新,操作模式也不会改变。
6.寄存器映射
6.1.寄存器
6.1.1.NOOP Register (offset = 0h) [reset = 0000h]
6.1.2.SYNC Register (offset = 2h) [reset = 0300h]
DAC-A/B-BRDCAST-EN :
当设置为 1 时,相应的 DAC 设置为在串行接口写入 BRDCAST 寄存器后更新输出。
当清为 0 时,串行接口写入 BRDCAST 寄存器后,相应的 DAC 输出保持不受影响
DAC-A/B-SYNC-EN
当设置为 1 时,DAC 输出设置为更新以响应 LDAC 触发(同步模式)。
当清为 0 时,DAC 输出设置为立即更新(异步模式)(默认)。
6.1.3.TRIGGER Register (offset = 5h) [reset = 0000h]
LDAC:将该位设置为 1 可同步加载 SYNC 寄存器中设置为同步模式的 DAC。该位会自动复位。
SOFT-RESET [3:0] :当设置为保留代码 1010 时,该位会将器件重置为默认状态。该位会自动复位。
6.1.4.BRDCAST 寄存器(地址 = 6h)[当 RSTSEL 为逻辑低电平时复位 = 0000h,或者当 RSTSEL 为逻辑高电平时复位 = 8000h]
写入 BRDCAST 寄存器会强制设置为从 SYNC 寄存器广播的 DAC 通道将活动寄存器数据更新为 BRDCAST-DATA 位。
6.1.5.DAC-n 寄存器(地址 = 8h–9h)[当 RSTSEL 为逻辑低电平时复位 = 0000h,或者当 RSTSEL 为逻辑高电平时复位 = 8000h]
数据以直接二进制格式 MSB 对齐。
DAC-A/B-DATA [15:0]:模拟电压对应的16位二进制数据
7.代码
7.1.bsp_spi_dac82002.c
#include "bsp_spi_dac82002.h"
/*
DAC82002模块:
GND ------ GND
VDD ------ 5V
SYNC ------ PD2/DAC82002_CS
SCLK ------ PC10/SPI3_SCK
DIN ------ PC12/SPI3_MOSI
------ PC11/SPI3_MISO --- DAC无读出需求
RSTSEL------ AGND,DAC 上电至零电平
DAC8562基本特性:
1、供电2.7 - 5V; 【本例使用5V】
2、参考电压2.5V,使用外部参考
对SPI的时钟速度要求: 高达50MHz, 速度很快.
SCLK下降沿读取数据, 每次传送24bit数据, 高位先传
*/
/* SYNC, 也就是CS片选 */
#define CS_CLK_ENABLE() __HAL_RCC_GPIOD_CLK_ENABLE()
#define CS_GPIO GPIOD
#define CS_PIN DAC82002_CS_Pin
#define CS_1() CS_GPIO->BSRR = CS_PIN
#define CS_0() CS_GPIO->BSRR = ((uint32_t)CS_PIN << 16U)
/* 定义电压和DAC值间的关系。 两点校准 x是dac y 是电压 0.1mV */
#define X1 0
#define Y1 0
#define X2 65535
#define Y2 25000
#define SPI_BUFFER_SIZE (4 * 1024)
uint8_t g_spiTxBuf[SPI_BUFFER_SIZE];
uint8_t g_spiRxBuf[SPI_BUFFER_SIZE];
uint32_t g_spiLen;
/**********************************************************************************************************
* 函 数 名: bsp_InitDAC82002
* 功能说明: 配置GPIO并初始化DAC82002寄存器
* 形 参: 无
* 返 回 值: 无
**********************************************************************************************************/
void bsp_InitDAC82002(void)
{
//配置GPIO
{
GPIO_InitTypeDef gpio_init;
//打开GPIO时钟
CS_CLK_ENABLE();
gpio_init.Mode = GPIO_MODE_OUTPUT_PP; //设置推挽输出
gpio_init.Pull = GPIO_NOPULL; //上下拉电阻不使能
gpio_init.Speed = GPIO_SPEED_FREQ_MEDIUM; //GPIO速度等级
gpio_init.Pin = CS_PIN;
HAL_GPIO_Init(CS_GPIO, &gpio_init);
}
/* 初始化DAC82002寄存器 */
{
/* 配置TRIGGER寄存器 */
DAC82002_WriteCmd((TRIGGER_RS << 16));
/* LDAC pin inactive for DAC-B and DAC-A 不使用LDAC引脚更新数据(同步模式),DAC 输出设置为立即更新(异步模式 */
DAC82002_WriteCmd((SYNC_RS << 16));
/*配置BRDCAST Register */
DAC82002_WriteCmd((BRDCAST_RS << 16));
/* 复位2个DAC到零电平, 输出0V */
DAC82002_SetDacData(0, 0);
DAC82002_SetDacData(1, 0);
}
}
/**********************************************************************************************************
* 函 数 名: bsp_spiTransfer
* 功能说明: 启动数据传输
* 形 参: 无
* 返 回 值: 无
**********************************************************************************************************/
void bsp_spiTransfer(void)
{
if (g_spiLen > SPI_BUFFER_SIZE)
{
return;
}
if(HAL_SPI_TransmitReceive(&hspi3, (uint8_t*)g_spiTxBuf, (uint8_t *)g_spiRxBuf, g_spiLen, 1000000) != HAL_OK)
{
Error_Handler();
}
}
/**********************************************************************************************************
* 函 数 名: DAC82002_WriteCmd
* 功能说明: 向SPI总线发送24个bit数据,取出3次8位数据放在缓冲区
* 形 参: _cmd : 数据
* 返 回 值: 无
**********************************************************************************************************/
void DAC82002_WriteCmd(uint32_t _cmd)
{
CS_0();
g_spiLen = 0;
g_spiTxBuf[g_spiLen++] = (_cmd >> 16);
g_spiTxBuf[g_spiLen++] = (_cmd >> 8);
g_spiTxBuf[g_spiLen++] = (_cmd);
bsp_spiTransfer();
CS_1();
}
/**********************************************************************************************************
* 函 数 名 : DAC82002复位函数
* 功能说明 : 异步复位,低电平有效,如果 RESET 为低电平,
* 并且RSTSEL = AGND,则所有 DAC 通道都会重置为零电平 (RSTSEL = AGND)
* 形 参 : 无
* 返 回 值 : 无
**********************************************************************************************************/
void DAC82002_Reset(void)
{
HAL_GPIO_WritePin(DAC82002_RESET_GPIO_Port, DAC82002_RESET_Pin, GPIO_PIN_RESET);
}
/**********************************************************************************************************
* 函 数 名: DAC82002_SetDacData
* 功能说明: 设置DAC输出,并立即更新。
* 形 参: _ch, 通道, 0-A , 1-B
* _data : 数据
* 返 回 值: 无
**********************************************************************************************************/
void DAC82002_SetDacData(uint8_t _ch, uint16_t _dac)
{
if (_ch == 0)
{
/* Write to DAC-A input register and update DAC-A; */
DAC82002_WriteCmd((DAC_A_RS << 16) | (_dac << 0));
}
else if (_ch == 1)
{
/* Write to DAC-B input register and update DAC-B; */
DAC82002_WriteCmd((DAC_B_RS << 16) | (_dac << 0));
}
}
/**********************************************************************************************************
* 函 数 名: CaculTwoPoint
* 功能说明: 根据2点直线方程,计算Y值
* 形 参: 2个点的坐标和x输入量
* 返 回 值: x对应的y值
**********************************************************************************************************/
int32_t CaculTwoPoint(int32_t x1, int32_t y1, int32_t x2, int32_t y2, int32_t x)
{
return y1 + ((int64_t)(y2 - y1) * (x - x1)) / (x2 - x1);
}
/**********************************************************************************************************
* 函 数 名: DAC82002_DacToVoltage
* 功能说明: 将DAC值换算为电压值,单位0.1mV
* 形 参: _dac 16位DAC字
* 返 回 值: 电压:单位0.1mV
**********************************************************************************************************/
uint16_t DAC82002_DacToVoltage(uint16_t _dac)
{
uint16_t y;
/* CaculTwoPoint(int32_t x1, int32_t y1, int32_t x2, int32_t y2, int32_t x);*/
y = CaculTwoPoint(X1, Y1, X2, Y2, _dac);
return y;
}
/**********************************************************************************************************
* 函 数 名: DAC82002_VoltageToDac
* 功能说明: 将电压值转换为DAC值
* 形 参: _volt 电压,单位0.1mV
* 返 回 值: 16位DAC字
**********************************************************************************************************/
uint16_t DAC82002_VoltageToDac(uint16_t _volt)
{
/* CaculTwoPoint(int32_t x1, int32_t y1, int32_t x2, int32_t y2, int32_t x);*/
return CaculTwoPoint(Y1, X1, Y2, X2, _volt);
}
7.2.bsp_spi_dac82002.h
#include <stdio.h>
#ifndef BSP_SPI_DAC82002_H
#define BSP_SPI_DAC82002_H
#endif
//寄存器地址
#define SYNC_RS 0x02 //0 000 0010
#define TRIGGER_RS 0x05 //0 000 0101
#define BRDCAST_RS 0x06 //0 000 0110
#define DAC_A_RS 0x08 //0 000 1000
#define DAC_B_RS 0x09 //0 000 1001
void bsp_InitDAC82002(void);
void bsp_spiTransfer(void);
void DAC82002_WriteCmd(uint32_t _cmd);
void DAC82002_SetDacData(uint8_t _ch, uint16_t _dac);
int32_t CaculTwoPoint(int32_t x1, int32_t y1, int32_t x2, int32_t y2, int32_t x);
uint16_t DAC82002_DacToVoltage(uint16_t _dac);
uint16_t DAC82002_VoltageToDac(uint16_t _volt);