下面看看相关函数的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;
}