You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

wiringpi_test9_pwm.c 4.6 KiB

4 kuukautta sitten
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. // WiringPi test program: PWM test
  2. // Compile: gcc -Wall wiringpi_test9_pwm.c -o wiringpi_test9_pwm -lwiringPi
  3. #include "wpi_test.h"
  4. #include <string.h>
  5. #include <errno.h>
  6. #include <unistd.h>
  7. #include <sys/time.h>
  8. #include <time.h>
  9. #include <stdint.h>
  10. int PWM0 = 12;
  11. int FREQIN = 6;
  12. volatile int gCounter = 0;
  13. //Interrupt Service Routine for FREQIN
  14. void ISR_FREQIN(void) {
  15. gCounter++;
  16. }
  17. double MeasureAndCheckFreq(const char* msg, double expect_freq) {
  18. double fFrequency;
  19. clock_t CPUClockBegin, CPUClockEnd;
  20. int CountBegin, CountEnd;
  21. double CPUClockInterval, CountInterval;
  22. double elapsed_time, CPULoad;
  23. uint64_t tbegin, tend;
  24. int SleepMs = 1200;
  25. CPUClockBegin = clock();
  26. tbegin = piMicros64();
  27. CountBegin = gCounter;
  28. delay(SleepMs);
  29. CountEnd = gCounter;
  30. CPUClockEnd = clock();
  31. tend = piMicros64();
  32. elapsed_time = (double)(tend-tbegin)/1.0e6;
  33. CountInterval = CountEnd - CountBegin;
  34. CPUClockInterval = CPUClockEnd - CPUClockBegin;
  35. CPULoad = CPUClockInterval*100.0 / CLOCKS_PER_SEC / elapsed_time;
  36. fFrequency = CountInterval / elapsed_time / 1000;
  37. printf("Interval: time: %.6f sec (CPU: %3.1f %%), count: %g -> frequency: %.3f kHz\n",
  38. elapsed_time, CPULoad, CountInterval, fFrequency);
  39. CheckSameDouble("Wait for freq. meas.", elapsed_time, SleepMs/1000.0, 0.1); //100ms tolerance. maybe problematic on high freq/cpu load
  40. CheckSameDouble(msg, fFrequency, expect_freq, expect_freq*2/100); //2% tolerance
  41. return fFrequency;
  42. }
  43. int tests_pwmc[7] = {1456, 1000, 512, 100, 2000, 3000, 4000};
  44. int tests_duty[7] = { 512, 768, 682, 922, 256, 341, 102};
  45. int tests_pwmr[10]= { 100, 512, 1024, 1456, 2000, 3000, 5000, 10000, 15000, 20000};
  46. int main (void) {
  47. int major, minor;
  48. char msg[255];
  49. wiringPiVersion(&major, &minor);
  50. printf("WiringPi GPIO test program 9 (using PWM@GPIO%d (output) and GPIO%d (input))\n", PWM0, FREQIN);
  51. printf(" pwm0 irq time\n");
  52. printf("\nPWM/ISR test (WiringPi %d.%d)\n", major, minor);
  53. wiringPiSetupGpio() ;
  54. int rev, mem, maker, overVolted, RaspberryPiModel;
  55. piBoardId(&RaspberryPiModel, &rev, &mem, &maker, &overVolted);
  56. CheckNotSame("Model: ", RaspberryPiModel, -1);
  57. if (!piBoard40Pin()) {
  58. PWM0 = 18;
  59. FREQIN = 17;
  60. }
  61. // INT_EDGE_BOTH, INT_EDGE_FALLING, INT_EDGE_RISING only one ISR per input
  62. int result = wiringPiISR(FREQIN, INT_EDGE_RISING, &ISR_FREQIN);
  63. CheckSame("Register ISR", result, 0);
  64. if (result < 0) {
  65. printf("Unable to setup ISR for GPIO %d (%s)\n\n",
  66. FREQIN, strerror(errno));
  67. return UnitTestState();
  68. }
  69. int Pi4 = 0;
  70. switch(RaspberryPiModel) {
  71. case PI_MODEL_4B:
  72. case PI_MODEL_400:
  73. case PI_MODEL_CM4:
  74. case PI_MODEL_CM4S:
  75. Pi4 = 1;
  76. break;
  77. case PI_MODEL_5:
  78. return UnitTestState(); //not supported so far
  79. }
  80. printf("\nPWM0 BAL mode:\n");
  81. printf("==============\n");
  82. pinMode(PWM0, PWM_OUTPUT); //pwmr=1024, pwmc=32
  83. const int pmw = 512;
  84. int pmwr = 1024;
  85. pwmWrite(PWM0, pmw); //50% Duty
  86. //MeasureAndCheckFreq("50\% Duty (default)", 300.000); //FAIL , freq (pwmc=32) to high for irq count
  87. for (int c_duty=0, c_duty_end = sizeof(tests_duty)/sizeof(tests_duty[0]); c_duty<c_duty_end; c_duty++) {
  88. double tests_duty_corr;
  89. if (tests_duty[c_duty]>(pmwr/2)) {
  90. tests_duty_corr = pmwr-tests_duty[c_duty];
  91. } else {
  92. tests_duty_corr = tests_duty[c_duty];
  93. }
  94. double duty_fact = tests_duty_corr/(double)pmwr;
  95. printf("\n%d/%d set duty %d/%d\n",c_duty+1, c_duty_end, tests_duty[c_duty], pmwr);
  96. pwmWrite(PWM0, tests_duty[c_duty]);
  97. for (int c_pwmc=0, end = sizeof(tests_pwmc)/sizeof(tests_pwmc[0]); c_pwmc<end; c_pwmc++) {
  98. if (Pi4 && tests_pwmc[c_pwmc]>1456) {
  99. printf("* Set Clock (pwmc) %d not possible on BCM2711 system (OSC 54 MHz), ignore\n", tests_pwmc[c_pwmc]);
  100. continue;
  101. }
  102. pwmSetClock(tests_pwmc[c_pwmc]);
  103. delay(250);
  104. double freq = 19200.0/tests_pwmc[c_pwmc]*duty_fact;
  105. sprintf(msg, "Set Clock (pwmc) %d, %d%% duty", tests_pwmc[c_pwmc], tests_duty[c_duty]*100/pmwr);
  106. MeasureAndCheckFreq(msg, freq);
  107. }
  108. }
  109. delay(250);
  110. pwmSetMode(PWM_MODE_MS) ;
  111. printf("\nPWM0 MS mode:\n");
  112. printf("==============\n");
  113. int pwmc = 10;
  114. pwmSetClock(pwmc);
  115. delay(2500);
  116. for (int c_pmwr=0, c_pmwr_end = sizeof(tests_pwmr)/sizeof(tests_pwmr[0]); c_pmwr<c_pmwr_end; c_pmwr++) {
  117. pwmWrite(PWM0, tests_pwmr[c_pmwr]/2);
  118. pwmSetRange(tests_pwmr[c_pmwr]) ;
  119. delay(250);
  120. double freq = 19200.0/(double)pwmc/(double)tests_pwmr[c_pmwr];
  121. sprintf(msg, "Set range (pwmr) %d", tests_pwmr[c_pmwr]);
  122. MeasureAndCheckFreq(msg, freq);
  123. }
  124. return UnitTestState();
  125. }