AD5593R模块介绍
AD5593R有8个输入/输出(I/O)引脚,可独立配置为数模转换器(DAC)输出、模数转换器(ADC)输入、数字输出或数字输入。当一个I/O引脚被配置为一个模拟输出时,它是由一个12位的DAC驱动的。DAC的输出范围为0V到VREF或0V到2×VREF。当I/O引脚被配置为模拟输入时,它通过模拟多路复用器连接到12位ADC。ADC的输入范围为0V到VREF或0V到2×VREF。输入/输出引脚也可以配置为通用的数字输入或输出(GPIO)引脚。可以通过I2C写或读取操作分别访问GPIO写数据寄存器和GPIO读取寄存器配置寄存器来设置或读回GPIO引脚的状态。
硬件电路连接
VCC,RES,ADD,VRE都接5V;
GND接GND;
SCL接PB6;
SDA接PB7;
其中RES引脚。将此引脚置高,以便于正常操作。当该引脚降低时,AD5593R将被重置为其默认配置,ADD为地址输入引脚。设置7位从属地址的LSB,IO0-7为8个输出通道。
软件设计
I2C写入的第一个字节一般是固定的,第一位为器件代码,根据手册内容第一位写入为(0X22),位[D7:D4]是选择要执行的操作的模式位。位[D3:D0]中包含的数据取决于所需的操作。要配置为DAC输出,
第二位写入应该为(0x05)即00000101。
第三位第四位为DAC通道配置,这边直接写入(0x00)、(0xFF),将所有通道都配置为DAC输出。
配置好了就需要进行DAC电压写入,这部分我参考了MCP4725的设计代码:(0x10)为通道0,(0x11)为通道1,以此内推,(0x17)为通道7。
void MCP4725_WriteData_Voltage(uint16_t Vout) //电压单位mV
{
uint8_t temp;
uint16_t Dn;
Dn = (4095 * Vout) / VREF_5V; //这里的VREF_5V宏定义为5000
temp = (0x0F00 & Dn) >> 8; //12位数据。0000XXXX XXXXXXXX
IIC_Start();
IIC_Send_Byte(0X22); //器件寻址,器件代吗:1100; 地址位A2,A1,A0为 0 , 0 , 1;-> 1100 0010
//这个地址0XC0或0XC1,根据自己购买的模块决定
IIC_Wait_Ack();
IIC_Send_Byte(0X10);
IIC_Wait_Ack();
IIC_Send_Byte(temp); //将高8位送到DAC寄存器
IIC_Wait_Ack();
IIC_Send_Byte(Dn); //将低8位送到DAC寄存器
IIC_Wait_Ack();
IIC_Stop();//产生一个停止条件
Delay_ms(10);
}
代码
MCP4725.h代码:
#ifndef __MCP4725_H
#define __MCP4725_H
#include "myIIC.h"
#define VREF_5V 3200 //这个数值根据自己给模块的供电电压而定
void MCP4725_Init(void);
void MCP4725_WriteData_Digital(uint16_t data);
void MCP4725_WriteData_Voltage(uint16_t Vout);
#endif
MCP4725.c代码:(其中0x03部分为配置2×VREF电压
)
#include "stm32f10x.h" // Device header
#include "MCP4725.h"
#include "delay.h"
//初始化IIC接口
void MCP4725_Init(void)
{
IIC_Init();
IIC_Start();
IIC_Send_Byte(0X22);
IIC_Wait_Ack();
IIC_Send_Byte(0X05);
IIC_Wait_Ack();
IIC_Send_Byte(0X00);
IIC_Wait_Ack();
IIC_Send_Byte(0XFF);
IIC_Wait_Ack();
IIC_Stop();//产生一个停止条件
Delay_ms(10);
IIC_Start();
IIC_Send_Byte(0X22);
IIC_Wait_Ack();
IIC_Send_Byte(0X03);
IIC_Wait_Ack();
IIC_Send_Byte(0X00);
IIC_Wait_Ack();
IIC_Send_Byte(0X00);//0X10为2*VREF,不超过供电电压
IIC_Wait_Ack();
IIC_Stop();//产生一个停止条件
Delay_ms(10);
}
//使用快速模式写命令写DAC寄存器
void MCP4725_WriteData_Voltage(uint16_t Vout) //电压单位mV
{
uint8_t temp;
uint16_t Dn;
Dn = (4095 * Vout) / VREF_5V; //这里的VREF_5V宏定义为5000
temp = (0x0F00 & Dn) >> 8; //12位数据。0000XXXX XXXXXXXX
IIC_Start();
IIC_Send_Byte(0X22); //器件寻址,器件代吗:1100; 地址位A2,A1,A0为 0 , 0 , 1;-> 1100 0010
//这个地址0XC0或0XC1,根据自己购买的模块决定
IIC_Wait_Ack();
IIC_Send_Byte(0X10);
IIC_Wait_Ack();
IIC_Send_Byte(temp); //将高8位送到DAC寄存器
IIC_Wait_Ack();
IIC_Send_Byte(Dn); //将低8位送到DAC寄存器
IIC_Wait_Ack();
IIC_Stop();//产生一个停止条件
Delay_ms(10);
}
void MCP4725_WriteData_Digital(uint16_t data) //12位数字量
{
uint8_t data_H=0,data_L=0;
data_H = (0x0F00 & data) >> 8;
data_L = 0X00FF & data ;
IIC_Start();
IIC_Send_Byte(0X22); //器件寻址,器件代吗:1100; 地址位A2,A1,A0为 0 , 0 , 0;-> 1100 0010
IIC_Wait_Ack();
IIC_Send_Byte(0X10);
IIC_Wait_Ack();
IIC_Send_Byte(data_H);
IIC_Wait_Ack();
IIC_Send_Byte(data_L);
IIC_Wait_Ack();
IIC_Stop();//产生一个停止条件
Delay_ms(10);
}
IIC.c代码:
#include "stm32f10x.h" // Device header
#include "myIIC.h"
#include "delay.h"
/*引脚配置*/
#define MCP4725_W_SCL(x) GPIO_WriteBit(GPIOB, GPIO_Pin_6, (BitAction)(x))
#define MCP4725_W_SDA(x) GPIO_WriteBit(GPIOB, GPIO_Pin_7, (BitAction)(x))
#define MCP4725_W_SDAIN GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_7)
//初始化IIC
void IIC_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB, ENABLE ); //使能GPIOB时钟
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6|GPIO_Pin_7; //PB6 ->SCL; PB7->SDA
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP ; //推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);
GPIO_SetBits(GPIOB,GPIO_Pin_6|GPIO_Pin_7); //PB6,PB7 输出高,因为IIC空闲状态都是高电平
}
//SDA设置为输入
void SDA_IN (void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB, ENABLE );
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOB, &GPIO_InitStructure);
}
//SDA设置为输出
void SDA_OUT(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB, ENABLE );
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP ;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);
}
//产生IIC起始信号
void IIC_Start(void)
{
SDA_OUT(); //sda线设置为输出
MCP4725_W_SDA(1);
MCP4725_W_SCL(1);
Delay_us(10);
MCP4725_W_SDA(0); //START:when CLK is high,DATA change form high to low
Delay_us(10);
MCP4725_W_SCL(0); //钳住I2C总线,准备发送或接收数据
}
//产生IIC停止信号
void IIC_Stop(void)
{
SDA_OUT();//sda线输出
MCP4725_W_SCL(0);
MCP4725_W_SDA(0); //STOP:when CLK is high DATA change form low to high
Delay_us(10);
MCP4725_W_SCL(1);
MCP4725_W_SDA(1); //发送I2C总线结束信号
Delay_us(10);
}
//等待应答信号到来
//返回值:1,接收应答失败
// 0,接收应答成功
uint8_t IIC_Wait_Ack(void)
{
uint8_t ucErrTime=0;
SDA_IN(); //SDA设置为输入
MCP4725_W_SDA(1);
Delay_us(2);
MCP4725_W_SCL(1);
Delay_us(2);
while(MCP4725_W_SDAIN)
{
ucErrTime++;
if(ucErrTime>250)
{
IIC_Stop();
return 1;
}
}
MCP4725_W_SCL(0);//时钟输出0
return 0;
}
//产生ACK应答
void IIC_Ack(void)
{
MCP4725_W_SCL(0);
SDA_OUT();
MCP4725_W_SDA(0);
Delay_us(5);
MCP4725_W_SCL(1);
Delay_us(5);
MCP4725_W_SCL(0);
}
//不产生ACK应答
void IIC_NAck(void)
{
MCP4725_W_SCL(0);
SDA_OUT();
MCP4725_W_SDA(1);
Delay_us(5);
MCP4725_W_SCL(1);
Delay_us(5);
MCP4725_W_SCL(0);
}
//IIC发送一个字节
//返回从机有无应答
//1,有应答
//0,无应答
void IIC_Send_Byte(uint8_t txd)
{
uint8_t t;
SDA_OUT();
MCP4725_W_SCL(0);//拉低时钟开始数据传输
for(t=0;t<8;t++) //开始准备信号线
{
if((txd&0x80)>>7)
MCP4725_W_SDA(1);
else
MCP4725_W_SDA(0);
txd<<=1;
Delay_us(5); //对TEA5767这三个延时都是必须的
MCP4725_W_SCL(1);
Delay_us(5);
MCP4725_W_SCL(0);
Delay_us(5);
}
}
//读1个字节,ack=1时,发送ACK,ack=0,发送nACK
uint8_t IIC_Read_Byte(unsigned char ack)
{
unsigned char i,receive=0;
SDA_IN();//SDA设置为输入
for(i=0;i<8;i++ )
{
MCP4725_W_SCL(0);
Delay_us(5);
MCP4725_W_SCL(1);
receive<<=1;
if(MCP4725_W_SDAIN)
{receive++; }
Delay_us(4);
}
if (!ack)
IIC_NAck();//发送nACK
else
IIC_Ack(); //发送ACK
return receive;
}
main.c代码:
#include "stm32f10x.h" // Device header
#include "Delay.h"
#include "LED.h"
#include "Serial.h"
#include "MCP4725.h"
#include "myIIC.h"
uint8_t RxData;
int main(void)
{
LED_Init();
MCP4725_Init();
Serial_Init();
GPIO_InitTypeDef GPIO_Initstructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE);
GPIO_Initstructure.GPIO_Pin = GPIO_Pin_13;
GPIO_Initstructure.GPIO_Speed = GPIO_Speed_10MHz;
GPIO_Initstructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIOC,&GPIO_Initstructure);
GPIO_SetBits(GPIOC,GPIO_Pin_13);
while (1)
{
//Serial_SendByte('B');
//GPIO_ResetBits(GPIOC, GPIO_Pin_13);
//Delay_ms(1000);
//GPIO_SetBits(GPIOC, GPIO_Pin_13);
//Delay_ms(1000);
MCP4725_WriteData_Voltage(2200);
}
}
小结
实测过,代码绝对可用,初学者,还请多多关照!需要工程代码可联系博主。