树莓派GPIO入门10-使用TLC5940芯片输出多路PWM

嵌入式技术

1335人已加入

描述


在之前的章节,我们曾经用树莓派的IO口输出不同调宽的PWM信号来控制LED灯的亮度。
本文使用芯片TLC5940来输出多路PWM信号以同时控制多达16个LED的亮度。
在本文的基础上你可以发挥想象,制作出各种有趣的彩灯效果。

最终效果TODO

视频演示

硬件

  • TLC5940芯片 X 1
    TLC5940芯片
  • LED X 3
  • 2-3k电阻一只

原理说明

简单的说,TLC5940是一个拥有16路输出的LED驱动芯片,每一路输出支持4096级!亮度调节。
老规矩,看一下它的引脚图:
TLC5940的引脚图
跟本文无关的内容或设置在此不做说明,请自己查询datasheet:

引脚功能OUT0-1516路PWM信号输出(负极)VPRG指定工作模式,接GND是我们需要的PWM模式SIN串行移位输入SCLK串行移位寄存器时钟(上升沿有效)XLAT从移位寄存器写入GS寄存器(下文介绍)时钟(上升沿有效)BLANK当设为高电平时,关闭所有输出,GS计数器(下文介绍)也将重置IREF跟GND之间连接一个电阻,阻值决定了输出电流的最大值GSCLKGS时钟输入(下文介绍)SOUT串行输出,级联多块芯片时使用
  • 先将BLANK设置为H,关闭所有输出。
  • 输入各组亮度信息。跟我们之前学过的芯片一样,这款芯片同样是通过移位寄存器来输入数据的。
    移位寄存器用于传送12bit X 16组PWM数值GSn(n=0-15),共192bit。每组数据的值范围是0-4095。
    传送顺序是倒序的:GS15,GS14。。。GS0。先传输的是OUT15的12位数据,其次是OUT14的12位数据。。。最后是OUT0的12位数据。
    GSn决定了OUTn的PWM调宽。(GSn / 4095 = 0% - 100%)
  • 192位数据全部传送完毕后制造XLAT的上升沿,将移位寄存器里的数据写入GS寄存器。
  • BLANK设置为L,打开所有输出
  • 准备工作完毕,为了让TLC5940芯片正常工作,还需要向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,会有明显的闪烁感。但我们主要是为了说明原理,明白原理了可以用别的方法来实现功能,比如使用c语言的wiringPi库的话效率会高不少,甚至可以使用外部的单片机或其他电路来产生高频率的时钟信号提供给TLC5940,这个作者也在探索中。以后有空再更新。
  • 硬件连接

    模块1引脚模块2引脚TLC5940VPRG树莓派GPIO17TLC5940SIN树莓派GPIO13TLC5940SCLK树莓派GPIO19TLC5940XLAT树莓派GPIO27TLC5940BLANK树莓派GPIO23TLC5940IREF树莓派GND(中间串联一个2-3k的电阻)TLC5940SOUT树莓派GPIO4TLC5940OUT0LED0负极TLC5940OUT1LED1负极TLC5940OUT2LED2负极TLC5940VCC树莓派5VTLC5940GND树莓派GNDLED0,1,2正极树莓派5V

    代码(Python)

    123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120

    #!/usr/bin/env python import RPi.GPIO as GPIOimport timeVPRG=17SIN=13SCLK=19XLAT=27BLANK=23DCPRG=18GSCLK=4# 传输GSData(0-4095)def setGSData(data):# print ""# print "S-----------setByte---------------:", hex(data)for bit in range(0,12):# 传入的数字从高位到低位依次判断是否为1,若为1则设置高电平,否则设置低电平# 判断的方法是先向左移位,把要判断的位移动到最高位然后跟0x800(1000 0000 0000)相与,# 如果结果仍然是0x80(1000 0000 0000)就表示最高位是1,否则最高位就是0if ((data<0x800 == 0x800):setBitData(True)# print "1",else:setBitData(False)# print "0",# print ""# print "E-----------setByte---------------"def setBitData(data):GPIO.output(SCLK, False)GPIO.output(SIN, data)GPIO.output(SCLK, True)# 输出GSCLK时钟信号def runGSCLK():i=0while(1):i+=1if i>=4096:# 注意,每次计数到4095时需要手动重置一次芯片的计数器GPIO.output(BLANK, True)#time.sleep(0.001);GPIO.output(BLANK, False)i=0else:GPIO.output(GSCLK, True)GPIO.output(GSCLK, False)try:GPIO.setmode(GPIO.BCM)GPIO.setup(VPRG, GPIO.OUT)GPIO.setup(SIN, GPIO.OUT)GPIO.setup(SCLK, GPIO.OUT)GPIO.setup(XLAT, GPIO.OUT)GPIO.setup(BLANK, GPIO.OUT)GPIO.setup(DCPRG, GPIO.OUT)GPIO.setup(GSCLK, GPIO.OUT)# VPRG设置为L,使其工作在GS modeGPIO.output(VPRG, False)# BLANK设置为H,关闭所有输出GPIO.output(BLANK, True)GPIO.output(DCPRG, True)# 传送12bit X 16组PWM数值GSn(n=0-15),共192bit# 每组数据的值范围是0-4095# 因为是通过移位寄存器传输,所以传送顺序是倒序的:GS15,GS14。。。GS0# GSn决定了OUTn的PWM调宽。(GSn / 4095 = 0% - 100%)setGSData(0) # GS15 本文不使用15-3号输出,设为0setGSData(0) # GS14setGSData(0) # GS13setGSData(0) # GS12setGSData(0) # GS11setGSData(0) # GS10setGSData(0) # GS9setGSData(0) # GS8setGSData(0) # GS7setGSData(0) # GS6setGSData(0) # GS5setGSData(0) # GS4setGSData(0) # GS3# print "GS2"setGSData(4095) # GS2# print "GS1"setGSData(2500) # GS1# print "GS0"setGSData(1000) # GS0# 送完GS数据后,创造XLAT的上升沿,将移位寄存器的数据一次性送入GS寄存器GPIO.output(XLAT, False)GPIO.output(XLAT, True)# BLANK设置为L,打开所有输出# GPIO.output(BLANK, False)# 准备工作完毕,下面向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,会有明显的闪烁感runGSCLK()except KeyboardInterrupt:pass# 清理GPIO口GPIO.cleanup()




    打开APP阅读更多精彩内容
    声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
    • 相关推荐

    全部0条评论

    快来发表一下你的评论吧 !

    ×
    20
    完善资料,
    赚取积分