DAC60004是德州仪器品牌的一款数模转换器,可以将数字量转换为模拟量。
产品的数据手册讲解可以看下面的链接,讲述的比较清楚了
基于FPGA驱动DAC6004_dac ldac解释-CSDN博客
以下是本人使用STM32F407标准固件库开发的程序,亲测有效
本实例中,DAC60004是接到SPI2通讯的,所以,需要编写SPI2的功能代码,如下:
SPI2.c
#include "SPI2.h"
//SPI2 MOSI PB15 复用推挽输出
//SPI2 MISO PB14 推挽输出
//SPI2 CLK PB13 复用推挽输出
//SPI2 CS PG12 对应的DAC60004的SYNC引脚
//启动SPI2,片选线CS,也就是DAC60004的SYNC引脚,SYNC引脚拉低,开启功能,输入的数字才有效
void SPI2_Start(void)
{
GPIO_ResetBits(GPIOG,GPIO_Pin_12);
}
//关闭SPI2,也就是拉高片选线CS,即DAC60004的SYNC
void SPI2_Stop(void)
{
GPIO_SetBits(GPIOG,GPIO_Pin_12);
}
void SPI2_Init(void)
{
//开启GPIO和SPI2的时钟
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB | RCC_AHB1Periph_GPIOG,ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2,ENABLE);
//初始化GPIO引脚,PB13,PB15分别对应CLK和MOSI,需要设置为复用推挽输出
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13 | GPIO_Pin_15;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB,&GPIO_InitStructure);
//复用引脚为SPI2
GPIO_PinAFConfig(GPIOB,GPIO_PinSource13,GPIO_AF_SPI2);
GPIO_PinAFConfig(GPIOB,GPIO_PinSource15,GPIO_AF_SPI2);
//配置引脚PB14为推挽输出
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_14;
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(GPIOB,&GPIO_InitStructure);
//配置引脚PG12(对应片选引脚)为上拉输出
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;
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(GPIOG,&GPIO_InitStructure);
//配置SPI2,其中CPHA的值必须为1,也就是SPI_CPHA_2Edge
//DAC60004的最大传输速率为50MHz,而SPI2挂载在APB1总线,对应频率为42MHz
SPI_InitTypeDef SPI_InitStructure;
SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_2;
SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;
SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;
SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;
SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
SPI_InitStructure.SPI_CRCPolynomial = 7;
SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;
SPI_Init(SPI2,&SPI_InitStructure);
SPI_Cmd(SPI2,ENABLE);
SPI2_Stop(); //初始化的时候,就要拉高片选线,对应DAC60004的SYNC
}
//交换一个字节的函数
uint8_t SPI2_SwapByte(uint8_t SPI2_Send)
{
uint8_t SPI2_Recv = 0;
//发送一个字节
while(SPI_I2S_GetFlagStatus(SPI2,SPI_I2S_FLAG_TXE) != SET);
SPI_SendData(SPI2,SPI2_Send);
//接收一个字节
while(SPI_I2S_GetFlagStatus(SPI2,SPI_I2S_FLAG_RXNE) != SET);
SPI2_Recv = SPI_I2S_ReceiveData(SPI2);
return SPI2_Recv;
}
SPI2.h
#ifndef __SPI2_H
#define __SPI2_H
#include "stm32f4xx.h" // Device header
void SPI2_Start(void);
void SPI2_Stop(void);
void SPI2_Init(void);
uint8_t SPI2_SwapByte(uint8_t SPI2_Send);
#endif
DAC60004.c
#include "DAC6004.h"
/*
SCLK PB13 SPI2
SDIN PB15 SPI2
SDO PB14 SPI2
SYNC PG12 SPI2
LDAC PG15 DAC6004 LOAD
CLR PB3 DAC6004
*/
void LOAD_UP(void)
{
GPIO_SetBits(GPIOG,GPIO_Pin_15);
}
void LOAD_Down(void)
{
GPIO_ResetBits(GPIOG,GPIO_Pin_15);
}
void CLR_UP(void)
{
GPIO_SetBits(GPIOB,GPIO_Pin_3);
}
void CLR_Down(void)
{
GPIO_ResetBits(GPIOB,GPIO_Pin_3);
}
//DAC60004初始化函数
void Init_DAC6004(void)
{
SPI2_Init();
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB | RCC_AHB1Periph_GPIOG,ENABLE);
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_15;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOG,&GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB,&GPIO_InitStructure);
LOAD_UP(); //LOAD —— LDAC引脚
CLR_UP(); //LCR —— CLR引脚
}
//交换指令码
uint32_t Swap_DAC6004(uint32_t sendbuf)
{
uint32_t Recv = 0;
SPI2_Start();
Recv = SPI2_SwapByte(sendbuf >> 24);
Recv <<= 8;
Recv |= SPI2_SwapByte(sendbuf >> 16);
Recv <<= 8;
Recv |= SPI2_SwapByte(sendbuf >> 8);
Recv <<= 8;
Recv |= SPI2_SwapByte(sendbuf);
delay_us(5);
SPI2_Stop();
return Recv;
}
DAC60004.h
#ifndef __DAC6004_H
#define __DAC6004_H
#include "stm32f4xx.h"
#include "SPI2.h"
#include "delay.h"
void LOAD_UP(void);
void LOAD_Down(void);
void CLR_UP(void);
void CLR_Down(void);
void Init_DAC6004(void);
uint32_t Swap_DAC6004(uint32_t sendbuf);
#endif
主函数代码,main.c
#include "stm32f4xx.h"
#include "delay.h"
#include "SPI1.h"
#include "SPI2.h"
#include "DAC6004.h"
int main(void)
{
Init_DAC6004(); //初始化DAC6004(包括SPI2)
while (1)
{
LOAD_UP();
//02:commands F:所有通道 000:电压有效数位 0:无意义,DAC6004只有12位,读取不到这一位
//最后一个0:Mode Bits
Swap_DAC6004(0X02F00000); //所以后通道的电压变为0
delay_ms(5);
LOAD_Down(); //更新输入的电压值,没有这一步,输出端的电压值不变
delay_s(3);
LOAD_UP();
Swap_DAC6004(0X02FFFF00); //所有通道的电压变为V ref(参考电压,REFIN电压)
delay_ms(5);
LOAD_Down();
delay_s(3);
LOAD_UP();
Swap_DAC6004(0X02F00000); //所有通道的电压变为0
delay_ms(5);
LOAD_Down();
delay_s(3);
LOAD_UP();
Swap_DAC6004(0X020FFF00); //通道a的电压变为V ref,其他通道的电压不变,仍然是0
delay_ms(5);
LOAD_Down();
delay_s(3);
}
}
/*
REFIN端接5v时,通道a的输出电压值与数字对应说明:
0x02000000 0V
0x02010000 0.31V
0x02020000 0.62V
0x02030000 0.92V
0x02040000 1.23V
0x02050000 1.54V
0x02060000 1.85V
0x02070000 2.16V
0x02080000 2.47V FFF/2 = 7FF,即800,所以此处输出的电压值为REFIN的一半
0x02090000 2.77V
0x020A0000 3.08V
0x020B0000 3.39V
0x020C0000 3.70V
0x020D0000 4.01V
0x020E0000 4.32V
0x020F0000 4.61V
0x020FFF00 4.93V
注:0~FFF相当于把5V的电压分成4096份,按照比例输出对应的电压
*/