正在做NCV84090DR2G设计?看过来!

正在做NCV84090DR2G设计?看过来!

TechForum分享者:yinxiangxv

关键词:ADC,开关,开发板

NCV80490硬件电路搭建和负载驱动

要让上面的模块能够正常工作首先要提供一个稳定的直流电压12V。并且要明确每个引脚的功能和定义:

引脚连接说明:

  • VD (电源): 这是芯片的功率电源输入。
  • 连接: 将这两个引脚(VD)直接连接到汽车电池的正极 (V_BAT, 通常为12V)。
  • 设计要点: 在VD和GND之间放置一个100nF的陶瓷电容作为退耦电容,尽可能靠近芯片引脚。这能滤除电源噪声,保证芯片稳定工作。
  • GND (地): 芯片的参考地。
  • 连接: 连接到系统的地平面 (GND)。
  • OUT (输出): 功率输出端。
  • 连接: 将这两个引脚(OUT)连接到负载 Z_L 的一端。负载的另一端连接到系统地 (GND)。
  • IN (输入): 逻辑控制输入。
  • 连接: 连接到MCU的一个GPIO输出引脚。MCU通过输出高电平(例如5V或3.3V)来命令芯片导通,输出低电平(0V)来命令芯片关断。
  • 设计要点: 可以在MCU和IN引脚之间串联一个小电阻(如 1kΩ),用于限流保护MCU的GPIO口。
  • CS_EN (电流检测使能): 诊断功能使能。
  • 连接: 连接到MCU的另一个GPIO输出引脚。MCU输出高电平来激活电流检测和所有诊断功能,输出低电平来关闭它们以降低功耗。
  • CS (电流检测): 模拟反馈输出。
  • 连接: 连接到MCU的一个ADC(模数转换器)输入引脚。
  • 设计要点: 这是最关键的外围电路设计。

在CS引脚和GND之间连接一个精密电阻 R_CS。芯片输出的检测电流 I_CS 流过这个电阻,产生一个MCU可以测量的电压 V_CS。R_CS 的值需要根据最大负载电流和MCU的ADC量程来计算(具体见应用案例)。

在CS引脚和GND之间并联一个小电容 C_CS(如 1nF)。它与 R_CS 组成一个RC低通滤波器,滤除噪声,为ADC提供一个稳定的信号。

image
image
image

如果上面的12v满足之后就要进行控制了。

按照这个思路进行:

简易原理图描述:

  • 电源部分: V_BAT或者12v直流电源 → NCV84090的 VD 引脚。
  • 负载部分: NCV84090的 OUT 引脚 → 负载 Z_L → GND。
  • 控制部分 (MCU):
  • MCU GPIO_1 → 1kΩ电阻 → IN 引脚。
  • MCU GPIO_2 → CS_EN 引脚。
  • MCU ADC_1 → CS 引脚。
  • 反馈部分: CS 引脚 → R_CS → GND。同时,CS 引脚 → C_CS → GND。

根据上面提到的控制部分,刚好手边有一个开发板,是创龙的t113,正好用来进行控制的逻辑。

为此要实现这些函数:

1. 驱动函数接口 (API) 设计:

void NCV84090_Init(pin_IN, pin_CS_EN, pin_CS): 初始化函数,配置MCU的GPIO和ADC引脚。

void NCV84090_TurnOn(): 打开开关。内部实现是将 IN 引脚置为高电平。

void NCV84090_TurnOff(): 关闭开关。内部实现是将 IN 引脚置为低电平。

void NCV84090_EnableDiagnostics(bool enable): 使能/禁能诊断。控制 CS_EN 引脚。

float NCV84090_ReadCurrent(): 核心功能,读取并返回以安培(A)为单位的负载电流。

FaultType NCV84090_CheckFault(): 诊断函数,返回当前检测到的故障类型(如正常、开路、短路等)。

2. 核心函数实现逻辑:

NCV84090_ReadCurrent() 实现:

确保开关已导通 (IN = High) 且诊断已使能 (CS_EN = High)。

等待稳定时间! 根据数据手册,从 IN 变高到 CS 信号稳定需要一个延迟 t_CS_High2。程序必须等待超过这个时间。

通过MCU的ADC读取 CS 引脚的电压 V_CS。

计算检测电流: I_CS = V_CS / R_CS。

查表计算真实电流: NCV84090的电流检测比 K 是非线性的。需要根据数据手册中的 K vs I_OUT 曲线创建一个查找表。通过 I_CS 估算 I_OUT 范围,然后在表中查找或插值得到准确的 K 值。

计算最终电流: I_OUT = I_CS * K。

返回 I_OUT。

NCV84090_CheckFault() 实现:

导通状态故障:

读取 V_CS 电压。如果 V_CS 远高于正常工作范围,达到了一个固定的故障电压 V_CS_FAULT,则说明发生了过流、短路或过热故障。

关断状态开路故障:

执行诊断序列:将 IN 置低,CS_EN 置高。

等待延迟 t_d_OL_off。

读取 V_CS 电压。如果此时 V_CS 被拉高到 V_CS_FAULT,则说明发生了开路负载故障。

第二步:确定T113上使用的GPIO

你需要查看你的 T113 开发板的原理图或引脚分布图,找到一个空闲的、可以作为 GPIO 输出的引脚。全志的芯片引脚命名通常是 P + 组号 + 序号,例如 PB5 (第B组的第5个引脚) 或 PG13 (第G组的第13个引脚)。

假设我们选择了 PB5 这个引脚。

image

第三步:在T113的Linux系统中控制GPIO

在 root@T113-Tronlong:~# 这个运行环境中,控制 GPIO 最直接、最标准的方法是通过 Linux 的 sysfs GPIO 接口。这是一种通过读写虚拟文件来控制硬件的方式,非常方便。

以下是完整的命令行操作步骤:

1. 导出 (Export) GPIO

首先,你需要告诉内核,你想要使用 PB5 这个引脚。你需要计算出它的编号。

GPIO 编号计算公式: (组号 ASCII – ‘A’) * 32 + 序号

对于 PB5: (‘B’的ASCII – ‘A’的ASCII) * 32 + 5 → (1) * 32 + 5 = 37

现在,导出这个GPIO:

echo 37 > /sys/class/gpio/export

执行成功后,系统会创建一个新的目录 /sys/class/gpio/gpio37。

2. 设置GPIO方向 (Direction)

接下来,你需要将这个GPIO设置为输出模式。

echo “out” > /sys/class/gpio/gpio37/direction

3. 控制GPIO输出高低电平

现在,你可以通过向 value 文件写入 1 或 0 来控制GPIO输出高电平或低电平了。

输出高电平 (3.3V) → 导通NCV84090 → 负载工作:

echo 1 > /sys/class/gpio/gpio37/value

当你执行这条命令时,T113的PB5引脚会输出高电平,NCV84090的IN引脚收到高电平,其内部开关导通,OUT引脚被拉到地,电流流过你的负载,负载开始工作(例如,继电器吸合,LED点亮)。

输出低电平 (0V) → 关断NCV84090 → 负载停止:

echo 0 > /sys/class/gpio/gpio37/value

当你执行这条命令时,PB5引脚输出低电平,NCV84090的IN引脚收到低电平,其内部开关断开,OUT引脚变为高阻态,负载上没有电流流过,负载停止工作。

4. (可选) 释放 (Unexport) GPIO

当你不再使用这个GPIO时,可以将其释放,让其他程序使用。

echo 37 > /sys/class/gpio/unexport

第四步:编写Shell脚本实现自动化控制

你可以把上述命令写到一个Shell脚本里,方便调用。例如,创建一个名为 control_load.sh 的脚本:

如何使用这个脚本:

在T113上,用vi control_load.sh创建并编辑这个文件,把代码粘贴进去。

给脚本添加执行权限: chmod +x control_load.sh

打开负载: ./control_load.sh on

关闭负载: ./control_load.sh off

这样,就成功地在你的T113运行环境中,通过编程(Shell脚本)的方式,利用GPIO控制了外部的NCV84090芯片,并驱动了一个12V的负载。

上面的代码是通过shell代码的方式进行运行的。不过也可以通过c代码的方式进行。

A screenshot of a computer program

AI-generated content may be incorrect.

下面看看相关函数的c代码如何实现:

使用C语言(推荐用于最终产品)

这是最正规、最高效的方式。我们需要利用Linux提供的系统调用来访问sysfs接口。

1. 环境准备

你的T113开发板的Linux系统里通常已经内置了C语言的交叉编译工具链(gcc)或者你可以通过opkg或apt安装它。

2. C语言代码实现

下面是一个C语言实现的示例,它基本实现了你设计的API。

文件: ncv84090_driver.c

# 运行编译好的程序

这样的就必须要启用虚拟机的环境进行编译,为此还是用这个shell代码比较直接:

image

后面的测试等下次再进行吧,这个逻辑上和硬件的连线上面没什么问题,调试没什么问题,应该就可以连接硬件后运行代码,并也可以配合示波器进行检测。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdbool.h>

// --- 定义GPIO编号 (根据你的硬件连接修改) ---
// 假设 IN -> PB5 -> 37
// 假设 CS_EN -> PG13 -> 205
#define PIN_IN_NUM    37
#define PIN_CS_EN_NUM 205

// --- 全局变量存储引脚编号 ---
static int pin_IN = -1;
static int pin_CS_EN = -1;
// ADC引脚通常通过IIO子系统访问,这里简化处理
// static int pin_CS = -1; 

// --- 底层GPIO操作函数 ---
int gpio_export(int pin) {
    char buffer[64];
    int fd = open("/sys/class/gpio/export", O_WRONLY);
    if (fd < 0) {
        perror("Failed to open export for writing");
        return -1;
    }
    int len = snprintf(buffer, sizeof(buffer), "%d", pin);
    if (write(fd, buffer, len) < 0) {
        // Ignore error if already exported
    }
    close(fd);
    return 0;
}

int gpio_set_direction(int pin, const char* dir) {
    char path[64];
    snprintf(path, sizeof(path), "/sys/class/gpio/gpio%d/direction", pin);
    int fd = open(path, O_WRONLY);
    if (fd < 0) {
        perror("Failed to open direction for writing");
        return -1;
    }
    if (write(fd, dir, strlen(dir)) < 0) {
        perror("Failed to set direction");
        close(fd);
        return -1;
    }
    close(fd);
    return 0;
}

int gpio_set_value(int pin, int value) {
    char path[64];
    snprintf(path, sizeof(path), "/sys/class/gpio/gpio%d/value", pin);
    int fd = open(path, O_WRONLY);
    if (fd < 0) {
        perror("Failed to open value for writing");
        return -1;
    }
    char val_str = (value == 1) ? '1' : '0';
    if (write(fd, &val_str, 1) != 1) {
        perror("Failed to write value");
        close(fd);
        return -1;
    }
    close(fd);
    return 0;
}

// --- ADC读取函数 (这是一个简化的示例) ---
// 在真实的T113系统中,你需要通过IIO (Industrial I/O)子系统来读取ADC
// 通常是读取 /sys/bus/iio/devices/iio:deviceX/in_voltageY_raw 文件
float read_adc_voltage() {
    // 伪代码: 实际实现会更复杂
    int raw_value;
    float voltage;
    char buffer[16];
    
    // 假设ADC在iio:device0的通道1
    int fd = open("/sys/bus/iio/devices/iio:device0/in_voltage1_raw", O_RDONLY);
    if (fd < 0) {
        perror("Failed to open ADC raw file");
        return -1.0;
    }
    read(fd, buffer, sizeof(buffer)-1);
    close(fd);

    raw_value = atoi(buffer);
    // 假设ADC是12位(4096),参考电压是1.8V
    voltage = (float)raw_value / 4095.0 * 1.8; 
    
    printf("ADC Raw: %d, Voltage: %.3fV\n", raw_value, voltage);
    return voltage;
}


// --- API 实现 ---

/**
 * @brief 初始化NCV84090驱动
 * @note 在Linux sysfs中,不需要传入pin号,硬编码或从配置文件读取
 */
void NCV84090_Init() {
    pin_IN = PIN_IN_NUM;
    pin_CS_EN = PIN_CS_EN_NUM;

    printf("Initializing NCV84090 driver...\n");
    gpio_export(pin_IN);
    gpio_export(pin_CS_EN);

    gpio_set_direction(pin_IN, "out");
    gpio_set_direction(pin_CS_EN, "out");

    // Set initial state
    NCV84090_TurnOff();
    NCV84090_EnableDiagnostics(false);
    printf("Initialization complete.\n");
}

/**
 * @brief 打开开关
 */
void NCV84090_TurnOn() {
    gpio_set_value(pin_IN, 1);
}

/**
 * @brief 关闭开关
 */
void NCV84090_TurnOff() {
    gpio_set_value(pin_IN, 0);
}

/**
 * @brief 使能/禁能诊断
 */
void NCV84090_EnableDiagnostics(bool enable) {
    gpio_set_value(pin_CS_EN, enable ? 1 : 0);
}

/**
 * @brief 读取并返回以安培(A)为单位的负载电流
 */
float NCV84090_ReadCurrent() {
    // 1. 确保开关导通且诊断使能
    NCV84090_TurnOn();
    NCV84090_EnableDiagnostics(true);

    // 2. 等待稳定时间 (t_CS_High2), 例如 200微秒
    usleep(200); 

    // 3. 读取CS引脚电压
    float v_cs = read_adc_voltage();
    if (v_cs < 0) {
        return -1.0; // Read error
    }

    // --- 简化处理,实际需要查找表 ---
    // 假设R_CS = 1kΩ, 那么 I_CS = V_CS / 1000
    // 假设在工作点 K ≈ 5000 (需要查数据手册)
    float i_cs = v_cs / 1000.0;
    float k_ratio = 5000.0;
    float i_out = i_cs * k_ratio;
    
    // 操作完成后可以关闭诊断以降低功耗
    NCV84090_EnableDiagnostics(false);

    return i_out;
}

// FaultType NCV84090_CheckFault() { ... } // 故障诊断函数实现类似

// --- 主函数:测试API ---
int main() {
    NCV84090_Init();

    printf("Turning ON the load...\n");
    NCV84090_TurnOn();
    sleep(2); // 保持开启2秒

    printf("Reading current...\n");
    float current = NCV84090_ReadCurrent();
    if (current >= 0) {
        printf("Measured Load Current: %.3f A\n", current);
    } else {
        printf("Failed to read current.\n");
    }
    
    sleep(1);

    printf("Turning OFF the load...\n");
    NCV84090_TurnOff();

    return 0;
}

想参与一起讨论?欢迎到TechForum原文下留言:

【DigiKey免单狂欢】NCV84090DR2G软硬件设计-1

【DigiKey免单狂欢】NCV80490DR2G软硬件设计-2 

【DigiKey免单狂欢】NCV84090DR2G软硬件设计-3 

帖文内容源自DigiKey与21电源网 – 电子研习社的活动:

A screenshot of a computer

AI-generated content may be incorrect.

想知道更多不同活动资讯,请到热点活动页面了解更多→

A logo with black lines and red text

AI-generated content may be incorrect.

******

如有任何问题,欢迎联系得捷电子DigiKey客服团队。

中国(人民币)客服
- service.sh@digikey.com
- QQ在线实时咨询 |QQ号:4009201199

中国(美金)/ 香港客服
- china.support@digikey.com

Digikey WeChat QR Code

到微信搜寻“digikey”或“得捷电子
关注我们官方微信
并登记成会员,
每周接收工程师秘技,
赚积分、换礼品、享福利

头像
得捷电子

Copyright©DigiKey Electronics