dac8568驱动OK
This commit is contained in:
parent
065e3b4c5b
commit
d3dc45ae2d
|
@ -198,8 +198,8 @@ extern "C"
|
|||
#define DAC1_MISO_Pin GPIO_PIN_4
|
||||
#define DAC1_MISO_GPIO_Port GPIOB
|
||||
//DAC8568引脚定义
|
||||
#define DAC8568_CS_Pin GPIO_PIN_15
|
||||
#define DAC8568_CS_GPIO_Port GPIOD
|
||||
#define DAC8568_SYNC_Pin GPIO_PIN_15
|
||||
#define DAC8568_SYNC_GPIO_Port GPIOD
|
||||
#define DAC8568_SCLK_Pin GPIO_PIN_10
|
||||
#define DAC8568_SCLK_GPIO_Port GPIOC
|
||||
#define DAC8568_DIN_Pin GPIO_PIN_12
|
||||
|
|
|
@ -802,34 +802,37 @@ void start_dac161s997_test_task(void const *argument)
|
|||
/* USER CODE END Header_start_dac8568_test_task */
|
||||
void start_dac8568_test_task(void const *argument)
|
||||
{
|
||||
/* USER CODE BEGIN start_dac8568_test_task */
|
||||
static float test_voltage = 0.0f; // 测试电压值
|
||||
static uint8_t channel = 0; // 当前测试通道
|
||||
static TickType_t last_update_time = 0;
|
||||
TickType_t current_time;
|
||||
|
||||
// 等待系统稳定
|
||||
osDelay(100);
|
||||
// // 初始化DAC8568
|
||||
DAC8568_Init();
|
||||
osDelay(100);
|
||||
// SPI3裸发测试
|
||||
uint8_t test_tx[4] = {0xAA, 0x55, 0xFF, 0x00};
|
||||
uint8_t test_rx[4] = {0};
|
||||
|
||||
for (;;) {
|
||||
// 拉低CS
|
||||
HAL_GPIO_WritePin(DAC8568_CS_GPIO_Port, DAC8568_CS_Pin, GPIO_PIN_RESET);
|
||||
// 发送数据
|
||||
HAL_SPI_TransmitReceive(&hspi3, test_tx, test_rx, 4, 1000);
|
||||
// 拉高CS
|
||||
HAL_GPIO_WritePin(DAC8568_CS_GPIO_Port, DAC8568_CS_Pin, GPIO_PIN_SET);
|
||||
// 初始化DAC8568
|
||||
DAC8568_Init(&hspi3); // 使用SPI3
|
||||
HAL_Delay(10);
|
||||
|
||||
// 启用静态内部参考(2.5V)
|
||||
DAC8568_EnableStaticInternalRef();
|
||||
|
||||
osDelay(10);
|
||||
while(1)
|
||||
{
|
||||
uint16_t i = 65535;
|
||||
//DAC8568_WriteAndUpdate(CHANNEL_A, (uint16_t)i);
|
||||
//DAC8568_WriteAndUpdate(CHANNEL_B, (uint16_t)i);
|
||||
//DAC8568_WriteAndUpdate(CHANNEL_C, (uint16_t)i);
|
||||
//DAC8568_WriteAndUpdate(CHANNEL_D, (uint16_t)i);
|
||||
DAC8568_WriteAndUpdate(CHANNEL_E, (uint16_t)i);
|
||||
//DAC8568_WriteAndUpdate(CHANNEL_F, (uint16_t)i);
|
||||
DAC8568_WriteAndUpdate(CHANNEL_G, (uint16_t)i);
|
||||
//DAC8568_WriteAndUpdate(CHANNEL_H, (uint16_t)i);
|
||||
|
||||
|
||||
// for (int i = 65535; i >= 0; i = i - 4096) // 从65535到0,步长4096
|
||||
// {
|
||||
|
||||
// // 写入并更新所有通道的值
|
||||
// DAC8568_WriteAndUpdate(BROADCAST, (uint16_t)i);
|
||||
|
||||
// // 计算电压值 (假设Vref=2.5V,16位分辨率,2倍增益)
|
||||
// float voltage = 2.5f * 2.0f * i / 65536.0f;
|
||||
|
||||
// 延时2秒
|
||||
osDelay(2000);
|
||||
//}
|
||||
}
|
||||
|
||||
|
||||
/* Infinite loop */
|
||||
|
||||
/* USER CODE END start_dac8568_test_task */
|
||||
}
|
Binary file not shown.
|
@ -1,96 +1,303 @@
|
|||
#include "DAC8568.h"
|
||||
#include "stm32f4xx_hal.h" // 添加HAL库头文件
|
||||
/*
|
||||
* DAC8568/DAC8168/DAC8568 驱动程序
|
||||
* 作者: 雪豹
|
||||
*/
|
||||
#include "dac8568.h"
|
||||
#include "main.h"
|
||||
#include "user_spi.h"
|
||||
#include <stdint.h> // 添加标准整型定义
|
||||
|
||||
#define DAC_MAX_VALUE 65535
|
||||
static SPI_HandleTypeDef *hspi_dac; // SPI句柄指针,用于SPI通信
|
||||
|
||||
/**
|
||||
* @brief DAC8568通用写函数
|
||||
* @param cmd 命令类型:0-初始化内部参考电压,1-写入并更新DAC值
|
||||
* @param channel 通道号(0-7),仅在cmd=1时有效
|
||||
* @param value DAC值(0-65535)或命令值,根据cmd决定
|
||||
* @return void
|
||||
* @brief 初始化DAC8568驱动。
|
||||
* @param hspi SPI外设句柄指针。
|
||||
* @note 此函数会保存SPI句柄,并将CS和LDAC引脚初始化为高电平。
|
||||
* 默认执行软件复位,可选启用内部参考电压。
|
||||
*/
|
||||
void DAC8568_Write(uint8_t cmd, uint8_t channel, uint32_t value)
|
||||
void DAC8568_Init(SPI_HandleTypeDef *hspi)
|
||||
{
|
||||
uint8_t tx_data[4];
|
||||
uint8_t rx_data[4] = {0}; // Initialize receive buffer
|
||||
uint32_t send_data;
|
||||
|
||||
// 根据命令类型准备发送数据
|
||||
if(cmd == 0) // 初始化内部参考电压
|
||||
{
|
||||
send_data = DAC8568_EN_INTER_REF_STATIC;
|
||||
}
|
||||
else // 写入并更新DAC值
|
||||
{
|
||||
// 输入参数合法性检查
|
||||
if(channel > 7)
|
||||
{
|
||||
channel = 7;
|
||||
}
|
||||
if(value > DAC_MAX_VALUE)
|
||||
{
|
||||
value = DAC_MAX_VALUE;
|
||||
}
|
||||
|
||||
send_data = DAC8568_WRITE_UPDATE_SEL_DAC;
|
||||
send_data |= (channel << 20);
|
||||
send_data |= (value << 4);
|
||||
}
|
||||
|
||||
// 准备发送数据
|
||||
tx_data[0] = (uint8_t)(send_data >> 24);
|
||||
tx_data[1] = (uint8_t)(send_data >> 16);
|
||||
tx_data[2] = (uint8_t)(send_data >> 8);
|
||||
tx_data[3] = (uint8_t)(send_data & 0xFF);
|
||||
|
||||
// 开始SPI传输
|
||||
DAC8568_CS_L; // 拉低CS,使能SPI接口
|
||||
extern SPI_HandleTypeDef hspi3; // 声明外部SPI句柄
|
||||
spi_transmit_receive(&hspi3, tx_data, rx_data, 4); // 使用hspi3发送4字节数据
|
||||
DAC8568_CS_H; // 拉高CS,禁止SPI接口
|
||||
hspi_dac = hspi; // 保存SPI句柄
|
||||
|
||||
// 初始化CS和LDAC引脚为高电平(空闲状态)
|
||||
HAL_GPIO_WritePin(DAC8568_CS_GPIO_Port, DAC8568_CS_Pin, GPIO_PIN_SET);
|
||||
HAL_GPIO_WritePin(DAC8568_LDAC_GPIO_Port, DAC8568_LDAC_Pin, GPIO_PIN_SET);
|
||||
|
||||
// 执行软件复位
|
||||
DAC8568_SoftwareReset();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 初始化DAC8568芯片
|
||||
* @return void
|
||||
* @brief 向DAC指定通道的输入寄存器写入数据。
|
||||
* @param channel 目标DAC通道 (CHANNEL_A 到 CHANNEL_H, 或 BROADCAST)。
|
||||
* @param data 要写入的16位数据。
|
||||
*/
|
||||
void DAC8568_Init(void)
|
||||
void DAC8568_Write(uint8_t channel, uint16_t data)
|
||||
{
|
||||
//初始化GPIO和SPI
|
||||
dac8568_spi_init();
|
||||
// 将LDAC置低,DAC8568处于同步模式
|
||||
DAC8568_LD_L;
|
||||
// 初始化内部参考电压
|
||||
DAC8568_Write(0, 0, 0);
|
||||
|
||||
uint8_t txData[4];
|
||||
|
||||
// 构造32位帧
|
||||
txData[0] = 0b00000000 | (CMD_WRITE_INPUT_REG & 0b00001111);
|
||||
txData[1] = ((channel & 0b00001111) << 4) | ((data >> 12) & 0b00001111);
|
||||
txData[2] = (data >> 4) & 0xFF;
|
||||
txData[3] = ((data & 0b00001111) << 4) | 0b00000000;
|
||||
|
||||
// 执行SPI传输
|
||||
HAL_GPIO_WritePin(DAC8568_CS_GPIO_Port, DAC8568_CS_Pin, GPIO_PIN_RESET);
|
||||
HAL_SPI_Transmit(hspi_dac, txData, 4, HAL_MAX_DELAY);
|
||||
HAL_GPIO_WritePin(DAC8568_CS_GPIO_Port, DAC8568_CS_Pin, GPIO_PIN_SET);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 设置DAC8568指定通道的电压值
|
||||
* @param mCh 通道号(0-7)
|
||||
* @param mVol 电压值(0-2.5V)
|
||||
* @return void
|
||||
* @brief 更新DAC指定通道的输出。
|
||||
* @param channel 目标DAC通道 (CHANNEL_A 到 CHANNEL_H, 或 BROADCAST)。
|
||||
*/
|
||||
void dac8568_set_voltage(unsigned char mCh, float mVol)
|
||||
void DAC8568_Update(uint8_t channel)
|
||||
{
|
||||
float mDatafloat;
|
||||
uint16_t mDtashort;
|
||||
|
||||
// 将电压值转换为DAC值
|
||||
mDatafloat = mVol * (65536/(5*1.91));
|
||||
mDtashort = (uint16_t)mDatafloat;
|
||||
mDtashort &= 0xffff;
|
||||
|
||||
// 限制DAC值范围
|
||||
if(mDtashort > 65535)
|
||||
mDtashort = 65535;
|
||||
|
||||
// 写入并更新DAC值
|
||||
DAC8568_Write(1, mCh, mDtashort);
|
||||
uint8_t txData[4];
|
||||
|
||||
txData[0] = 0b00000000 | (CMD_UPDATE_DAC_REG & 0b00001111);
|
||||
txData[1] = ((channel & 0b00001111) << 4) | 0b00000000;
|
||||
txData[2] = 0;
|
||||
txData[3] = 0;
|
||||
|
||||
HAL_GPIO_WritePin(DAC8568_CS_GPIO_Port, DAC8568_CS_Pin, GPIO_PIN_RESET);
|
||||
HAL_SPI_Transmit(hspi_dac, txData, 4, HAL_MAX_DELAY);
|
||||
HAL_GPIO_WritePin(DAC8568_CS_GPIO_Port, DAC8568_CS_Pin, GPIO_PIN_SET);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 向DAC指定通道的输入寄存器写入数据并立即更新其模拟输出。
|
||||
* @param channel 目标DAC通道 (CHANNEL_A 到 CHANNEL_H)。
|
||||
* @param data 要写入的16位数据。
|
||||
*/
|
||||
void DAC8568_WriteAndUpdate(uint8_t channel, uint16_t data)
|
||||
{
|
||||
uint8_t txData[4];
|
||||
|
||||
txData[0] = 0b00000000 | (CMD_WRITE_INPUT_UPDATE_ONE & 0b00001111);
|
||||
txData[1] = ((channel & 0b00001111) << 4) | ((data >> 12) & 0b00001111);
|
||||
txData[2] = (data >> 4) & 0xFF;
|
||||
txData[3] = ((data & 0b00001111) << 4) | 0b00000000;
|
||||
|
||||
HAL_GPIO_WritePin(DAC8568_CS_GPIO_Port, DAC8568_CS_Pin, GPIO_PIN_RESET);
|
||||
HAL_SPI_Transmit(hspi_dac, txData, 4, HAL_MAX_DELAY);
|
||||
HAL_GPIO_WritePin(DAC8568_CS_GPIO_Port, DAC8568_CS_Pin, GPIO_PIN_SET);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 将数据数组中的值分别写入所有8个DAC通道的输入寄存器。
|
||||
* @param data_array 包含8个uint16_t类型数据的数组指针,分别对应通道A到H。
|
||||
* @note 此函数通过循环调用 DAC8568_Write 实现。
|
||||
*/
|
||||
void DAC8568_WriteAllChannels(uint16_t *data_array) // 参数为包含8个通道数据的数组指针
|
||||
{
|
||||
for (uint8_t ch = 0; ch < 8; ch++) // 遍历0到7,代表通道A到H
|
||||
{
|
||||
DAC8568_Write(ch, data_array[ch]); // 为当前通道 ch 写入数组中对应的数据
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 更新所有DAC通道的模拟输出。
|
||||
* @note 此函数使用CMD_UPDATE_DAC_REG命令和BROADCAST地址。
|
||||
*/
|
||||
void DAC8568_UpdateAllChannels(void)
|
||||
{
|
||||
uint8_t txData[4];
|
||||
|
||||
txData[0] = 0b00000000 | (CMD_UPDATE_DAC_REG & 0b00001111);
|
||||
txData[1] = (BROADCAST << 4) | 0b00000000; // 使用 BROADCAST 地址
|
||||
txData[2] = 0;
|
||||
txData[3] = 0;
|
||||
|
||||
HAL_GPIO_WritePin(DAC8568_CS_GPIO_Port, DAC8568_CS_Pin, GPIO_PIN_RESET);
|
||||
HAL_SPI_Transmit(hspi_dac, txData, 4, HAL_MAX_DELAY);
|
||||
HAL_GPIO_WritePin(DAC8568_CS_GPIO_Port, DAC8568_CS_Pin, GPIO_PIN_SET);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 设置指定DAC通道或所有通道的电源模式。
|
||||
* @param channel 目标通道 (CHANNEL_A 到 CHANNEL_H) 或 BROADCAST。
|
||||
* @param mode 电源模式 (POWER_UP, POWER_DOWN_1K, POWER_DOWN_100K, POWER_DOWN_HIZ)。
|
||||
* @note 参考数据手册第47页表13。
|
||||
*/
|
||||
void DAC8568_SetPowerMode(uint8_t channel, uint8_t mode)
|
||||
{
|
||||
uint8_t txData[4]; // 定义SPI传输的4字节数据缓冲区
|
||||
|
||||
// 32位帧格式:
|
||||
// [31:28] 前缀位(0000)
|
||||
// [27:24] 命令位(CMD_POWER_DOWN = 0100) - 电源控制命令
|
||||
// [23:20] 地址位(channel) - 选择目标通道或广播
|
||||
// [19:10] 均为0 (不关心)
|
||||
// [9:8] PD1和PD0电源模式位 (位于整个SPI帧的DB9, DB8)
|
||||
// [7:0] 均为0 (不关心, 包括特征位)
|
||||
|
||||
// 第一个字节 (DB31-DB24): 前缀位 + 命令位
|
||||
txData[0] = 0b00000000 | (CMD_POWER_DOWN & 0b00001111);
|
||||
|
||||
// 第二个字节 (DB23-DB16): 地址位 + 数据高4位(此命令中为0)
|
||||
txData[1] = ((channel & 0b00001111) << 4) | 0b00000000;
|
||||
|
||||
// 第三个字节 (DB15-DB8): 包含电源模式位 PD1(DB9) 和 PD0(DB8)
|
||||
// (mode & 0b00000011) 提取 mode 参数中的 PD1(bit1) 和 PD0(bit0)。
|
||||
// 这些位对应SPI帧的DB9和DB8,因此直接放入 txData[2] 的最低两位。
|
||||
// txData[2] 的高6位 (DB15-DB10) 为 不关心 (设为0)。
|
||||
txData[2] = (mode & 0b00000011); // PD1位于bit1, PD0位于bit0 of txData[2] (对应帧的D9, D8)
|
||||
|
||||
// 第四个字节 (DB7-DB0): 均为0 (不关心)
|
||||
txData[3] = 0;
|
||||
|
||||
// 执行SPI传输
|
||||
HAL_GPIO_WritePin(DAC8568_CS_GPIO_Port, DAC8568_CS_Pin, GPIO_PIN_RESET);
|
||||
HAL_SPI_Transmit(hspi_dac, txData, 4, HAL_MAX_DELAY);
|
||||
HAL_GPIO_WritePin(DAC8568_CS_GPIO_Port, DAC8568_CS_Pin, GPIO_PIN_SET);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 启用静态内部参考电压(2.5V)。
|
||||
* @note 参考数据手册第44页表7。命令 CMD_INTERNAL_REF, 地址 0b0000, 特征位 REF_ENABLE。内部参考电压为2.5V,但是在C/D等级中内部会有一个2倍增益。见数据手册31页8.2.1
|
||||
*/
|
||||
void DAC8568_EnableStaticInternalRef(void)
|
||||
{
|
||||
DAC8568_SendRawCommand(CMD_INTERNAL_REF, 0b0000, 0x0000, REF_ENABLE);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 禁用静态内部参考电压(2.5V)。
|
||||
* @note 参考数据手册第44页表7。命令 CMD_INTERNAL_REF, 地址 0b0000, 特征位 REF_DISABLE。内部参考电压为2.5V,但是在C/D等级中内部会有一个2倍增益。见数据手册31页8.2.1
|
||||
*/
|
||||
void DAC8568_DisableStaticInternalRef(void)
|
||||
{
|
||||
DAC8568_SendRawCommand(CMD_INTERNAL_REF, 0b0000, 0x0000, REF_DISABLE);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 启用内部参考的灵活模式 (Flex Mode)。
|
||||
* @note 参考数据手册第45页表9。命令 CMD_INTERNAL_REF, 地址 0b0001, 数据位 D13=1, 特征位 0b0000。
|
||||
*/
|
||||
void DAC8568_EnableFlexMode(void)
|
||||
{
|
||||
// 数据位 D13 (对应整个16位数据字段的 bit 13) 设置为1
|
||||
DAC8568_SendRawCommand(CMD_INTERNAL_REF, 0b0001, (1 << 13), 0b0000);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 禁用内部参考的灵活模式 (Flex Mode)。
|
||||
* @note 参考数据手册第45页表9。命令 CMD_INTERNAL_REF, 地址 0b0001, 数据位 D13=0, 特征位 0b0000。
|
||||
* 禁用灵活模式后,内部参考的行为由静态模式控制位决定。
|
||||
*/
|
||||
void DAC8568_DisableFlexMode(void)
|
||||
{
|
||||
// 数据位 D13 设置为0
|
||||
DAC8568_SendRawCommand(CMD_INTERNAL_REF, 0b0001, 0x0000, 0b0000);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 在灵活模式下,设置内部参考是否始终开启。
|
||||
* @param enable 1 表示始终开启, 0 表示根据需要自动开启/关闭 (默认行为)。
|
||||
* @note 参考数据手册第45页表10。命令 CMD_INTERNAL_REF, 地址 0b0001, 数据位 D15 控制, 特征位 0b0000。
|
||||
*/
|
||||
void DAC8568_SetFlexModeRefAlwaysOn(uint8_t enable)
|
||||
{
|
||||
uint16_t data_bits = enable ? (1 << 15) : 0; // D15 控制
|
||||
DAC8568_SendRawCommand(CMD_INTERNAL_REF, 0b0001, data_bits, 0b0000);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 在灵活模式下,设置内部参考是否始终关闭。
|
||||
* @param enable 1 表示始终关闭, 0 表示根据需要自动开启/关闭。
|
||||
* @note 参考数据手册第45页表11。命令 CMD_INTERNAL_REF, 地址 0b0001, 数据位 D14 控制, 特征位 0b0000。
|
||||
*/
|
||||
void DAC8568_SetFlexModeRefAlwaysOff(uint8_t enable)
|
||||
{
|
||||
uint16_t data_bits = enable ? (1 << 14) : 0; // D14 控制
|
||||
DAC8568_SendRawCommand(CMD_INTERNAL_REF, 0b0001, data_bits, 0b0000);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 设置DAC清零时的行为。
|
||||
* @param mode 清除代码模式 (CLEAR_CODE_ZERO_SCALE, CLEAR_CODE_MID_SCALE, CLEAR_CODE_FULL_SCALE, CLEAR_CODE_NO_OPERATION)。
|
||||
* @note 参考数据手册第39页表5。
|
||||
*/
|
||||
void DAC8568_SetClearCode(uint8_t mode)
|
||||
{
|
||||
uint8_t txData[4]; // 定义SPI传输的4字节数据缓冲区
|
||||
|
||||
// 32位帧格式:
|
||||
// [31:28] 前缀位(0000)
|
||||
// [27:24] 命令位(CMD_CLEAR_CODE_REG = 0101) - 清除代码寄存器命令
|
||||
// [23:4] 均为0 (不关心)
|
||||
// [3:2] 特征位 F1, F0 (位于整个SPI帧的DB3, DB2) 控制清除模式
|
||||
// [1:0] 均为0 (不关心)
|
||||
|
||||
// 第一个字节 (DB31-DB24): 前缀位 + 命令位
|
||||
txData[0] = 0b00000000 | (CMD_CLEAR_CODE_REG & 0b00001111);
|
||||
|
||||
// 第二个字节 (DB23-DB16): 地址位(不关心, 设为0) + 数据高位(不关心, 设为0)
|
||||
txData[1] = 0b00000000;
|
||||
|
||||
// 第三个字节 (DB15-DB8): 数据中间位(不关心, 设为0)
|
||||
txData[2] = 0;
|
||||
|
||||
// 第四个字节 (DB7-DB0): 包含特征位 F1, F0
|
||||
// (mode & 0b00000011) 提取 mode 参数的最低两位作为 F1(bit1)F0(bit0)。
|
||||
// 左移2位,将它们放置到SPI帧的DB3和DB2位置。
|
||||
txData[3] = (mode & 0b00000011) << 2; // F1(DB3), F0(DB2) 控制清除模式
|
||||
|
||||
// 执行SPI传输
|
||||
HAL_GPIO_WritePin(DAC8568_CS_GPIO_Port, DAC8568_CS_Pin, GPIO_PIN_RESET);
|
||||
HAL_SPI_Transmit(hspi_dac, txData, 4, HAL_MAX_DELAY);
|
||||
HAL_GPIO_WritePin(DAC8568_CS_GPIO_Port, DAC8568_CS_Pin, GPIO_PIN_SET);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 执行软件复位。
|
||||
*/
|
||||
void DAC8568_SoftwareReset(void)
|
||||
{
|
||||
uint8_t txData[4];
|
||||
|
||||
txData[0] = 0b00000000 | (CMD_SOFTWARE_RESET & 0b00001111);
|
||||
txData[1] = 0;
|
||||
txData[2] = 0;
|
||||
txData[3] = 0;
|
||||
|
||||
HAL_GPIO_WritePin(DAC8568_CS_GPIO_Port, DAC8568_CS_Pin, GPIO_PIN_RESET);
|
||||
HAL_SPI_Transmit(hspi_dac, txData, 4, HAL_MAX_DELAY);
|
||||
HAL_GPIO_WritePin(DAC8568_CS_GPIO_Port, DAC8568_CS_Pin, GPIO_PIN_SET);
|
||||
HAL_Delay(1);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 直接发送一个完整的32位命令帧到DAC8568。
|
||||
*/
|
||||
void DAC8568_SendRawCommand(uint8_t cmd_bits, uint8_t addr_bits, uint16_t data_bits, uint8_t feature_bits)
|
||||
{
|
||||
uint8_t txData[4];
|
||||
|
||||
txData[0] = 0b00000000 | (cmd_bits & 0b00001111);
|
||||
txData[1] = ((addr_bits & 0b00001111) << 4) | ((data_bits >> 12) & 0b00001111);
|
||||
txData[2] = (data_bits >> 4) & 0xFF;
|
||||
txData[3] = ((data_bits & 0b00001111) << 4) | (feature_bits & 0b00001111);
|
||||
|
||||
HAL_GPIO_WritePin(DAC8568_CS_GPIO_Port, DAC8568_CS_Pin, GPIO_PIN_RESET);
|
||||
HAL_SPI_Transmit(hspi_dac, txData, 4, HAL_MAX_DELAY);
|
||||
HAL_GPIO_WritePin(DAC8568_CS_GPIO_Port, DAC8568_CS_Pin, GPIO_PIN_SET);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 直接发送自定义的4字节原始数据到DAC8568。
|
||||
* @param raw_data 指向包含4字节数据的数组。
|
||||
* @note 此函数用于发送预先构建好的完整SPI帧。
|
||||
*/
|
||||
void DAC8568_SendRawData(uint8_t raw_data[4])
|
||||
{
|
||||
// 开始传输(拉低CS)
|
||||
HAL_GPIO_WritePin(DAC8568_CS_GPIO_Port, DAC8568_CS_Pin, GPIO_PIN_RESET);
|
||||
|
||||
// SPI传输
|
||||
HAL_SPI_Transmit(hspi_dac, raw_data, 4, HAL_MAX_DELAY); // 传输4字节
|
||||
|
||||
// 结束传输(拉高CS)
|
||||
HAL_GPIO_WritePin(DAC8568_CS_GPIO_Port, DAC8568_CS_Pin, GPIO_PIN_SET);
|
||||
}
|
|
@ -1,62 +1,183 @@
|
|||
#include "stm32f4xx_hal.h" // 添加HAL库头文件
|
||||
/*
|
||||
* DAC8568/DAC8168/DAC8568 驱动程序
|
||||
* 参考数据手册: https://www.ti.com.cn/product/cn/DAC8568
|
||||
* 版本: 2025-4-10
|
||||
* 作者: 雪豹
|
||||
* 描述: 驱动TI DAC8568系列DAC芯片,支持SPI通信和基本功能
|
||||
* 开源协议: MIT
|
||||
* 版权所有 (c) 2025 雪豹
|
||||
* 注意:本代码仅供参考,使用前请仔细阅读数据手册和相关文档。
|
||||
* 使用本代码即表示您同意承担所有风险和责任。
|
||||
*/
|
||||
/*
|
||||
* TI DAC7568/DAC8168/DAC8568 核心特性 (数据手册第1/5-7页)
|
||||
*
|
||||
* 【共同特性】
|
||||
* - 通道数量: 8通道独立电压输出
|
||||
* - 内部基准: 2.5V (±0.004%初始精度, 2ppm/°C温漂典型值)
|
||||
* - 毛刺能量: 0.1nV-s (代码切换瞬态)
|
||||
* - 输出缓冲: 轨到轨输出,驱动能力 20mA sink/source
|
||||
* - 电源范围: 2.7V至5.5V单电源供电
|
||||
* - 接口速度: 最高50MHz SPI时钟
|
||||
* - 低功耗:
|
||||
* > 工作模式: 1.25mA @5V (含基准)
|
||||
* > 断电模式: 0.18μA @5V (典型)
|
||||
* - 温度范围: -40°C至+125°C
|
||||
* - 复位特性: 上电复位至零电平/中间电平(型号后缀A/B/C/D区分)
|
||||
*
|
||||
* 【关键性能参数】
|
||||
* - DAC建立时间:
|
||||
* > 5μs (典型值, 空载, 1/4至3/4量程, ±0.024%误差)
|
||||
* > 10μs (最大值, 接1MΩ负载)
|
||||
*
|
||||
* 【型号差异】
|
||||
* >> DAC7568 (12位):
|
||||
* - 分辨率: 12位 (0x000-0xFFF)
|
||||
* - INL: ±1 LSB (最大值)
|
||||
* - 封装: TSSOP-14/16
|
||||
*
|
||||
* >> DAC8168 (14位):
|
||||
* - 分辨率: 14位 (0x0000-0x3FFF)
|
||||
* - INL: ±4 LSB (最大值)
|
||||
* - 封装: TSSOP-14/16
|
||||
*
|
||||
* >> DAC8568 (16位):
|
||||
* - 分辨率: 16位 (0x0000-0xFFFF)
|
||||
* - INL: ±12 LSB (最大值)
|
||||
* - 封装: TSSOP-16
|
||||
*
|
||||
* 【编程注意】
|
||||
* 1. 数据对齐差异:
|
||||
* DAC7568使用12位数据(D11-D0),需左移4位填充到SPI帧
|
||||
* DAC8168使用14位数据(D13-D0),需左移2位
|
||||
* DAC8568使用全部16位数据(D15-D0)
|
||||
*
|
||||
* 2. 建立时间影响:
|
||||
* 输出稳定需等待至少10μs,高速连续写入时需添加延时:
|
||||
* HAL_Delay(1); // 保守延时1ms (实际最低10μs)
|
||||
*/
|
||||
/*
|
||||
* SPI 外设配置说明 (针对 DAC8568)
|
||||
* ----------------------------------------------------------------
|
||||
* 参数要求(参考数据手册第7-8页时序图和第6页电气特性):
|
||||
* 1. 模式: 全双工主模式 (DAC8568 为从设备)
|
||||
* 2. 数据大小: 8位 (需手动组合为24/32位帧)
|
||||
* 3. 时钟极性 (CPOL): 低电平空闲 (CPOL=0)
|
||||
* 4. 时钟相位 (CPHA): 数据在第一个边沿采样 (CPHA=0)
|
||||
* 5. 传输顺序: MSB 高位在前 (强制要求)
|
||||
* 6. 波特率: ≤50MHz (建议根据主频选择分频器)
|
||||
* 7. 硬件NSS: 禁用 (使用独立GPIO控制SYNC引脚)
|
||||
*
|
||||
* CubeMX 具体设置步骤:
|
||||
* 1. Connectivity → SPIx → Mode = "Full-Duplex Master"
|
||||
* 2. Parameter Settings →
|
||||
* - Data Size = 8 Bits
|
||||
* - First Bit = MSB First
|
||||
* - Clock Polarity = High 注意这个
|
||||
* - Clock Phase = 1 Edge
|
||||
* - Baud Rate Prescaler = 分频值 (如 2/4/8,确保 SCLK ≤50MHz)
|
||||
* 3. GPIO Settings →
|
||||
* - 配置 SYNC 引脚为 GPIO_Output (初始化高电平)
|
||||
* - MOSI/SCK 自动分配,模式为 Alternate Function Push-Pull
|
||||
*/
|
||||
/*
|
||||
* DAC8568 硬件连接说明:
|
||||
* ----------------------------------------------------------------
|
||||
* DAC8568引脚 | STM32引脚 | 备注
|
||||
* -----------|----------------|-----------------------------------
|
||||
* DIN | SPIx_MOSI | 主设备输出,直连无需上拉
|
||||
* SCLK | SPIx_SCK | 保持短走线,减少干扰
|
||||
* SYNC | 任意GPIO (如PA4)| 需配置为输出模式,传输前拉低
|
||||
* VDD | 3.3V | 电源需并联100nF去耦电容
|
||||
* GND | GND | 共地
|
||||
*/
|
||||
|
||||
#ifndef DAC8568_H
|
||||
#define DAC8568_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
#include "main.h"
|
||||
#include "stm32f4xx_hal.h"
|
||||
#include <stdint.h>
|
||||
|
||||
/************************DA8568寄存器SR的值*****************************/
|
||||
// DAC8568数据帧结构 (31-0位)
|
||||
// 31-28位: 前缀位 (PREFIX BITS) - 始终为0
|
||||
// 27-24位: 命令位 (CONTROL BITS)
|
||||
// 23-20位: 地址位 (ADDRESS BITS)
|
||||
// 19-4位: 数据位 (DATA BITS)
|
||||
// 3-0位: 特征位 (FEATURE BITS)
|
||||
|
||||
#define PrefixControlbyte 0x03//前缀控制字节
|
||||
#define AddressOutA 0x0//通道A地址
|
||||
#define AddressOutB 0x1//通道B地址
|
||||
#define AddressOutC 0x2//通道C地址
|
||||
#define AddressOutD 0x3//通道D地址
|
||||
#define AddressOutE 0x4//通道E地址
|
||||
#define AddressOutF 0x5//通道F地址
|
||||
#define AddressOutG 0x6//通道G地址
|
||||
#define AddressOutH 0x7//通道H地址
|
||||
#define Featurebyte 0x0//特征字节
|
||||
// DAC8568命令定义 (27-24位控制位) (参考数据手册第35-38页表4)
|
||||
#define CMD_WRITE_INPUT_REG 0b0000 // 写入输入寄存器
|
||||
#define CMD_UPDATE_DAC_REG 0b0001 // 更新DAC寄存器
|
||||
#define CMD_WRITE_INPUT_UPDATE_ALL 0b0010 // 写入所有输入寄存器并更新所有DAC寄存器
|
||||
#define CMD_WRITE_INPUT_UPDATE_ONE 0b0011 // 写入单个输入寄存器并更新相应的DAC寄存器
|
||||
#define CMD_POWER_DOWN 0b0100 // 电源模式控制
|
||||
#define CMD_CLEAR_CODE_REG 0b0101 // 清除代码寄存器
|
||||
#define CMD_LDAC_REG 0b0110 // LDAC寄存器控制
|
||||
#define CMD_SOFTWARE_RESET 0b0111 // 软件复位
|
||||
#define CMD_INTERNAL_REF 0b1000 // 内部参考控制
|
||||
|
||||
/*****DA8568寄存器SR的值-结尾*************************************/
|
||||
// DAC通道选择 (23-20位地址位) (参考数据手册第36页)
|
||||
#define CHANNEL_A 0b0000 // 通道A对应CH0
|
||||
#define CHANNEL_B 0b0001 // 通道B对应CH4
|
||||
#define CHANNEL_C 0b0010 // 通道C对应CH1
|
||||
#define CHANNEL_D 0b0011 // 通道D对应CH5
|
||||
#define CHANNEL_E 0b0100 // 通道E对应CH2
|
||||
#define CHANNEL_F 0b0101 // 通道F对应CH6
|
||||
#define CHANNEL_G 0b0110 // 通道G对应CH3
|
||||
#define CHANNEL_H 0b0111 // 通道H对应CH7
|
||||
#define BROADCAST 0b1111 // 广播模式(所有通道)
|
||||
|
||||
/****************************DAC8568命令************************/
|
||||
#define SETUP_INTERNAL_REGISTER 0
|
||||
#define POWER_UP 1
|
||||
#define RESET 2
|
||||
/*****DAC8568命令-结尾*******************************************/
|
||||
// 电源模式定义 (特征位F1-F0) (参考数据手册第47页表13)
|
||||
#define POWER_UP 0b00 // 正常工作模式
|
||||
#define POWER_DOWN_1K 0b01 // 关断模式,1K电阻接地
|
||||
#define POWER_DOWN_100K 0b10 // 关断模式,100K电阻接地
|
||||
#define POWER_DOWN_HIZ 0b11 // 关断模式,高阻态
|
||||
|
||||
//---------------------------------------- Pin definition
|
||||
// 内部参考控制 (特征位) (参考数据手册第44-45页)
|
||||
#define REF_DISABLE 0b0000 // 禁用内部参考
|
||||
#define REF_ENABLE 0b0001 // 启用内部参考
|
||||
#define REF_FLEX_MODE_ENABLE 0b0010 // 启用灵活模式
|
||||
#define REF_FLEX_MODE_ALWAYS_ON 0b0011 // 灵活模式常开
|
||||
#define REF_FLEX_MODE_ALWAYS_OFF 0b0100 // 灵活模式常关
|
||||
|
||||
//---------------------------------------- Command definition
|
||||
#define DAC8568_EN_INTER_REF_STATIC 0x08000001
|
||||
#define DAC8568_WRITE_UPDATE_SEL_DAC 0x03000000
|
||||
// 清除代码控制 (特征位F1-F0) (参考数据手册第39页表5)
|
||||
#define CLEAR_CODE_ZERO_SCALE 0b00 // 清除为零刻度
|
||||
#define CLEAR_CODE_MID_SCALE 0b01 // 清除为中间刻度
|
||||
#define CLEAR_CODE_FULL_SCALE 0b10 // 清除为全刻度
|
||||
#define CLEAR_CODE_NO_OPERATION 0b11 // 无操作
|
||||
|
||||
//---------------------------------------- Reference Voltage
|
||||
#define DAC8568_REF_VOLTAGE 2.5
|
||||
// 硬件相关定义
|
||||
#define DAC8568_CS_GPIO_Port GPIOD
|
||||
#define DAC8568_CS_Pin GPIO_PIN_15
|
||||
#define DAC8568_LDAC_GPIO_Port GPIOD
|
||||
#define DAC8568_LDAC_Pin GPIO_PIN_14
|
||||
|
||||
void DAC8568_Init(void);
|
||||
void DAC8568_Write_Update_Sel_DAC(uint32_t ChannelNum, uint32_t DACValue);
|
||||
// 函数声明
|
||||
void DAC8568_Init(SPI_HandleTypeDef *hspi);
|
||||
void DAC8568_Write(uint8_t channel, uint16_t data);
|
||||
void DAC8568_Update(uint8_t channel);
|
||||
void DAC8568_WriteAndUpdate(uint8_t channel, uint16_t data);
|
||||
void DAC8568_WriteAllChannels(uint16_t *data);
|
||||
void DAC8568_UpdateAllChannels(void);
|
||||
void DAC8568_SetPowerMode(uint8_t channel, uint8_t mode);
|
||||
void DAC8568_EnableStaticInternalRef(void);
|
||||
void DAC8568_DisableStaticInternalRef(void);
|
||||
void DAC8568_EnableFlexMode(void);
|
||||
void DAC8568_DisableFlexMode(void);
|
||||
void DAC8568_SetFlexModeRefAlwaysOn(uint8_t enable);
|
||||
void DAC8568_SetFlexModeRefAlwaysOff(uint8_t enable);
|
||||
void DAC8568_SetClearCode(uint8_t mode);
|
||||
void DAC8568_SoftwareReset(void);
|
||||
void DAC8568_SendRawCommand(uint8_t cmd_bits, uint8_t addr_bits, uint16_t data_bits, uint8_t feature_bits);
|
||||
void DAC8568_SendRawData(uint8_t raw_data[4]);
|
||||
|
||||
|
||||
// #define DAC8568_SYNC_H GPIO_SetBits(GPIOA,GPIO_Pin_15)
|
||||
// #define DAC8568_SYNC_L GPIO_ResetBits(GPIOA,GPIO_Pin_15)
|
||||
// #define DAC8568_SCLK_H GPIO_SetBits(GPIOC,GPIO_Pin_10)
|
||||
// #define DAC8568_SCLK_L GPIO_ResetBits(GPIOC,GPIO_Pin_10)
|
||||
// #define DAC8568_DIN_H GPIO_SetBits(GPIOC,GPIO_Pin_12)
|
||||
// #define DAC8568_DIN_L GPIO_ResetBits(GPIOC,GPIO_Pin_12)
|
||||
//引脚拉高拉低
|
||||
#define DAC8568_CS_H HAL_GPIO_WritePin(DAC8568_CS_GPIO_Port, DAC8568_CS_Pin, GPIO_PIN_SET)
|
||||
#define DAC8568_CS_L HAL_GPIO_WritePin(DAC8568_CS_GPIO_Port, DAC8568_CS_Pin, GPIO_PIN_RESET)
|
||||
#define DAC8568_SCLK_H HAL_GPIO_WritePin(DAC8568_SCLK_GPIO_Port, DAC8568_SCLK_Pin, GPIO_PIN_SET)
|
||||
#define DAC8568_SCLK_L HAL_GPIO_WritePin(DAC8568_SCLK_GPIO_Port, DAC8568_SCLK_Pin, GPIO_PIN_RESET)
|
||||
#define DAC8568_DIN_H HAL_GPIO_WritePin(DAC8568_DIN_GPIO_Port, DAC8568_DIN_Pin, GPIO_PIN_SET)
|
||||
#define DAC8568_DIN_L HAL_GPIO_WritePin(DAC8568_DIN_GPIO_Port, DAC8568_DIN_Pin, GPIO_PIN_RESET)
|
||||
#define DAC8568_LD_H HAL_GPIO_WritePin(DAC8568_LD_GPIO_Port, DAC8568_LD_Pin, GPIO_PIN_SET)
|
||||
#define DAC8568_LD_L HAL_GPIO_WritePin(DAC8568_LD_GPIO_Port, DAC8568_LD_Pin, GPIO_PIN_RESET)
|
||||
|
||||
void dac8568_init(void);
|
||||
void dac8568_set_voltage(unsigned char mCh,float mVol);
|
||||
void SPI_SendByte(uint8_t m);
|
||||
void DAC8568_Write_passageway(uint8_t Addressbyte, uint16_t Datashort);
|
||||
void DAC8568_Write_Command(uint8_t command);
|
||||
void dac8568_set_voltage(unsigned char mCh, float mVol);
|
||||
void dac8568_spi_init(void);
|
||||
void DAC8568_Init(void);
|
||||
void dac8568_output_ch0_1v5(void);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /* DAC8568_H */
|
|
@ -178,7 +178,7 @@ void dac8568_spi_init(void)
|
|||
hspi3.Init.Mode = SPI_MODE_MASTER;
|
||||
hspi3.Init.Direction = SPI_DIRECTION_2LINES;
|
||||
hspi3.Init.DataSize = SPI_DATASIZE_8BIT;
|
||||
hspi3.Init.CLKPolarity = SPI_POLARITY_LOW; // CPOL = 0
|
||||
hspi3.Init.CLKPolarity = SPI_POLARITY_HIGH; // CPOL = 0
|
||||
hspi3.Init.CLKPhase = SPI_PHASE_1EDGE; // CPHA = 0
|
||||
hspi3.Init.NSS = SPI_NSS_SOFT;
|
||||
hspi3.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_32; // 提高SPI速度
|
||||
|
@ -194,7 +194,7 @@ void dac8568_spi_init(void)
|
|||
|
||||
// 初始化CS和LDAC引脚状态
|
||||
HAL_GPIO_WritePin(DAC8568_CS_GPIO_Port, DAC8568_CS_Pin, GPIO_PIN_SET); // CS初始为高电平
|
||||
HAL_GPIO_WritePin(DAC8568_LD_GPIO_Port, DAC8568_LD_Pin, GPIO_PIN_RESET); // LDAC初始为低电平
|
||||
HAL_GPIO_WritePin(DAC8568_LD_GPIO_Port, DAC8568_LD_Pin, GPIO_PIN_SET); // LDAC初始为高电平
|
||||
|
||||
// 等待一段时间确保DAC8568稳定
|
||||
HAL_Delay(10);
|
||||
|
|
Loading…
Reference in New Issue