// WiringPi test program: PWM test // Compile: gcc -Wall wiringpi_test9_pwm.c -o wiringpi_test9_pwm -lwiringPi #include "wpi_test.h" #include #include #include #include #include #include int PWM_OUT[4] = { 18, 12, 13, 19 }; int PWM_IN[4] = { 17, 13, 12, 26 }; volatile int gCounter = 0; //Interrupt Service Routine for FREQIN void ISR_FREQIN(void) { gCounter++; } double MeasureAndCheckFreq(const char* msg, double expect_freq) { double fFrequency; clock_t CPUClockBegin, CPUClockEnd; int CountBegin, CountEnd; double CPUClockInterval, CountInterval; double elapsed_time, CPULoad; uint64_t tbegin, tend; int SleepMs = 1200; CPUClockBegin = clock(); tbegin = piMicros64(); CountBegin = gCounter; delay(SleepMs); CountEnd = gCounter; CPUClockEnd = clock(); tend = piMicros64(); elapsed_time = (double)(tend-tbegin)/1.0e6; CountInterval = CountEnd - CountBegin; CPUClockInterval = CPUClockEnd - CPUClockBegin; CPULoad = CPUClockInterval*100.0 / CLOCKS_PER_SEC / elapsed_time; fFrequency = CountInterval / elapsed_time / 1000; printf("\nInterval: time: %.6f sec (CPU: %3.1f %%), count: %g -> frequency: %.3f kHz\n", elapsed_time, CPULoad, CountInterval, fFrequency); CheckSameDouble("Wait for freq. meas.", elapsed_time, SleepMs/1000.0, 0.1); //100ms tolerance. maybe problematic on high freq/cpu load CheckSameDouble(msg, fFrequency, expect_freq, expect_freq*2/100); //2% toleranc return fFrequency; } int tests_pwmc[7] = {1456, 1000, 512, 100, 2000, 3000, 4000}; int tests_duty[7] = { 512, 768, 682, 922, 256, 341, 102}; int tests_pwmr[12]= { 50, 100, 200, 512, 1024, 1456, 2000, 3000, 5000, 10000, 15000, 20000}; int tests_pwm[3] = { 50, 25, 75}; int main (void) { int major, minor; char msg[255]; int testruns = 4; int PWM, FREQIN; wiringPiVersion(&major, &minor); printf("WiringPi GPIO test program 9\n"); printf("PWM/ISR test (WiringPi %d.%d)\n", major, minor); wiringPiSetupGpio() ; int rev, mem, maker, overVolted, RaspberryPiModel; piBoardId(&RaspberryPiModel, &rev, &mem, &maker, &overVolted); CheckNotSame("Model: ", RaspberryPiModel, -1); int Pi4 = 0; int Pi5 = 0; double MaxFreq = 100.0; switch(RaspberryPiModel) { case PI_MODEL_A: case PI_MODEL_B: case PI_MODEL_BP: case PI_MODEL_AP: case PI_MODEL_ZERO: case PI_MODEL_ZERO_W: case PI_MODEL_CM: MaxFreq = 13.0; // 12.5 kHz -> ~40% CPU@800 MHz printf(" - Pi1/BCM2835 detected, will skip tests with frequency above %g kHz\n", MaxFreq); break; case PI_MODEL_2: MaxFreq = 20.0; printf(" - Pi2/BCM2836 detected, will skip tests with frequency above %g kHz\n", MaxFreq); break; case PI_MODEL_3B: case PI_MODEL_CM3: case PI_MODEL_3BP: case PI_MODEL_3AP: case PI_MODEL_CM3P: case PI_MODEL_ZERO_2W: MaxFreq = 50.0; printf(" - Pi3/BCM2837 detected, will skip tests with frequency above %g kHz\n", MaxFreq); break; case PI_MODEL_4B: case PI_MODEL_400: case PI_MODEL_CM4: case PI_MODEL_CM4S: Pi4 = 1; break; case PI_MODEL_5: Pi5 = 1; break; } if (!piBoard40Pin()) { testruns = 1; // only fist PWM0, supported } for (int testrun=0; testrun(pmwr/2)) { tests_duty_corr = pmwr-tests_duty[c_duty]; } else { tests_duty_corr = tests_duty[c_duty]; } double duty_fact = tests_duty_corr/(double)pmwr; printf("\n%d/%d set duty %d/%d\n",c_duty+1, c_duty_end, tests_duty[c_duty], pmwr); pwmWrite(PWM, tests_duty[c_duty]); for (int c_pwmc=0, end = sizeof(tests_pwmc)/sizeof(tests_pwmc[0]); c_pwmc1456) { printf("* Set clock (pwmc) %d not possible on BCM2711 system (OSC 54 MHz), ignore\n", pwmc); continue; } double freq = 19200.0/pwmc*duty_fact; if (freq>MaxFreq) { printf("* Set clock (pwmc) %d not possible on system (to slow to measure %g kHz with ISR), ignore\n", pwmc, freq); continue; } pwmSetClock(pwmc); delay(250); sprintf(msg, "Set Clock (pwmc) %d, %d%% duty", pwmc, tests_duty[c_duty]*100/pmwr); MeasureAndCheckFreq(msg, freq); } } } delay(250); printf("\n"); printf("*********************************\n"); printf("* PWM MS mode *\n"); printf("*********************************\n"); int pwmc = 10; printf("SetClock pwmc=%d and enable MS mode\n", pwmc); pwmSetClock(pwmc); pwmSetMode(PWM_MODE_MS); printf("Wait for start ...\n"); delay(250); printf("Start:\n"); for (int c_pmwr=0, c_pmwr_end = sizeof(tests_pwmr)/sizeof(tests_pwmr[0]); c_pmwrMaxFreq) { printf("* Set Clock (pwmc, pwmr) %d, %d not possible on system (to slow to measure %g kHz with ISR), ignore\n", pwmc, pwmr, freq); continue; } sprintf(msg, "Set range (pwmr) %d", pwmr); pwmSetRange(pwmr); for (int c_pmw=0, c_pmw_end = sizeof(tests_pwm)/sizeof(tests_pwm[0]); c_pmw