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

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

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

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

1. 环境准备

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

2. C语言代码实现

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

文件: ncv84090_driver.c


# 运行编译好的程序

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

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

#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;
}