目录
前言
技术要点
1、引脚功能
2、配置位:
3、DAC数值对应计算关系
5、写指令类型
MCP4728驱动
1、快速写
2、同时写2路
3、一次写多路DAC
4、单次写入DAC
使用注意
MCP4728是一款4通道输出DAC芯片,分辨率为12bit,通信接口为I2C,而且内部自带EEPROM,EEPROM功能使得DAC器件在断点后仍然能够保持DAC输入寄存器值,这样就尤为方便了,因为是第一次使用,关于这个芯片的稳定性,还需要进一步测试。
这里面其他的引脚都好理解,主要是LDAC引脚比较重要,这个引脚,在功能说明上解释的是“同步输入”,也就是向输入寄存器中写入数值后,通过拉低该引脚进行同步输出电压。需要特别注意的是:
1)并不是一定要通过拉低LDAC才能同步输出电压的,在后面的介绍中,其实有一个软件功能位-UDAC位,只要将该位设置为0,也是可以实现同步输出的。
2)拉低LDAC会同步输出所有的4个通道电压。
3)设置UDAC为0,只会同步输出配置的那个通道。
这个表里,我们主要先熟悉一些配置位:
A2 A1 A0 :器件地址,默认为 000
Vref:参考电压选择,0-电源电压VDD,1-内部参考电压 2.048V
Gx:增益配置位,0-x1;1-x2,需要注意的是,如果我们的电源使用的是3.3V,那么我们不能设置增益为2.因为最大不能超过 Vdd
UDAC:同步输出位,我们如果不用外部LDAC引脚,只用UDAC位即可。
上图主要是对应最小分辨率对应的 电压(mV)值,最大值是固定的(4096),因为12bit。
上图中,我们主要关心的是Dn的计算,也就是我们想要DAC输出多大电压对应的寄存器数值。
4、DAC电压输出值的刷新操作。
mcp4728的输出并不是往寄存器中写入数值就可以的,需要配合外部LDAC引脚或者软件UDAC位,注意这里用了“或者”,表示这两种方式都是可以的。
1)拉低LDAC会同步输出所有的4个通道电压。
2)设置UDAC为0,只会同步输出配置的那个通道。
快速写的意思是,一次写4路DAC,并且这4路DAC输出同样大小的电压,这种模式不会存放到EEPROM中,对应时序:
最多同时写4路DAC,但是也支持2/3/4路。
我们以同时写4路DAC,并且这4路DAC的电压不相同,Vref = 2.048V,不适用LDAC为例,则驱动代码如下:
int mcp4728_write_all_channel(float vol1, float vol2, float vol3, float vol4)
{
u16 Dn[4];
u8 h_byte[4];
u8 l_byte[4];
int i;
Dn[0] = ( u16 )(vol1*2000);
Dn[1] = ( u16 )(vol2*2000);
Dn[2] = ( u16 )(vol3*2000);
Dn[3] = ( u16 )(vol4*2000);
for(i = 0; i < 4; i++){
Dn[i] = Dn[i]&0xFFFF;
Dn[i] = 0x8000|Dn[i]; // vref=1, PD0=0,PD1=0,Gx=0
h_byte[i] = ( u8 )(Dn[i] >> 8);
l_byte[i] = ( u8 )(Dn[i]);
}
MCP4728_IIC_Start();
MCP4728_IIC_SendByte( MCP4728_ADDR );
MCP4728_IIC_WaitAck();
MCP4728_IIC_SendByte( 0x50 ); // C2=0,C1=1,C0=0,W1=1,W2=0,DAC1=0,DAC0=0,
MCP4728_IIC_WaitAck();
for(i = 0; i < 4; i++){
MCP4728_IIC_SendByte( h_byte[i] );
MCP4728_IIC_WaitAck();
MCP4728_IIC_SendByte( l_byte[i] );
MCP4728_IIC_WaitAck();
}
MCP4728_IIC_Stop();
return 0;
}
该功能用于单次写某一通道DAC,
Vref = 2.048V,不适用LDAC为例,则驱动代码如下:
int mcp4728_write_signle(u8 chn, float vol)
{
u16 Dn;
u8 byte1,byte2,byte3,byte4;
byte1 = MCP4728_ADDR;
Dn = ( u16 )(vol*2000); // Vout*4096/2.048/1
switch( chn ){
case 1:
byte2 = 0x58; // UDAC = 0,upload output
break;
case 2:
byte2 = 0x5A; // UDAC = 0
break;
case 3:
byte2 = 0x5C; // UDAC = 0
break;
case 4:
byte2 = 0x5E; // UDAC = 0
break;
default:
byte2 = 0x58; // default channel A
break;
}
Dn = Dn&0xFFFF;
Dn = 0x8000|Dn; // vref=1, PD0=0,PD1=0,Gx=0
byte3 = ( u8 )(Dn >> 8);
byte4 = ( u8 )(Dn);
MCP4728_IIC_Start();
MCP4728_IIC_SendByte( byte1 );
MCP4728_IIC_WaitAck();
MCP4728_IIC_SendByte( byte2 );
MCP4728_IIC_WaitAck();
MCP4728_IIC_SendByte( byte3 );
MCP4728_IIC_WaitAck();
MCP4728_IIC_SendByte( byte4 );
MCP4728_IIC_WaitAck();
MCP4728_IIC_Stop();
return 0;
}
1、我们可能希望通过单次写入的方式分别控制各路DAC输出,但是这里经过测试发现,如果我们写入某一DAC后,立刻再写入,也就是说想要连续多次进行“单次写入”功能是会失败的,这个原因就是EEPROM的RDY状态,如果想要实现执行多次“单次吸入”操作,我们需要检测RDY引脚状态,或者我们做好演示。
2、多次写入操作,支持一次写4个DAC通道,并且这4个DAC通道的设定值可以不同,这就要求我们在写程序的时候,需要注意了。如何想要只改变某一个DAC而不影响其他DAC。