Linux-PWM
在应用层进行Linux-PWM的开发,关于驱动开发可以查看嵌入式Linux-PWM 子系统
调用应用层接口
验证PWM设备存在
root@ATK-IMX6U:/sys/class/pwm# ls pwmchip0 pwmchip1 pwmchip2 pwmchip3 pwmchip4 pwmchip5 pwmchip6 pwmchip7pwmchip0-7对应着PWM1-8这8个PWM输出口
导出pwmchip2(PWM3)的0号通道的的操作目录,则会看到pwm0这个操作接口
在I.MX6ULL中,每个pwm控制器下只有一路pwm输出口。均只有通道0是有效的
root@ATK-IMX6U:/sys/class/pwm# echo 0 > /sys/class/pwm/pwmchip2/export # 在 pwmchip2 这个PWM控制器上导出第0号PWM通道 root@ATK-IMX6U:/sys/class/pwm# ls /sys/class/pwm/pwmchip2/ device export npwm power pwm0 subsystem uevent unexport root@ATK-IMX6U:/sys/class/pwm#基于
pwmchip2/pwm0操作接口实现设置root@ATK-IMX6U:/sys/class/pwm/pwmchip2/pwm0# ls duty_cycle enable period polarity power uevent
使能
echo 1 > /sys/class/pwm/pwmchip2/pwm0/enable设置频率: 设置周期时间(ns)来设置频率
echo 20000 > /sys/class/pwm/pwmchip2/pwm0/period设置占空比: 设置高电平时间来设置占空比
echo 500 > /sys/class/pwm/pwmchip2/pwm0/duty_cycle在外设上使用指定的PWM
对于需要使用pwm的外设例如lcd屏幕,可以使用内置的pwn驱动来进行设置。需要修改设备树
以已有的背光节点作为参考
compatible属性必须为“pwm-backlight用于匹配内核驱动。pwms用于指定具体使用的哪一路pwm。brightness-levels用于设置背光等级,范围0-255,首个值必须为0。power-supply属性可以不设置,其用于设置支持的电压。backlight { compatible = "pwm-backlight"; pwms = <&pwm1 0 5000000>; #imx6每个pwn只有1个通道 因此通道为0 设置200Hz brightness-levels = <0 4 8 16 32 64 128 255>; default-brightness-level = <7>; status = "okay"; };
在Qt中调用Linux的PWM接口
-
程序
以下程序中使用硬编码的pwm通道,可以考虑进行修改。
static bool SetupPWMDevice(int frequencyHz, float dutyCycle) { // 检查sys/class/pwm/pwmchip2目录是否存在 const char* pwmChipPath = "/sys/class/pwm/pwmchip2"; if (!QFile::exists(pwmChipPath)) { qWarning() << "PWM芯片路径不存在:" << pwmChipPath; return false; } // 导出PWM通道0 QFile exportFile(QString("%1/export").arg(pwmChipPath)); if (!exportFile.open(QIODevice::WriteOnly)) { qWarning() << "无法打开PWM导出文件:" << exportFile.errorString(); return false; } QTextStream exportStream(&exportFile); exportStream << "0"; // 写入0 ,也就是导出通道0 exportFile.close(); // 设置PWM频率 QFile periodFile(QString("%1/pwm0/period").arg(pwmChipPath)); if (!periodFile.open(QIODevice::WriteOnly)) { qWarning() << "无法打开PWM周期文件:" << periodFile.errorString(); return false; } qint64 periodNs = static_cast<qint64>(1e9 / frequencyHz); // 周期,单位纳秒 QTextStream periodStream(&periodFile); periodStream << periodNs; periodFile.close(); // 设置PWM占空比 QFile dutyFile(QString("%1/pwm0/duty_cycle").arg(pwmChipPath)); if (!dutyFile.open(QIODevice::WriteOnly)) { qWarning() << "无法打开PWM占空比文件:" << dutyFile.errorString(); return false; } qint64 dutyNs = static_cast<qint64>(periodNs * dutyCycle); QTextStream dutyStream(&dutyFile); dutyStream << dutyNs; dutyFile.close(); // 使能 QFile enableFile(QString("%1/pwm0/enable").arg(pwmChipPath)); if (!enableFile.open(QIODevice::WriteOnly)) { qWarning() << "无法打开PWM使能文件:" << enableFile.errorString(); return false; } QTextStream enableStream(&enableFile); enableStream << "1"; // 写入1 ,也就是使能 enableFile.close(); return true; } static bool DeinitPWMDevice() { // 检查sys/class/pwm/pwmchip2目录是否存在 const char* pwmChipPath = "/sys/class/pwm/pwmchip2"; if (!QFile::exists(pwmChipPath)) { qWarning() << "PWM芯片路径不存在:" << pwmChipPath; return false; } // 关闭使能 QFile enableFile(QString("%1/pwm0/enable").arg(pwmChipPath)); if (!enableFile.open(QIODevice::WriteOnly)) { qWarning() << "无法打开PWM使能文件:" << enableFile.errorString(); return false; } QTextStream enableStream(&enableFile); enableStream << "0"; // 写入0 ,也就是关闭使能 enableFile.close(); // 取消导出PWM通道0 QFile unexportFile(QString("%1/unexport").arg(pwmChipPath)); if (!unexportFile.open(QIODevice::WriteOnly)) { qWarning() << "无法打开PWM取消导出文件:" << unexportFile.errorString(); return false; } QTextStream unexportStream(&unexportFile); unexportStream << "0"; // 写入0 ,也就是取消导出通道0 unexportFile.close(); return true; } static bool SetPWMDutyCycle(float dutyCycle) { // 检查sys/class/pwm/pwmchip2目录是否存在 const char* pwmChipPath = "/sys/class/pwm/pwmchip2"; if (!QFile::exists(pwmChipPath)) { qWarning() << "PWM芯片路径不存在:" << pwmChipPath; return false; } // 读取当前周期 QFile periodFile(QString("%1/pwm0/period").arg(pwmChipPath)); if (!periodFile.open(QIODevice::ReadOnly)) { qWarning() << "无法打开PWM周期文件:" << periodFile.errorString(); return false; } QTextStream periodStream(&periodFile); qint64 periodNs; periodStream >> periodNs; periodFile.close(); // 设置新的占空比 QFile dutyFile(QString("%1/pwm0/duty_cycle").arg(pwmChipPath)); if (!dutyFile.open(QIODevice::WriteOnly)) { qWarning() << "无法打开PWM占空比文件:" << dutyFile.errorString(); return false; } qint64 dutyNs = static_cast<qint64>(periodNs * dutyCycle); QTextStream dutyStream(&dutyFile); dutyStream << dutyNs; dutyFile.close(); // 重新使能PWM以应用新设置 QFile enableFile(QString("%1/pwm0/enable").arg(pwmChipPath)); if (!enableFile.open(QIODevice::WriteOnly)) { qWarning() << "无法打开PWM使能文件:" << enableFile.errorString(); return false; } QTextStream enableStream(&enableFile); enableStream << "1"; enableFile.close(); return true; }
验证
基于上述配置,设置生成周期为20KHz,占空比为20%的PWM波。
而后,使用Slogic Commbo8 的逻辑分析仪功能实现验证。
逻辑分析仪显示按照设置的值进行了输出。20KHz,20%占空比
结合Qt UI进行验证
UI设计
槽函数绑定
// 连接PWM滑动条信号到槽函数 connect(this,&sensorgui::sendPWMValueToControl,sensorOp,&SensorOperation::onSetPWMDutyCycle);事件响应
void sensorgui::on_pwm3ValueSlidrBar_valueChanged(int value) { //获取最大值和最小值 int minValue = ui->pwm3ValueSlidrBar->minimum(); int maxValue = ui->pwm3ValueSlidrBar->maximum(); //计算占空比 float dutyCycle = static_cast<float>(value - minValue) / (maxValue - minValue); //发送信号 emit sendPWMValueToControl(dutyCycle); } static bool SetPWMDutyCycle(float dutyCycle) { //检查sys/class/pwm/pwmchip2目录是否存在 const char *pwmChipPath = "/sys/class/pwm/pwmchip2"; if (!QFile::exists(pwmChipPath)) { qWarning() << "PWM芯片路径不存在:" << pwmChipPath; return false; } //读取当前周期 QFile periodFile(QString("%1/pwm0/period").arg(pwmChipPath)); if (!periodFile.open(QIODevice::ReadOnly)) { qWarning() << "无法打开PWM周期文件:" << periodFile.errorString(); return false; } QTextStream periodStream(&periodFile); qint64 periodNs; periodStream >> periodNs; periodFile.close(); //设置新的占空比 QFile dutyFile(QString("%1/pwm0/duty_cycle").arg(pwmChipPath)); if (!dutyFile.open(QIODevice::WriteOnly)) { qWarning() << "无法打开PWM占空比文件:" << dutyFile.errorString(); return false; } qint64 dutyNs = static_cast<qint64>(periodNs * dutyCycle); QTextStream dutyStream(&dutyFile); dutyStream << dutyNs; dutyFile.close(); return true; }效果验证



589

被折叠的 条评论
为什么被折叠?



