树莓派WiringPI多线程生成softPWM异常求助:无法稳定输出指定PWM
问题分析与解决方案
核心错误
你代码里的softPwmCreate调用存在致命的复制粘贴错误:除第一个引脚外,后续的softPwmCreate都错误传入了PWM_pin1,导致只有引脚22被正确初始化softPWM,其他引脚根本没创建对应的softPWM实例——这是大部分引脚不工作的直接原因。
另外,主线程完成线程join后立即退出,而WiringPi的softPWM依赖后台线程维持信号,程序退出后所有softPWM信号会立即终止,这也会导致PWM无法持续输出。同时你提到需要5路PWM,但当前代码只定义了4个引脚的参数,需补充第5路配置。
修正后的代码
#include <wiringPi.h> #include <stdio.h> #include <softPwm.h> #include <stdlib.h> #include <pthread.h> #define THREAD_NUM 5 // 对应5路PWM,每个线程负责一路 // 单个引脚的线程参数结构 struct thArg{ int pwmPin; int dutyCycle; }; // 5路PWM配置:引脚、占空比(可自行修改) struct thArg pwmConfigs[] = { {22, 20}, {23, 40}, {24, 80}, {25, 60}, {26, 50} // 补充第5路引脚与占空比 }; void* pwmRoutine(void* args){ struct thArg* config = (struct thArg*)args; // 初始化引脚并创建softPWM实例 pinMode(config->pwmPin, OUTPUT); if(softPwmCreate(config->pwmPin, 0, 100) != 0){ printf("Failed to create softPWM for pin %d\n", config->pwmPin); pthread_exit(NULL); } // 设置目标占空比 softPwmWrite(config->pwmPin, config->dutyCycle); // 线程保持存活,避免softPWM后台线程被终止 while(1){ delay(1000); } free(args); pthread_exit(NULL); } int main(int argc, char** argv) { if(wiringPiSetup() == -1){ printf("WiringPi setup failed!\n"); exit(EXIT_FAILURE); } pthread_t threads[THREAD_NUM]; for(int i=0; i<THREAD_NUM; i++){ // 复制参数到堆内存,避免线程访问栈变量 struct thArg* arg = malloc(sizeof(struct thArg)); *arg = pwmConfigs[i]; if(pthread_create(&threads[i], NULL, pwmRoutine, arg) != 0){ perror("Failed to create thread"); free(arg); exit(EXIT_FAILURE); } } // 主线程保持运行,防止程序退出导致softPWM终止 while(1){ delay(3000); } // 实际不会执行到此处,如需优雅退出可添加信号处理逻辑 for(int i = 0; i<THREAD_NUM; i++){ pthread_join(threads[i], NULL); } return EXIT_SUCCESS; }
关键修改点
- 修复
softPwmCreate的引脚参数错误,确保每个引脚对应独立的softPWM实例 - 改为每个PWM引脚对应一个线程,实现真正的多线程处理
- 补充第5路PWM配置,适配你的需求
- 线程内添加循环保持存活,主线程也添加循环避免程序退出,确保softPWM信号持续输出
- 增加WiringPi初始化失败、softPWM创建失败的错误提示
其他注意事项
- WiringPi的softPWM是软件模拟实现,过多路数会导致CPU占用过高,建议不超过8路
- 确保树莓派系统无其他进程占用目标GPIO引脚
- 编译时需链接pthread和wiringPi库,命令示例:
gcc pwm_threads.c -o pwm_threads -lwiringPi -lpthread
内容的提问来源于stack exchange,提问作者othmane Cherai
相关产品推荐
相关产品推荐

