DAC8562有可以使用内部参考电压和外部参考电压的两种方案,也决定着输出最大的电压就是参考电压。建议使用内部参考电压,准确度更高,因为单片机的3.3V大多数时候极不稳定。
方案一、使用外部参考电压
DAC8562.c
#include "DAC8562.h"
void Init_DAC8562_IO(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOF, ENABLE);
GPIO_InitStructure.GPIO_Pin = DAC8562_DIN_PIN|DAC8562_SCLK_PIN|DAC8562_SYNC_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; //推完输出
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; //不使用上下拉电阻
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(DAC8562_DIN_PORT, &GPIO_InitStructure);
}
void Output_DAC8562(uint16_t data_a, uint16_t data_b)
{
DAC_WR_REG(CMD_SETA_UPDATEA, data_a);
DAC_WR_REG(CMD_SETB_UPDATEB, data_b);
}
void Init_DAC8562(void)
{
Init_DAC8562_IO();
DAC_WR_REG(CMD_RESET_ALL_REG, DATA_RESET_ALL_REG);
DAC_WR_REG(CMD_PWR_UP_A_B, DATA_PWR_UP_A_B);
DAC_WR_REG(CMD_INTERNAL_REF_DIS, DATA_INTERNAL_REF_DIS);//禁止使用内部参考电压
DAC_WR_REG(CMD_GAIN, DATA_GAIN_B1_A1); //一倍放大
DAC_WR_REG(CMD_LDAC_DIS, DATA_LDAC_DIS);
}
void DAC_WR_REG(uint8_t cmd_byte, uint16_t data_byte)
{
DAC8562_SYNC_L;
SPI_SendByte(cmd_byte);
SPI_SendHalfWord(data_byte);
DAC8562_SYNC_H;
}
void SPI_SendHalfWord(uint16_t m)
{
uint8_t i;
for (i = 0; i < 16; i++)
{
DAC8562_SCLK_H;
if (m & 0x8000)
{
DAC8562_DIN_H;
}
else
{
DAC8562_DIN_L;
}
m = m << 1;
DAC8562_SCLK_L;
}
}
void SPI_SendByte(uint8_t m)
{
uint8_t i;
for (i = 0; i < 8; i++)
{
DAC8562_SCLK_H;
if (m & 0x80)
{
DAC8562_DIN_H;
}
else
{
DAC8562_DIN_L;
}
m = m << 1;
DAC8562_SCLK_L;
}
}
uint16_t Voltage_Convert(float voltage)
{
float Vref = 3.301; //这里使用的电压为外部的电压,我使用的是提供给单片机的电压,即3.3V
uint16_t dacValue = (uint16_t)((voltage / Vref) * 65535);
return dacValue;
}
DAC8562.h
#ifndef __DAC8562_H
#define __DAC8562_H
#include "stm32f4xx.h"
#define DAC8562_SYNC_PIN GPIO_Pin_2
#define DAC8562_SYNC_PORT GPIOF
#define DAC8562_SCLK_PIN GPIO_Pin_3
#define DAC8562_SCLK_PORT GPIOF
#define DAC8562_DIN_PIN GPIO_Pin_4
#define DAC8562_DIN_PORT GPIOF
#define DAC8562_SYNC_H GPIO_SetBits(GPIOF,GPIO_Pin_2)
#define DAC8562_SYNC_L GPIO_ResetBits(GPIOF,GPIO_Pin_2)
#define DAC8562_SCLK_H GPIO_SetBits(GPIOF,GPIO_Pin_3)
#define DAC8562_SCLK_L GPIO_ResetBits(GPIOF,GPIO_Pin_3)
#define DAC8562_DIN_H GPIO_SetBits(GPIOF,GPIO_Pin_4)
#define DAC8562_DIN_L GPIO_ResetBits(GPIOF,GPIO_Pin_4)
#define CMD_SETA_UPDATEA 0x18 // A通道命令+16位A路数据
#define CMD_SETB_UPDATEB 0x19 // B通道命令+16位B路数据
#define CMD_UPDATE_ALL_DACS 0x0F // 更新两路寄存器命令,后16位只需时钟即可
#define CMD_GAIN 0x02 // 内部放大倍数命令
#define DATA_GAIN_B2_A2 0x0000 // B路2倍,A路1倍
#define DATA_GAIN_B2_A1 0x0001 // B路1倍,A路2倍
#define DATA_GAIN_B1_A2 0x0002 // B路2倍,A路2倍
#define DATA_GAIN_B1_A1 0x0003 // B路1倍,A路1倍
#define CMD_PWR_UP_A_B 0x20 // 命令:上电A、B路
#define DATA_PWR_UP_A_B 0x0003 // 数据:Power up DAC-A and DAC-B data
#define CMD_RESET_ALL_REG 0x28 // 命令:所有寄存器复位、清空寄存器
#define DATA_RESET_ALL_REG 0x0001 // 数据:所有寄存器复位、清空寄存器
#define CMD_LDAC_DIS 0x30 // LDAC脚功能命令
#define DATA_LDAC_DIS 0x0003 // LDAC脚不起作用
#define CMD_INTERNAL_REF_DIS 0x38 // 命令:Disable internal reference and reset DACs to gain = 1
#define DATA_INTERNAL_REF_DIS 0x0000 // 数据:Disable internal reference and reset DACs to gain = 1
#define CMD_INTERNAL_REF_EN 0x38 // 命令:Enable Internal Reference & reset DACs to gain = 2
#define DATA_INTERNAL_REF_EN 0x0001 // 数据:Enable Internal Reference & reset DACs to gain = 2
void Init_DAC8562_IO(void);
void Output_DAC8562(uint16_t data_a, uint16_t data_b);
void Init_DAC8562(void);
void DAC_WR_REG(uint8_t cmd_byte, uint16_t data_byte);
void SPI_SendHalfWord(uint16_t m);
void SPI_SendByte(uint8_t m);
uint16_t Voltage_Convert(float voltage);
#endif
方案二、使用内部参考电压,即2.5V
DAC8562.c
#include "DAC8562.h"
void Init_DAC8562_IO(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOF, ENABLE);
GPIO_InitStructure.GPIO_Pin = DAC8562_DIN_PIN|DAC8562_SCLK_PIN|DAC8562_SYNC_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; //推完输出
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; //不使用上下拉电阻
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(DAC8562_DIN_PORT, &GPIO_InitStructure);
}
void Output_DAC8562(uint16_t data_a, uint16_t data_b)
{
DAC_WR_REG(CMD_SETA_UPDATEA, data_a);
DAC_WR_REG(CMD_SETB_UPDATEB, data_b);
}
void Init_DAC8562(void)
{
Init_DAC8562_IO();
DAC_WR_REG(CMD_RESET_ALL_REG, DATA_RESET_ALL_REG);
DAC_WR_REG(CMD_PWR_UP_A_B, DATA_PWR_UP_A_B);
DAC_WR_REG(CMD_INTERNAL_REF_EN, DATA_INTERNAL_REF_EN); //使用内部参考电压
DAC_WR_REG(CMD_GAIN, DATA_GAIN_B1_A1); //一倍放大
DAC_WR_REG(CMD_LDAC_DIS, DATA_LDAC_DIS);
}
void DAC_WR_REG(uint8_t cmd_byte, uint16_t data_byte)
{
DAC8562_SYNC_L;
SPI_SendByte(cmd_byte);
SPI_SendHalfWord(data_byte);
DAC8562_SYNC_H;
}
void SPI_SendHalfWord(uint16_t m)
{
uint8_t i;
for (i = 0; i < 16; i++)
{
DAC8562_SCLK_H;
if (m & 0x8000)
{
DAC8562_DIN_H;
}
else
{
DAC8562_DIN_L;
}
m = m << 1;
DAC8562_SCLK_L;
}
}
void SPI_SendByte(uint8_t m)
{
uint8_t i;
for (i = 0; i < 8; i++)
{
DAC8562_SCLK_H;
if (m & 0x80)
{
DAC8562_DIN_H;
}
else
{
DAC8562_DIN_L;
}
m = m << 1;
DAC8562_SCLK_L;
}
}
uint16_t Voltage_Convert(float voltage)
{
float Vref = 2.5f;
uint16_t dacValue = (uint16_t)((voltage / Vref) * 65535);
return dacValue;
}
DAC8562.h
这个文件通用,不变。