嵌入式硬件篇---龙芯PWM生成

发布于:2025-03-18 ⋅ 阅读:(17) ⋅ 点赞:(0)


前言

本文简单介绍了龙芯2k1000中的PWM生成。


1. 头文件引入

#include <stdio.h>    // 标准输入输出(如printf)
#include <stdlib.h>   // 系统调用(如open/close)
#include <time.h>     // 时间相关函数(未直接使用)
#include <fcntl.h>    // 文件控制选项(如O_WRONLY)
#include <unistd.h>   // POSIX API(如write/close)
#include <sys/mman.h> // 内存映射(未直接使用)

作用

作用:提供文件操作和系统调用的基础支持。

2. 导出PWM通道 pwm_export

int pwm_export(unsigned int pwm) {
    int fd;
    // 根据pwm编号选择对应的sysfs路径
    if (pwm == 0) {
        fd = open("/sys/class/pwm/pwmchip0/export", O_WRONLY);
    } else if (pwm == 1) {
        fd = open("/sys/class/pwm/pwmchip1/export", O_WRONLY);
    } // ... 其他pwm编号类似
    if (fd < 0) {
        printf("Failed export PWM%d\n", pwm);
        return -1;
    }
    write(fd, "0", 2); // 导出通道0(假设每个pwmchip只有一个通道)
    close(fd);
    return 0;
}

功能

功能:通过写入export文件激活PWM通道。

关键点

假设每个pwmchip仅支持一个通道(pwm0)。
写入"0"表示导出该芯片的通道0

问题

write(fd, “0”, 2) 中的长度参数应为1(仅写入字符’0’),多出的\0可能导致内核解析错误。

缺少对pwm参数的合法性检查(如传入pwm=4会导致未定义行为)。

3. 取消导出PWM通道 pwm_unexport

int pwm_unexport(unsigned int pwm) {
    // 类似pwm_export,操作unexport文件
    write(fd, "0", 2); // 取消导出通道0
}

作用

作用:清理已导出的PWM通道。

注意

注意:需与pwm_export配对使用。

4. 启用/禁用PWM pwm_enable/pwm_disable

int pwm_enable(unsigned int pwm) {
    // 打开对应通道的enable文件
    write(fd, "1", 2); // 启用PWM输出
}

功能

功能:通过写入1或0控制PWM输出开关。

改进建议

使用write(fd, “1”, 1)避免多余的空字符。
检查write返回值确保操作成功。

5. 配置周期和占空比 pwm_config

int pwm_config(unsigned int pwm, unsigned int period, unsigned int duty_cycle) {
    // 写入周期(单位:纳秒)
    write(fd, buf_p, len_p);
    // 写入占空比(单位:纳秒)
    write(fd, buf_d, len_d);
}

作用

作用:设置PWM波形参数。

关键点

period为完整周期时间,duty_cycle为高电平时间。
需确保duty_cycle <= period,否则配置失败。

示例

示例:若period=20000000(20ms),duty_cycle=1500000(1.5ms),则占空比为7.5%。

6. 设置极性 pwm_polarity

int pwm_polarity(int pwm, int polarity) {
    if (polarity == 1) {
        write(fd, "normal", 6);   // 正常极性(高电平有效)
    } else if (polarity == 0) {
        write(fd, "inversed", 8); // 反向极性(低电平有效)
    }
}

功能

功能:控制PWM信号的极性。

潜在问题

字符串"inversed"可能是拼写错误,某些驱动要求"inverted"。
需确认龙芯2K1000的PWM驱动支持的极性模式。

7.龙芯2K1000适配说明

7.1 硬件特性

PWM控制器数量

PWM控制器数量:假设支持4个独立PWM控制器(pwmchip0~pwmchip3)。

通道支持

通道支持:每个控制器可能仅支持单通道(pwm0),需参考《龙芯2K1000硬件手册》。

7.2关键问题与优化建议

问题1:写入长度错误

write(fd, “0”, 2); // 错误:多写入一个空字符
修复
修复:改为write(fd, “0”, 1),仅写入字符’0’。

问题2:路径生成冗余

优化:提取公共路径生成逻辑:
const char* get_pwm_path(int pwm, const char* file) {
    static char path[128];
    snprintf(path, sizeof(path), "/sys/class/pwm/pwmchip%d/pwm0/%s", pwm, file);
    return path;
}

问题3:错误处理不足

增强:检查所有系统调用的返回值:
if (write(fd, buf, len) != len) {
    perror("Write failed");
    return -1;
}

问题4:参数合法性校验

if (pwm < 0 || pwm > 3) {
    printf("Invalid PWM chip number: %d\n", pwm);
    return -1;
}

7.3完整优化示例

// 辅助函数:生成PWM路径
const char* get_pwm_path(int pwm, const char* file) {
    static char path[128];
    snprintf(path, sizeof(path), "/sys/class/pwm/pwmchip%d/pwm0/%s", pwm, file);
    return path;
}

// 导出PWM通道(优化后)
int pwm_export(unsigned int pwm) {
    if (pwm > 3) { // 校验参数合法性
        printf("Invalid PWM chip: %d\n", pwm);
        return -1;
    }
    char export_path[64];
    snprintf(export_path, sizeof(export_path), "/sys/class/pwm/pwmchip%d/export", pwm);
    int fd = open(export_path, O_WRONLY);
    if (fd < 0) {
        perror("Failed to open export file");
        return -1;
    }
    if (write(fd, "0", 1) != 1) { // 修正写入长度
        perror("Failed to export PWM");
        close(fd);
        return -1;
    }
    close(fd);
    return 0;
}

7.4应用场景示例

int main() {
    pwm_export(0);          // 导出PWM0
    pwm_config(0, 20000000, 1500000); // 20ms周期,1.5ms高电平
    pwm_polarity(0, 1);     // 正常极性
    pwm_enable(0);          // 启动PWM输出
    sleep(5);
    pwm_disable(0);         // 停止输出
    pwm_unexport(0);        // 清理
    return 0;
}

8.总结

功能

功能:完整控制PWM的初始化、参数配置和输出管理

优势

优势:基于sysfs接口,代码简洁,兼容性强

改进方向

  1. 修复写入长度和拼写错误。
  2. 提取公共逻辑减少冗余。
  3. 增强错误处理和参数校验。
  4. 支持多通道(若硬件允许)。