本期分享一个精密的 DAC 器件,为满足实验室项目对高精度数模转换的要求,我们选择了具有精密内部基准的双通道 12 位 DAC60502 芯片。
器件特性
- 16 位性能:1LSB INL 和 DNL(最大值)
- 低毛刺脉冲能量:4nV-s
- 宽电源电压范围:2.7V 至 5.5V
- 缓冲输出范围:5V、2.5V 或 1.25V
- 低功耗:1mA/通道 (5.5V)
- 集成 5ppm/˚C(最大值)、2.5V 精密基准
- 引脚可选串行接口
- 3 线制,兼容 SPI,高达 50MHz
- 两线制,兼容 I2C
- 上电复位:零电平或中间电平
- VDD = 5.5V 时的 VIH 为 1.62V
- 温度范围:–40˚C 至 +125˚C
- 封装:微型 10 引脚 WSON
器件应用
- 示波器 (DSO)
- 电池测试
- 半导体测试
- 数据采集 (DAQ)
- LCD 测试
- 小型蜂窝基站
- 模拟输出模块
- 过程分析(pH、气体、浓度、力和湿度)
- 直流电源、交流电源、电子负载
器件说明
16 位 DAC80502、14 位 DAC70502 和 12 位DAC60502 (DACx0502) 数模转换器 (DAC) 均为具有电压输出的高精度、低功耗器件。
DACx0502 线性度小于 1LSB。凭借高精度和微型封装特性,DACx0502 非常适合以下 应用: 增益和失调电压校准、电流或电压设置点设定和电源控制。这些器件包括一个 2.5V、5ppm/°C 内部基准,可提供 1.25V、2.5V 或 5V 的满量程输出电压范围。ACx0502 采用了上电复位电路,可确保 DAC 输出根据 RSTSEL 引脚的状态以零电平或中间电平上电,并在向器件写入有
效代码之前一直保持该电平。
DACx0502 的数字接口可通过 SPI2C 引脚配置为 SPI或 I2C 模式。在 SPI 模式下,DACx0502 使用一个在高达 50MHz 的时钟频率下运行的通用 3 线制串行接口。在 I2C 模式下,DACx0502 支持标准 (100kbps)、快速 (400kbps) 和快速+ (1.0Mbps) 工作模式。
功能方框图
引脚配置和功能
驱动模式
- SPI 或 IIC
寄存器映射
测试平台
- 测试平台:STM32F103ZET6
- 测试芯片:DAC60502
实验室自研基于 DAC60502 的双通道电流输出模块
驱动及应用示例
- myiic.c
#include "myiic.h" #include "delay.h" // 初始化IIC void IIC_Init(void) { RCC->APB2ENR|=1<<3; GPIOB->CRL&=0X00FFFFFF; GPIOB->CRL|=0X33000000; GPIOB->ODR|=3<<6; } // 产生IIC起始信号 void IIC_Start(void) { SDA_OUT(); IIC_SDA=1; IIC_SCL=1; delay_us(4); IIC_SDA=0; delay_us(4); IIC_SCL=0; } // 产生IIC停止信号 void IIC_Stop(void) { SDA_OUT(); IIC_SCL=0; IIC_SDA=0; delay_us(4); IIC_SCL=1; IIC_SDA=1; delay_us(4); } // 等待应答信号到来 // 返回值:1,接收应答失败 // 0,接收应答成功 uint8_t IIC_Wait_Ack(void) { uint8_t ucErrTime=0; SDA_IN(); IIC_SDA=1;delay_us(1); IIC_SCL=1;delay_us(1); while(READ_SDA) { ucErrTime++; if(ucErrTime>250) { IIC_Stop(); return 1; } } IIC_SCL=0; return 0; } // 产生ACK应答 void IIC_Ack(void) { IIC_SCL=0; SDA_OUT(); IIC_SDA=0; delay_us(2); IIC_SCL=1; delay_us(2); IIC_SCL=0; } // 不产生ACK应答 void IIC_NAck(void) { IIC_SCL=0; SDA_OUT(); IIC_SDA=1; delay_us(2); IIC_SCL=1; delay_us(2); IIC_SCL=0; } // IIC写一个字节 void IIC_Write_Byte(uint8_t txd) { uint8_t t; SDA_OUT(); IIC_SCL=0; for(t=0;t<8;t++) { IIC_SDA=(txd&0x80)>>7; txd<<=1; delay_us(2); IIC_SCL=1; delay_us(2); IIC_SCL=0; delay_us(2); } } // IIC读一个字节 // ack=1,发送ACK, // ack=0,发送nACK uint8_t IIC_Read_Byte(uint8_t ack) { uint8_t i,receive=0; SDA_IN(); for(i=0;i<8;i++ ) { IIC_SCL=0; delay_us(2); IIC_SCL=1; receive<<=1; if(READ_SDA)receive++; delay_us(1); } if (!ack) IIC_NAck(); else IIC_Ack(); return receive; } void IIC_Write_UINT16(uint8_t dev_addr, uint8_t wr_addr, uint16_t data) { IIC_Start(); IIC_Write_Byte(dev_addr); IIC_Wait_Ack(); IIC_Write_Byte(wr_addr); IIC_Wait_Ack(); IIC_Write_Byte(data >> 8); IIC_Wait_Ack(); IIC_Write_Byte(data & 0xFF); IIC_Wait_Ack(); IIC_Stop(); delay_ms(2); } uint16_t IIC_Read_UINT16(uint8_t dev_addr, uint8_t rd_addr) { uint16_t data; IIC_Start(); IIC_Write_Byte(dev_addr); IIC_Wait_Ack(); IIC_Write_Byte(rd_addr); IIC_Wait_Ack(); IIC_Start(); IIC_Write_Byte(dev_addr + 1); IIC_Wait_Ack(); data = IIC_Read_Byte(1); data = (data <<8 ) + IIC_Read_Byte(0); IIC_Stop(); return data; }
- myiic.h
#ifndef __MYIIC_H__ #define __MYIIC_H__ #include "sys.h" //IO方向设置 #define SDA_IN() {GPIOB->CRL&=0X0FFFFFFF;GPIOB->CRL|=(u32)8<<28;} #define SDA_OUT() {GPIOB->CRL&=0X0FFFFFFF;GPIOB->CRL|=(u32)3<<28;} //IO操作函数 #define IIC_SCL PBout(6) //SCL #define IIC_SDA PBout(7) //SDA #define READ_SDA PBin(7) //输入SDA //IIC操作函数 void IIC_Init(void); //初始化IIC的IO口 void IIC_Start(void); //发送IIC开始信号 void IIC_Stop(void); //发送IIC停止信号 void IIC_Write_Byte(uint8_t txd); //IIC发送一个字节 uint8_t IIC_Read_Byte(uint8_t ack); //IIC读取一个字节 uint8_t IIC_Wait_Ack(void); //IIC等待ACK信号 void IIC_Ack(void); //IIC发送ACK信号 void IIC_NAck(void); //IIC不发送ACK信号 void IIC_Write_UINT16(uint8_t dev_addr, uint8_t wr_addr, uint16_t data); uint16_t IIC_Read_UINT16(uint8_t dev_addr, uint8_t rd_addr); #endif
- dacx0502.c
#include "dac60502.h" #include "delay.h" //初始化IIC接口 int DAC60502_Init(void) { IIC_Init(); return 0; } void DAC60502_Write(uint16_t WrAddr, uint16_t Data) { IIC_Write_UINT16(DEV_ADDR, WrAddr, Data); } uint16_t DAC60502_Read(uint16_t RdAddr) { return IIC_Read_UINT16(DEV_ADDR, RdAddr); }
- dac60502.h
#ifndef __DAC60502_H__ #define __DAC60502_H__ #include "myiic.h" #define DEV_ADDR 0x90 #define NOOP 0x00 #define DEVID 0x01 #define SYNC 0x02 #define CONFIG 0x03 #define GAIN 0x04 #define TRIGGER 0x05 #define STATUS 0x06 #define DAC_A 0x08 #define DAC_B 0x09 int DAC60502_Init(void); void DAC60502_Write(uint16_t WrAddr, uint16_t Data); uint16_t DAC60502_Read(uint16_t RdAddr); #endif
- main.c
#include "sys.h" #include "delay.h" #include "usart.h" #include "led.h" #include "dac60502.h" #include "usmart.h" int main(void) { uint16_t data = 0; Stm32_Clock_Init(9); //系统时钟设置 uart_init(72,115200); //串口初始化为115200 delay_init(72); //延时初始化 usmart_dev.init(72); //初始化USMART LED_Init(); //初始化与LED连接的硬件接口 DAC60502_Init(); //IIC初始化 while(1) { data = data + 0x1; if(data > 0x0fff) data = 0; DAC60502_Write(DAC_A,data << 4); printf("Write: %d \r\n", data); delay_ms(100); printf("Read: %d \r\n", DAC60502_Read(DAC_A) >> 4); delay_ms(100); LED0=!LED0; } return 0; }
本期介绍了 DACx0502 系列双通道数模转换器及使用 STM32 驱动 DAC60502 的使用示例,在后期将会移植到 Zynq 嵌入式系统中进行开发设计。