如何用stm32驱动GP8413双路DAC

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


前言

提示:这里可以添加本文要记录的大概内容:

GP8413是一个I2C信号转模拟信号转换器,即DAC,此芯片可以将15Bit数字量0x0000-0x7FFF线性转换成两路独立的0-5V/0-10V模拟电压,输出电压误差为0.2%,线性度可达0.01%。


提示:以下是本篇文章正文内容,下面案例可供参考

一、GP8413特性

 GP8413 通过I2C接口,线性转换成0-5V/0-10V的两路模拟电压输出。
 一个I2C接口支持8路GP8413并联,通过三位硬件地址A2/A1/A0选择。
 VOUT=5V* DATA/0x7FFF或VOUT=10V*DATA/0x7FFF
 输入信号范围15Bit,0x0000-0x7FFF
 输入I2C信号高电平:2.7V-5.5V
 输出电压误差:< 0.2%
 输出电压线性度误差:0.01%
 输出短路保护,输出脚与地短路时芯片进入保护模式停止输出。
 电源电压:9V–36V
 功耗:<5mA
 启动时间:<2ms
 工作温度:-40°C to 85°C

二、管脚定义

管脚分布
其中A0,A1,A2为三位硬件地址,可以实现 8 片 GP8413 芯片的并接使用

典型电路如下所示,V5V为内部LDO,5V输出,必须外接大于1uF电容。VOUT作为板级接口使用时,加12V单向TVS,反接、浪涌保护。
在这里插入图片描述

三、代码编写

设置下图中红色配置位,地址设置为 02,则对 VOUT0 进行操作。将 15bit DATA 数据分为 DATA0 Low 和 DATA0 High 写 DATA0 Low为低 Byte, DATA0 High 为高 Byte。例如 0-10V 模式, 输出相对应的电压为:VOUT=DATA0/0x7FFF10V。
操作
设置下图中红色配置位, 地址设置为 04,则对 VOUT1 进行操作。 将 15bit DATA 数据分为 DATA Low 和 DATA High 写入, DATA Low为低 Byte, DATA High 为高 Byte。例如 0-10V 模式, 输出相对应的电压为:VOUT=DATA/0x7FFF
10V
在这里插入图片描述

1、头文件

代码如下(仅作参考):

//
// Created by LingFei Zhu on 2023/11/2.
//
#ifndef __GP8413_H
#define __GP8413_H
#ifdef __cplusplus
extern "C" {
#endif
#include "main.h"
#include "i2c_core.h"

#define CHANEL_COUNT           2            //DAC通道数目
#define SLAVE_ADDRESS          0X58         //DAC地址
#define RESOLUTION_15_BIT                   //12bit or 15bit数据,根据芯片来
#define GP8XXX_CONFIG_REG      0x2          //寄存器地址
#define in_min                 0            //最小输出电压,一般为0
#define in_max                 5            //最大输出电压,与需求相关
#define out_min                0            //i2c输出最小值0

#ifdef RESOLUTION_12_BIT
#define out_max 0x0FFF     //15bit输出最大值
#endif
#ifdef RESOLUTION_15_BIT
#define out_max 0x7FFF     //15bit输出最大值
#endif

typedef enum{
    chanel_0  = 2,
    chanel_1  = 4
}DAC_CHANEL_INDEX_T;

typedef enum{
    eOutputRange5V  = 1,
    eOutputRange10V = 2
}eOutPutRange_t;

typedef union{
    uint16_t voltage_value;
    uint8_t voltage_array[2];
}voltage_mapped;

typedef struct DAC_CHANEL_T
{
    DAC_CHANEL_INDEX_T CHANEL;   //记录是芯片的通道0 or 通道1
    uint8_t addr;                //DAC芯片的三位硬件地址
    uint16_t cur_voltage;        //记录当前输出电压值
}DAC_CHANEL;

uint8_t GP8413_init(i2c_dev *i2c_bus);
void setDACAddrArray(uint8_t index, uint8_t addr, DAC_CHANEL_INDEX_T chanel);
void setDACOutRange(uint8_t index, eOutPutRange_t range);
void setDACOutVoltage(uint8_t index,float voltage);
uint16_t readDACOutVoltage(uint8_t index);
uint8_t I2C_WriteRegister(uint8_t slave_addr, uint8_t reg_addr, uint8_t len, uint8_t *data_ptr);

#ifdef __cplusplus
}
#endif
#endif// __GP8413_H

2、c文件

代码如下(仅作参考):

//
// Created by LingFei Zhu on 2023/11/2.
//
#include "gp8413.h"
#include "i2c_hw.h"
#include "i2c_core.h"

struct DAC_CHANEL_T DAC_ID[CHANEL_COUNT];       //用于存放对应ID的索引和通道信息
i2c_dev *GP8413_dev = NULL;                     //GP8413的i2c设备结构体指针

/** @brief 初始化
 * */
uint8_t GP8413_init(i2c_dev *i2c_bus)
{
    if (NULL == i2c_bus)
    {
        return -1;
    }
    GP8413_dev = i2c_bus;

    return 0;
}
/** @brief 将电压数据映射到15bit数据上
 *  @param input 输入电压值
 *  @return 映射后的数据
 * */
uint16_t data_map(float input)
{
    return (uint16_t)((input - in_min) * (out_max - out_min) / (in_max - in_min) + out_min);

}
/** @brief 初始化索引数组
 *  @param addr DAC的3bit物理地址
 *  @param chanel DAC芯片的高低通道
 *  @param index 总的通道索引值
 * */
void setDACAddrArray(uint8_t index, uint8_t addr, DAC_CHANEL_INDEX_T chanel)
{
    DAC_ID[index].addr = SLAVE_ADDRESS | addr;
    DAC_ID[index].CHANEL = chanel;
    DAC_ID[index].cur_voltage = 0;
}
/** @brief 设定最大输出电压5V/10V
 *  @param index 总的通道索引值
 *  @param range 输出电压挡位设定
 * */
void setDACOutRange(uint8_t index, eOutPutRange_t range)
{
    uint8_t data = (range == eOutputRange10V) ? 0x11 : 0x00;   //5V模式发送0x00,10V模式发送0x11
    uint8_t slave_addr = DAC_ID[index].addr;                   //从数组中获取地址
    uint8_t reg_addr = GP8XXX_CONFIG_REG >> 1;         
    I2C_WriteRegister(slave_addr, reg_addr, 1, &data);

}
/** @brief 设定输出电压
 *  @param index 总的通道索引值
 *  @param voltage 输出电压值
 * */
void setDACOutVoltage(uint8_t index,float voltage)
{
    uint8_t slave_addr = DAC_ID[index].addr;            //从数组中获取地址
    uint8_t reg_addr = (DAC_ID[index].CHANEL == chanel_0) ? GP8XXX_CONFIG_REG : GP8XXX_CONFIG_REG <<1;
    voltage_mapped t;
    t.voltage_value= data_map(voltage);
    DAC_ID[index].cur_voltage = t.voltage_value;
    I2C_WriteRegister(slave_addr, reg_addr, 2, t.voltage_array);
}

/** @brief 读取当前输出电压
 *  @param index 总的通道索引值
 *  @return 当前输出电压值
 * */
uint16_t readDACOutVoltage(uint8_t index)
{
    return DAC_ID[index].cur_voltage;
}

/** @brief i2c发送函数
 *  @param slave_addr 器件地址
 *  @param reg_addr 寄存器地址
 *  @param len长度
 *  @param 数据地址
 * */
uint8_t I2C_WriteRegister(uint8_t slave_addr, uint8_t reg_addr, uint8_t len, uint8_t *data_ptr)
{
    i2c_message DAC_Msg[2];
    uint8_t	buf[2] = {0};
    buf[0] = reg_addr & 0xff;
    DAC_Msg[0].size  = 1;
    DAC_Msg[0].addr = slave_addr;
    DAC_Msg[0].flags = I2C_BUS_WR;
    DAC_Msg[0].buff  = buf;
    DAC_Msg[0].retries = 1;

    DAC_Msg[1].addr = slave_addr;
    DAC_Msg[1].flags = I2C_BUS_WR  | I2C_BUS_NO_START;
    DAC_Msg[1].buff  = (uint8_t*)data_ptr;
    DAC_Msg[1].size  = len;
    i2c_bus_xfer(GP8413_dev, DAC_Msg, 2);
    return len;

}


总结

GP8413的驱动还是比较简单的,I2C_WriteRegister为iic的发送函数,读者自行实现即可。

  • 7
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值