注: SCL配置为推挽输出模式 SDA配置为开漏输出模式 CS配置为推挽输出模式 LDAC配置为推挽输出模式 RDY配置为输入模式
#include "main.h"
#include "stdint.h"
#include "delay.h"
#define MCP4728_ADDR1 0xC0
#define MCP4728_ADDR2 0xC4
#define MCP4728_ADDR3 0xC8
#define MCP4728_Channel_A 0x00
#define MCP4728_Channel_B 0x02
#define MCP4728_Channel_C 0x04
#define MCP4728_Channel_D 0x06
#define SCL_Pin_SET() HAL_GPIO_WritePin(MCP4728_SCL_GPIO_Port, MCP4728_SCL_Pin, GPIO_PIN_SET)
#define SCL_Pin_RESET() HAL_GPIO_WritePin(MCP4728_SCL_GPIO_Port, MCP4728_SCL_Pin, GPIO_PIN_RESET)
#define SDA_Pin_SET() HAL_GPIO_WritePin(MCP4728_SDA_GPIO_Port, MCP4728_SDA_Pin, GPIO_PIN_SET)
#define SDA_Pin_RESET() HAL_GPIO_WritePin(MCP4728_SDA_GPIO_Port, MCP4728_SDA_Pin, GPIO_PIN_RESET)
#define LDAC1_Pin_SET() HAL_GPIO_WritePin(MCP4728_LDAC1_GPIO_Port, MCP4728_LDAC1_Pin, GPIO_PIN_SET)
#define LDAC1_Pin_RESET() HAL_GPIO_WritePin(MCP4728_LDAC1_GPIO_Port, MCP4728_LDAC1_Pin, GPIO_PIN_RESET)
#define LDAC2_Pin_SET() HAL_GPIO_WritePin(MCP4728_LDAC2_GPIO_Port, MCP4728_LDAC2_Pin, GPIO_PIN_SET)
#define LDAC2_Pin_RESET() HAL_GPIO_WritePin(MCP4728_LDAC2_GPIO_Port, MCP4728_LDAC2_Pin, GPIO_PIN_RESET)
#define LDAC3_Pin_SET() HAL_GPIO_WritePin(MCP4728_LDAC3_GPIO_Port, MCP4728_LDAC3_Pin, GPIO_PIN_SET)
#define LDAC3_Pin_RESET() HAL_GPIO_WritePin(MCP4728_LDAC3_GPIO_Port, MCP4728_LDAC3_Pin, GPIO_PIN_RESET)
#define SDA_Pin_READ() HAL_GPIO_ReadPin(MCP4728_SDA_GPIO_Port, MCP4728_SDA_Pin)
#define RDY1_Pin_READ() HAL_GPIO_ReadPin(MCP4728_RDY1_GPIO_Port, MCP4728_RDY1_Pin)
#define RDY2_Pin_READ() HAL_GPIO_ReadPin(MCP4728_RDY2_GPIO_Port, MCP4728_RDY2_Pin)
#define RDY3_Pin_READ() HAL_GPIO_ReadPin(MCP4728_RDY3_GPIO_Port, MCP4728_RDY3_Pin)
static void IIC_Start_MCP4728(void)
{
SDA_Pin_SET();
SCL_Pin_SET();
delay_us(4);
SDA_Pin_RESET();
delay_us(4);
SCL_Pin_RESET();
}
static void IIC_Stop(void)
{
SCL_Pin_RESET();
SDA_Pin_RESET();
delay_us(5);
SCL_Pin_SET();
SDA_Pin_SET();
delay_us(5);
}
uint8_t I2C1_Wait_Ack(void)
{
uint16_t ucErrTime = 0;
SDA_Pin_SET();
delay_us(1);
SCL_Pin_SET();
delay_us(1);
while(SDA_Pin_READ() == GPIO_PIN_SET)
{
ucErrTime++;
if(ucErrTime>1000)
{
IIC_Stop();
return 1;
}
}
SCL_Pin_RESET();
return 0;
}
void I2C1_Ack(void)
{
SCL_Pin_RESET();
SDA_Pin_RESET();
delay_us(2);
SCL_Pin_SET();
delay_us(2);
SCL_Pin_RESET();
}
void I2C1_NAck(void)
{
SCL_Pin_RESET();
SDA_Pin_SET();
delay_us(2);
SCL_Pin_SET();
delay_us(2);
SCL_Pin_RESET();
}
void I2C1_Send_One_Byte(uint8_t txd)
{
uint8_t t;
SCL_Pin_RESET();
for(t=0; t<8; t++)
{
if (txd & 0x80) SDA_Pin_SET();
else SDA_Pin_RESET();
txd<<=1;
delay_us(2);
SCL_Pin_SET();
delay_us(2);
SCL_Pin_RESET();
delay_us(2);
}
}
static void IIC_SendACK(uint8_t ack)
{
if(ack!=0) SDA_Pin_SET();
else SDA_Pin_RESET();
SCL_Pin_SET();
delay_us(5);
SCL_Pin_RESET();
delay_us(5);
}
static uint8_t IIC_RecvACK(void)
{
uint8_t rtn = 1;
SCL_Pin_SET();
delay_us(5);
rtn = SDA_Pin_READ();
SCL_Pin_RESET();
delay_us(5);
return rtn;
}
static uint8_t IIC_SendByte(uint8_t dat)
{
uint8_t i;
for (i=0; i<8; i++)
{
if (dat & 0x80) SDA_Pin_SET();
else SDA_Pin_RESET();
delay_us(1);
SCL_Pin_SET();
delay_us(5);
SCL_Pin_RESET();
dat <<= 1;
delay_us(5);
}
SDA_Pin_SET();
return IIC_RecvACK();
}
uint8_t I2C1_Read_One_Byte(unsigned char ack)
{
unsigned char i,receive=0;
for(i=0; i<8; i++ )
{
SCL_Pin_RESET();
delay_us(2);
SCL_Pin_SET();
receive<<=1;
if(SDA_Pin_READ() == GPIO_PIN_SET)
{
receive |= 1;
}
delay_us(1);
}
if (!ack)
I2C1_NAck();
else
I2C1_Ack();
return receive;
}
static uint8_t IIC_RecvByte(void)
{
uint8_t i;
uint8_t dat = 0;
SDA_Pin_SET();
for (i=0; i<8; i++)
{
dat <<= 1;
SCL_Pin_SET();
delay_us(5);
if(SDA_Pin_READ() == GPIO_PIN_SET)
{
dat |= 0x01;
}
SCL_Pin_RESET();
delay_us(5);
}
return dat;
}
uint8_t MCP4728_ReadData(uint8_t* DataRcvBuf)
{
uint8_t rt;
uint8_t i;
IIC_Start_MCP4728();
rt = IIC_SendByte(MCP4728_ADDR1 + 1);
if(rt == 1)
{
return 1;
}
for(i = 0; i < 23; i++)
{
DataRcvBuf[i] = IIC_RecvByte();
IIC_SendACK(0);
}
DataRcvBuf[i] = IIC_RecvByte();
IIC_SendACK(1);
IIC_Stop();
return 0;
}
uint8_t MCP4728_ReadAddr(const uint8_t cs)
{
uint8_t rt = rt = 1;
uint8_t ADDR_Read = 0;
LDAC1_Pin_SET();
LDAC2_Pin_SET();
LDAC3_Pin_SET();
IIC_Start_MCP4728();
I2C1_Send_One_Byte(0x00);
rt = I2C1_Wait_Ack();
I2C1_Send_One_Byte(0x0C);
switch(cs)
{
case 0x01:
LDAC1_Pin_RESET();
break;
case 0x02:
LDAC2_Pin_RESET();
break;
case 0x03:
LDAC3_Pin_RESET();
break;
default:
break;
}
rt = I2C1_Wait_Ack();
IIC_Start_MCP4728();
I2C1_Send_One_Byte(0xC1);
rt = I2C1_Wait_Ack();
ADDR_Read = I2C1_Read_One_Byte(0);
IIC_Stop();
ADDR_Read = ((ADDR_Read >> 4) & 0x0E) | 0xC0;
return ADDR_Read;
}
void change_address(uint8_t OldAddr, uint8_t Cmd_NewAdd, const uint8_t cs)
{
LDAC1_Pin_SET();
LDAC2_Pin_SET();
LDAC3_Pin_SET();
IIC_Start_MCP4728();
I2C1_Send_One_Byte(OldAddr);
I2C1_Wait_Ack();
I2C1_Send_One_Byte(((OldAddr & 0x0E) << 1) | 0x61);
switch(cs)
{
case 0x01:
LDAC1_Pin_RESET();
break;
case 0x02:
LDAC2_Pin_RESET();
break;
case 0x03:
LDAC3_Pin_RESET();
break;
default:
break;
}
I2C1_Wait_Ack();
I2C1_Send_One_Byte(((Cmd_NewAdd & 0x0E) << 1) | 0x62);
I2C1_Wait_Ack();
I2C1_Send_One_Byte(((Cmd_NewAdd & 0x0E) << 1) | 0x63);
I2C1_Wait_Ack();
IIC_Stop();
delay_ms(20);
}
void MCP4728Init(void)
{
uint8_t addr1;
uint8_t addr2;
uint8_t addr3;
delay_ms(5);
addr1 = MCP4728_ReadAddr(1);
addr2 = MCP4728_ReadAddr(2);
addr3 = MCP4728_ReadAddr(3);
if(addr1 != MCP4728_ADDR1)
{
change_address(addr1, MCP4728_ADDR1, 1);
}
if(addr2 != MCP4728_ADDR2)
{
change_address(addr2, MCP4728_ADDR2, 2);
}
if(addr3 != MCP4728_ADDR3)
{
change_address(addr3, MCP4728_ADDR3, 3);
}
LDAC1_Pin_SET();
LDAC2_Pin_SET();
LDAC3_Pin_SET();
}
uint8_t MCP4728_SetVoltage(const uint8_t Addr, const uint8_t Channel, const uint16_t AnalogVol, const uint8_t WriteEEPROM)
{
uint8_t rt;
uint8_t SendData;
uint16_t temp_u16 = AnalogVol;
temp_u16 = (temp_u16 > 4095) ? 4095 : temp_u16;
IIC_Start_MCP4728();
rt = IIC_SendByte(Addr);
SendData = (WriteEEPROM == 1) ? 0x58|Channel : 0x40|Channel;
rt = IIC_SendByte(SendData);
SendData = 0x90 | (temp_u16>>8);
rt = IIC_SendByte(SendData);
SendData = temp_u16 & 0xFF;
rt = IIC_SendByte(SendData);
if(rt == 1)
{
return 0;
}
IIC_Stop();
return 1;
}
|