/* gpioClockSet * * Parameters: * - pin: int * - freq: int * Return Type: void */ mrb_value mrb_Pi_gpioClockSet(mrb_state* mrb, mrb_value self) { mrb_int native_pin; mrb_int native_freq; /* Fetch the args */ mrb_get_args(mrb, "ii", &native_pin, &native_freq); /* Invocation */ gpioClockSet(native_pin, native_freq); return mrb_nil_value(); }
void doClock (int argc, char *argv []) { int pin, freq ; if (argc != 4) { fprintf (stderr, "Usage: %s clock <pin> <freq>\n", argv [0]) ; exit (1) ; } pin = atoi (argv [2]) ; freq = atoi (argv [3]) ; gpioClockSet (pin, freq) ; }
void doClock (int argc, char *argv []) { int pin, freq ; if (argc != 4) { fprintf (stderr, "Usage: %s clock <pin> <freq>\n", argv [0]) ; exit (1) ; } pin = atoi (argv [2]) ; if ((wpMode == WPI_MODE_PINS) && ((pin < 0) || (pin >= NUM_PINS))) return ; freq = atoi (argv [3]) ; gpioClockSet (pin, freq) ; }
int main (void) { wiringPiSetup () ; pinMode (VPRG, OUTPUT) ; pinMode (SIN, OUTPUT) ; pinMode (SCLK, OUTPUT) ; pinMode (XLAT, OUTPUT) ; pinMode (BLANK, OUTPUT) ; pinMode (DCPRG, OUTPUT) ; // 注意,这里我们设置输出模式为时钟模式 // 在这个模式下,GPIO4引脚可以稳定高速的输出时钟信号(方波),并且不会额外占用CPU资源 // 可以使用这个模式的引脚只有GPIO4,这个引脚是树莓派硬件支持时钟信号输出的 pinMode (GSCLK, GPIO_CLOCK) ; // 设置时钟频率,最高19.2MHz,或者是19.2Mhz的n分频,这里我们设置GSCLK为2.4MHz(19.2Mhz/8) // 设置BLANK为585Hz (2.4Mhz/4096) gpioClockSet (GSCLK, 9600000) ; // VPRG设置为L,使其工作在GS mode digitalWrite (VPRG, LOW) ; // BLANK设置为H,关闭所有输出 digitalWrite (BLANK, HIGH) ; digitalWrite (DCPRG, HIGH) ; // 传送12bit X 16组PWM数值GSn(n=0-15),共192bit // 每组数据的值范围是0-4095 // 因为是通过移位寄存器传输,所以传送顺序是倒序的:GS15,GS14。。。GS0 // GSn决定了OUTn的PWM调宽。(GSn / 4095 = 0% - 100%) for (i = 0; i < 192-36; ++i) { digitalWrite (SIN, LOW) ; // 创造SCLK的上升沿,写SIN数据到移位寄存器中 digitalWrite (SCLK, LOW) ; digitalWrite (SCLK, HIGH) ; } // OUT2 n=11; for (i = 0; i < 12-n; ++i) { digitalWrite (SIN, LOW) ; // 创造SCLK的上升沿,写SIN数据到移位寄存器中 digitalWrite (SCLK, LOW) ; digitalWrite (SCLK, HIGH) ; } for (i = 0; i < 12; ++i) { digitalWrite (SIN, HIGH) ; // 创造SCLK的上升沿,写SIN数据到移位寄存器中 digitalWrite (SCLK, LOW) ; digitalWrite (SCLK, HIGH) ; } // OUT1 n=9; for (i = 0; i < 12-n; ++i) { digitalWrite (SIN, LOW) ; // 创造SCLK的上升沿,写SIN数据到移位寄存器中 digitalWrite (SCLK, LOW) ; digitalWrite (SCLK, HIGH) ; } for (i = 0; i < n; ++i) { digitalWrite (SIN, HIGH) ; // 创造SCLK的上升沿,写SIN数据到移位寄存器中 digitalWrite (SCLK, LOW) ; digitalWrite (SCLK, HIGH) ; } // OUT0 n=5; for (i = 0; i < 12-n; ++i) { digitalWrite (SIN, LOW) ; // 创造SCLK的上升沿,写SIN数据到移位寄存器中 digitalWrite (SCLK, LOW) ; digitalWrite (SCLK, HIGH) ; } for (i = 0; i < n; ++i) { digitalWrite (SIN, HIGH) ; // 创造SCLK的上升沿,写SIN数据到移位寄存器中 digitalWrite (SCLK, LOW) ; digitalWrite (SCLK, HIGH) ; } // 送完GS数据后,创造XLAT的上升沿,将移位寄存器的数据一次性送入GS寄存器 digitalWrite (XLAT, LOW) ; digitalWrite (XLAT, HIGH) ; // BLANK设置为L,打开所有输出 digitalWrite (BLANK, LOW) ; // 准备工作完毕,下面向GSCLK输送时钟信号(高低电平交互的方波信号) // TLC5940会根据这个时钟信号进行从0-4095的计数,一边计数一边检查各GSn的设定值,一旦到达GSn的值,则切换OUTn的电平 // 一直计数到4095为止,再从0开始重新计数。从0计数到4095就是一个高低电平的切换周期。 // 所以我们给5940提供的时钟频率越快,最后输出的PWM频率就越快 // 最后输出的PWM的频率 = 时钟信号的频率 / 4095 // 比如时钟频率是8M,则最后从各OUT口输出的PWM频率是8MHz / 4095 = 1.953KHz // 根据TLC5940的官方文档,GSCLK可支持最高30MHz的时钟频率,也就是最高可以输出7.3KHz的PWM信号。 // 如果是控制LED的亮度,那么让人眼感觉不到闪烁的最低频率应该是50Hz以上, // 所以我们应该至少给GSCLK提供不低于50 X 4095 = 200KHz的方波。 // 树莓派Python的GPIO库翻转IO口的速度不高,实测速度只能达到60KHz, // 导致最后输出的PWM频率只有14Hz,会有明显的闪烁感 // 后来查了相关资料,发现树莓派GPIO4是硬件支持时钟信号输出的,速度可达到19.2Mhz,于是本文采用此方法 resetBLACK(); return 0 ; }