使用C的Beaglebone黑色PWM

我在C中为beaglebone black写了一个示例pwm函数。 每当我在其他模块或main()中进行函数调用时,我最终都会出现分段错误。 请帮助我犯错误以及如何处理这个问题。 以下是代码。

int trigger_pwm_output(unsigned input_no ) { FILE *pwm,*duty,*period,*run;`` uint16_t input=0; uint8_t input_no=0,input_state=0; unsigned int duty_cycle =500000; pwm = fopen("/sys/devices/bone_capemgr.9/slots", "w"); fseek(pwm,0,SEEK_SET); fprintf(pwm,"am33xx_pwm"); fflush(pwm); switch(input_no) { case 0: fprintf(pwm,"bone_pwm_P8_13"); fflush(pwm); period = fopen("/sys/devices/ocp.3/pwm_test_P8_13.15/period", "w"); fseek(period,0,SEEK_SET); fprintf(period,"%d",500000); fflush(period); duty = fopen("/sys/devices/ocp.3/pwm_test_P8_13.15/duty", "w"); fseek(duty,0,SEEK_SET); run = fopen("/sys/devices/ocp.3/pwm_test_P8_13.15/run", "w"); fseek(run,0,SEEK_SET); fprintf(run,"%d",0); fflush(run); fseek(run,0,SEEK_SET); count++; do { duty_cycle += 10; fprintf(duty,"%d",duty_cycle); }while(count > 0) || (count < 10)); fflush(duty); fprintf(run,"%d",1); fflush(run); fclose(pwm); fclose(duty); fclose(period); fclose(run); break; case 1: fprintf(pwm,"bone_pwm_P8_19"); fflush(pwm); period = fopen("/sys/devices/ocp.3/pwm_test_P8_19.16/period", "w"); fseek(period,0,SEEK_SET); fprintf(period,"%d",500000); fflush(period); duty = fopen("/sys/devices/ocp.3/pwm_test_P8_19.16/duty", "w"); fseek(duty,0,SEEK_SET); run = fopen("/sys/devices/ocp.3/pwm_test_P8_19.16/run", "w"); fseek(run,0,SEEK_SET); fprintf(run,"%d",0); fflush(run); fseek(run,0,SEEK_SET); --count; do { duty_cycle += 10; fprintf(duty,"%d",duty_cycle); }while(count <10); fflush(duty); fprintf(run,"%d",1); fflush(run); fclose(pwm); fclose(duty); fclose(period); fclose(run); break; } return 0; } 

`

我刚刚使用C在BeagleBone Black上成功启用了4个PWM输出,所以我希望能给你一些合法的建议。

使用/sys/devices/ocp.3/目录下的文件(称为设备树覆盖)用于PWM不是一个好主意,原因有两个:

  • PWM引脚目录名的最后两位是任意的,例如pwm_test_P8_13.xx ,这是分段故障的潜在原因,因为您不检查fopen状态。 但是,fopen不允许在指定路径中使用通配符。 我的解决方法,根本不干净,是用popen调用echo /sys/devices/ocp.3/pwm_test_P8_13.*/来检索PWM引脚目录的正确完整路径。
  • BeagleBone Black上只有两个PWM模块,DTO可以防止每个模块使用多个PWM引脚。 因此,如果您尝试从命令行修改引脚的周期,则可能会返回写入错误。 如果您然后键入dmesg | tail dmesg | tail ,您可能会看到以下消息:

    [1406.652632] ehrpwm 48304200.ehrpwm:期间值与通道1冲突
    [1406.660047] pwm_test pwm_test_P8_19.11:pwm_config()失败

因此,我使用/sys/class/pwm/下的文件。 您仍然需要将am33xx_pwm和您计划使用的PWM引脚写入文件/sys/devices/bone_capemgr.9/slots 。 然后,你转到目录/sys/class/pwm/ ,将数字(0-7)写入文件export ,然后在生成的目录pwm?下修改文件pwm? 在哪里? 是写入export的数字。 下表显示了每个数字及其对应的引脚:

在此处输入图像描述

这是我提到的教程。

希望这可以帮助!

此代码存在几个问题 – 其中一些问题已在评论中进行了描述。

  • 存在变量名称冲突。 input_no既传递给函数,也传递给函数中定义的函数。
  • 两个do-while循环都可能是无限的。 两个循环都具有依赖于count的结束条件,该结束条件在任一循环的主体中都未被修改。 此外,无论count的值如何,第一个循环中的条件始终为true。
  • 永远不会检查所有fopen调用的返回值。 如果这些调用中的任何一个失败,则使用空文件指针调用后续文件操作。
  • count未在此代码中的任何位置定义或初始化。 它是全球定义的吗?
  • 你对fopen一个调用是在switch语句的主体之外进行的 – 最好将其相应的close调用移到外面。