数码之家

标题: 硬件SPI驱动TM1640 [打印本页]

作者: mmxx2015    时间: 2023-5-7 17:38
标题: 硬件SPI驱动TM1640
TM1640 是一种LED(发光二极管显示器)驱动控制专用电路,内部集成有MCU 数字接口、数据锁存器、LED 驱动等电路。本产品性能优良,质量可靠。主要应用于电子产品LED显示屏驱动。采用SOP28的封装形式。

本文仅以驱动TM1640为例,实际上,知道原理后,很容易扩展到其它类似芯片,如TM1668、TM1621等。

TM1640连续写时序如下图:
[attach]1817088[/attach]
[attach]1817089[/attach]

这个时序既不是I2C,也不是SPI,但是,一部分像I2C,有Start、Stop,一部分像SPI。
要实现这个控制时序,有2个要点:数据在时钟低电平时改变;时钟高电平时间至少维持1μS。控制这种芯片,一般做法是纯软件照时序图控制,但是,那样会消耗很多CPU时间。

对于有硬件SPI接口的芯片来说,只要简单变通一下,就可以用软硬结合的办法控制TM1640,大大减少CPU时间占用。

大部分芯片SPI时序图是这样,只需控制通讯速率就能满足TM1640控制时序。
[attach]1817093[/attach]

不过,有的芯片SPI时序是这样,需要硬件上处理一下才能满足TM1640控制时序。
[attach]1817094[/attach]

控制要点:
(1)确保数据在时钟低电平时改变数据,对于那些SPI接口在时钟高电平时改变数据的芯片,在时钟线加RC积分电路把时钟上升沿推后,确保数据在时钟低电平时改变。
[attach]1817165[/attach]

部分RC参数测试结果如下:
[attach]1817166[/attach]

(2)初始化时不使能SPI,只需用一般GPIO方式控制MOSI和SCLK输出高电平。
(3)开始发送数据时,用一般GPIO方式控制MOSI和SCLK输出高电平输出一个启动信号(MOSI输出电平一会后SCLK输出低电平)。
(4)SPI接口初始化配置为:先发送数据低位、CPOL=0、CPHA=1(空闲时时钟=低电平,数据在第二个边沿采样),使能SPI,使能SPI中断(数据量不多,DMA意义不大),发送Command1:设置数据。
(5)在SPI中断服务程序中禁用SPI,用一般GPIO方式控制MOSI和SCLK输出一个停止信号和一个启动信号,然后使能SPI,发送Command2:设置地址。
(6)中断方式继续发送数据直到显示数据发送完成。
(7)最后一个字节显示数据发送完成后的SPI中断禁用SPI,用一般GPIO方式控制MOSI和SCLK输出一个停止信号和一个启动信号,然后使能SPI,发送Command3:控制显示。
(8)发送Command3后的SPI中断禁用SPI,用一般GPIO方式控制MOSI和SCLK输出一个停止信号,一次显示数据输出完成。

上述处理信号时序如下:
[attach]1817109[/attach]

实际信号如下:
[attach]1817110[/attach]

扩展应用
对像TM1668那样多了STB通讯线的芯片,只需在输出STB信号的地方禁用SPI,输出STB信号,然后使能SPI继续通讯即可。
[attach]1817111[/attach]

对需要一个前导位+8数据位的SPI通讯,只需禁用SPI,输出前导位,然后再使能SPI发送8位数据即可。
[attach]1817112[/attach]

22楼更新代码:


作者: 北斗    时间: 2023-5-7 17:53
LZ高手,研究的狗透彻
作者: fqxxqwy    时间: 2023-5-7 18:03
这才是真正研究到位的!赞!!
作者: 慕名而来    时间: 2023-5-7 21:04
楼主你好,关于本帖中的最后一个时序图片的实现,我曾经也想利用I/O模拟发送D/CX加硬件SPI的方式实现,但是用STC单片机弄了很久未能实现,因为想不到可以用阻容延时来改变起始电平状态所以一直未能实现,很希望楼主能贴一段STC单片机适用的关于这种type c时序的硬件SPI代码来学习一下,先谢了。
作者: 广东梁百万    时间: 2023-5-7 21:49
TM1640是好东西,我开始买了5片作验证,成功后又买了20片作备用。

看我的程序     https://www.mydigit.cn/thread-378745-1-1.html
作者: mmxx2015    时间: 2023-5-7 22:20
慕名而来 发表于 2023-5-7 21:04
楼主你好,关于本帖中的最后一个时序图片的实现,我曾经也想利用I/O模拟发送D/CX加硬件SPI的方式实现,但是 ...

如果要控制的设备也是SPI接口只是多一位数据的话,是不需要加RC延时的,只需程序上加一位数据即可。我手上没有需要9位格式的通讯的芯片,有空我写一段你试下能不能用。
作者: inthsunshine    时间: 2023-5-7 23:27
其实还是io模拟更好,类似i2c, 这种读写数据量很小,也只有键盘扫描或者显示更新才会运行,基本不消耗什么资源, 大可不必简单问题复杂化

spi资源更珍贵,稍微做个复杂点的,spi口都不够用,64/100脚的stm32通常3个spi, 有些spi还会别的复用冲突
作者: 595953427@qq    时间: 2023-5-8 00:15
反复看了这个帖子,一直不明白用硬件SPI驱动TM1640的意义是什么,TM1640的数据量不大,对速度要求不高,任意单片机用IO模拟就完全可以了,本身就不是标准的IIC,也不是标准的SPI。
作者: mmxx2015    时间: 2023-5-8 01:43
inthsunshine 发表于 2023-5-7 23:27
其实还是io模拟更好,类似i2c, 这种读写数据量很小,也只有键盘扫描或者显示更新才会运行,基本不消耗什么 ...

本文只是一种方法来讲,当SPI接口紧缺而且有更重要的用途,当然要取舍,如果空闲,为什么不用呢?
作者: mmxx2015    时间: 2023-5-8 01:54
595953427@qq 发表于 2023-5-8 00:15
反复看了这个帖子,一直不明白用硬件SPI驱动TM1640的意义是什么,TM1640的数据量不大,对速度要求不高,任 ...

我个人的习惯是,能用硬件接口通讯就不用软件模拟,就这个TM1640来说,刚开始不加RC电路之前无法点亮,已用软件模拟方式点亮了,但这不是我想要的,于是,想出了这种方法。
作者: 595953427@qq    时间: 2023-5-8 08:30
mmxx2015 发表于 2023-5-8 01:54
我个人的习惯是,能用硬件接口通讯就不用软件模拟,就这个TM1640来说,刚开始不加RC电路之前无法点亮,已 ...

我的看法完全相反,能用IO模拟解决的就不用硬件解决,除非数据量大,速度要快,要用DMA,否则就用IO模拟
作者: inthsunshine    时间: 2023-5-8 09:38
mmxx2015 发表于 2023-5-8 01:43
本文只是一种方法来讲,当SPI接口紧缺而且有更重要的用途,当然要取舍,如果空闲,为什么不用呢? ...

不过从你的操作过程看,远比io模拟更复杂, 一会开中断一会关中断;IO模式一会复用,一会通用,硬件上还要加RC, RC取值还有讲究

作者: mmxx2015    时间: 2023-5-8 10:00
本帖最后由 mmxx2015 于 2023-5-8 10:01 编辑
inthsunshine 发表于 2023-5-8 09:38
不过从你的操作过程看,远比io模拟更复杂, 一会开中断一会关中断;IO模式一会复用,一会通用,硬件上还 ...


不用关中断啊,只需在中断中禁用SPI,发完stop、start再使能SPI。
RC的值是可以大概计算的。
作者: 慕名而来    时间: 2023-5-8 11:11
mmxx2015 发表于 2023-5-7 22:20
如果要控制的设备也是SPI接口只是多一位数据的话,是不需要加RC延时的,只需程序上加一位数据即可。我手 ...

多谢,期待看到你的代码,其实我的这个三线spi屏也已经驱动成功很久了,现在使用中的是通过可寻址位变量逐位输出模拟SPI的模式,用STC硬件驱动也测试成功了只是需要发送两次8位数据,一直想通过I/O模拟一位数据+8位SPI硬件的模式驱动却无法实现,看到你的实验又勾起了我的兴趣想再玩一玩。我现在用的代码如下,这个代码看似复杂其实效率是很高的,STC8H8K64TL单片机时钟频率超过22M就无法通讯了,这种C接口的屏幕貌似通讯速度快不起来的。

  1. voidwrite_data(u8 dat)
  2. {
  3. bitdata=dat;
  4. sda=1;
  5. scl=0;scl=1;//D/C=1写数据
  6. sda=bit7;
  7. scl=0;scl=1;
  8. sda=bit6;
  9. scl=0;scl=1;
  10. sda=bit5;
  11. scl=0;scl=1;
  12. sda=bit4;
  13. scl=0;scl=1;
  14. sda=bit3;
  15. scl=0;scl=1;
  16. sda=bit2;
  17. scl=0;scl=1;
  18. sda=bit1;
  19. scl=0;scl=1;
  20. sda=bit0;
  21. scl=0;scl=1;
  22. }
复制代码



作者: STC32位8051    时间: 2023-5-8 14:00
提示: 作者被禁止或删除 内容自动屏蔽
作者: 595953427@qq    时间: 2023-5-8 18:27
慕名而来 发表于 2023-5-8 11:11
多谢,期待看到你的代码,其实我的这个三线spi屏也已经驱动成功很久了,现在使用中的是通过可寻址位变量 ...

速度太快通迅异常,有没有可能是芯片IO口的速度跟不上CPU的速度?

一般SPI接口的液晶屏的接口速度是非常快的
作者: 慕名而来    时间: 2023-5-8 21:23
595953427@qq 发表于 2023-5-8 18:27
速度太快通迅异常,有没有可能是芯片IO口的速度跟不上CPU的速度?

一般SPI接口的液晶屏的接口速度是非常 ...

这我就不太清楚了,我也只是能做到模拟时序实现基本驱动,如楼主那样清晰的分析原理我还做不来。
作者: 595953427@qq    时间: 2023-5-8 22:07
慕名而来 发表于 2023-5-8 21:23
这我就不太清楚了,我也只是能做到模拟时序实现基本驱动,如楼主那样清晰的分析原理我还做不来。 ...

一般的芯片都是CPU的速度比外设的速度快,比如STM32F103,CPU速度是72M,GPIO的速度最高只有50M,如果CPU不停的让IO输出高低电平,可能IO会反应不过来,导致实际输出的波形出错,然后导致通讯出错。
作者: zhkrid    时间: 2023-5-8 22:21
大多情况下是cpu性能过剩,一般项目不会这么折腾,但有研究的意义
作者: 慕名而来    时间: 2023-5-8 22:24
595953427@qq 发表于 2023-5-8 22:07
一般的芯片都是CPU的速度比外设的速度快,比如STM32F103,CPU速度是72M,GPIO的速度最高只有50M,如果CPU ...

明白了,找时间我用STM32再测试一下这段代码,谢谢。
作者: 595953427@qq    时间: 2023-5-8 23:29
慕名而来 发表于 2023-5-8 22:24
明白了,找时间我用STM32再测试一下这段代码,谢谢。

如果用IO模拟不加延时的话,用STM32也可能会出现通讯异常。除非是GPIO的速度比CPU快,可以降低CPU的主频,让IO的速度比CPU快,这样CPU让IO输出高低电平的时候IO能反应的过来了。
作者: mmxx2015    时间: 2023-5-9 01:00
本帖最后由 mmxx2015 于 2023-5-9 01:03 编辑
慕名而来 发表于 2023-5-8 11:11
多谢,期待看到你的代码,其实我的这个三线spi屏也已经驱动成功很久了,现在使用中的是通过可寻址位变量 ...

显示驱动芯片如果是ILI9481,时序要求如下:
[attach]1818465[/attach]
时钟电平、高电平最窄分别为40nS,最多时钟周期=100nS。
以STC8H8K64U来说,主频=22.1184MHz时,你这段程序输出信号大致如下图:
[attach]1818473[/attach]
时钟低电平宽度不够40nS,需插入延时。
查看反汇编指令,时钟低电平只维持一个系统时钟,对照指令表,以主频=22.1184MHz计算,时间=(1/22.1184MHz)≈45nS,比较临界。
[attach]1818470[/attach]
插入延时后的程序(需包含intrins.h):

  1. #define        SCL_LOW_DELAY()                NOP1()
  2. #define        SCL_HIGH_DELAY()        //NOP2()

  3. void write_data(unsigned char dat)
  4. {
  5.         bitdata=dat;
  6.         
  7.         sda=1;
  8.         scl=0;SCL_LOW_DELAY();scl=1;SCL_HIGH_DELAY();        //D/C=1写数据
  9.         sda=bit7;
  10.         scl=0;SCL_LOW_DELAY();scl=1;SCL_HIGH_DELAY();
  11.         sda=bit6;
  12.         scl=0;SCL_LOW_DELAY();scl=1;SCL_HIGH_DELAY();
  13.         sda=bit5;
  14.         scl=0;SCL_LOW_DELAY();scl=1;SCL_HIGH_DELAY();
  15.         sda=bit4;
  16.         scl=0;SCL_LOW_DELAY();scl=1;SCL_HIGH_DELAY();
  17.         sda=bit3;
  18.         scl=0;SCL_LOW_DELAY();scl=1;SCL_HIGH_DELAY();
  19.         sda=bit2;
  20.         scl=0;SCL_LOW_DELAY();scl=1;SCL_HIGH_DELAY();
  21.         sda=bit1;
  22.         scl=0;SCL_LOW_DELAY();scl=1;SCL_HIGH_DELAY();
  23.         sda=bit0;
  24.         scl=0;SCL_LOW_DELAY();scl=1;SCL_HIGH_DELAY();
  25. }
复制代码
插入延时后的信号
[attach]1818474[/attach]

由于带宽的原因,我这个逻辑分析仪无法采集主频=48MHz时的I/O翻转信号,测试主频=40MHz时,I/O翻转速度可以测到但可能不是很准。
[attach]1818476[/attach]

主频=48MHz时,指令周期=(1/48MHz)=20.8nS,时钟低电平之后需插入约2个NOP。
  1. #define        SCL_LOW_DELAY()                NOP2()
  2. #define        SCL_HIGH_DELAY()        //NOP2()
复制代码
插入2个NOP后的信号,这样的信号应该能正常通讯了,如果不行,改为3~4个NOP。

[attach]1818477[/attach]


作者: bboroo    时间: 2023-5-9 08:36
个人觉得,除非是IO口不够用,否则还是用IO口直接控制的方便。
作者: 慕名而来    时间: 2023-5-9 09:20
mmxx2015 发表于 2023-5-9 01:00
显示驱动芯片如果是ILI9481,时序要求如下:

时钟电平、高电平最窄分别为40nS,最多时钟周期=100nS。

我玩的正是这个9481的TFT屏,第一次学到时序模拟如此清晰明了,其实我也有一个简易的逻辑分析仪,带宽只有24M而且也是因为这个驱动才学习了一点简单的用法,也只是学会了大致看一下波形、而参数分析就不会了,与楼主的交流学习到了很多东西,多谢了!
作者: mmxx2015    时间: 2023-5-9 09:24
慕名而来 发表于 2023-5-9 09:20
我玩的正是这个9481的TFT屏,第一次学到时序模拟如此清晰明了,其实我也有一个简易的逻辑分析仪,带宽只 ...


测量开关信号,至少需要10倍待测信号频率的带宽,采样频率也要尽量高,不然,要么采不到或者信号宽度误差大。
协议分析是厂家配的软件提供的功能,当然了,也可以自己解析。
作者: STC32位8051    时间: 2023-5-9 09:39
提示: 作者被禁止或删除 内容自动屏蔽
作者: 人生之际    时间: 2023-5-9 09:48
很好,理解原理的
作者: lmn2005    时间: 2023-5-9 09:52
总觉得用硬件SPI来驱动TM1640,真不如用软件来驱动方便。 不过还得佩服楼主的研究精神。
作者: 慕名而来    时间: 2023-5-9 09:59
mmxx2015 发表于 2023-5-9 09:24
测量开关信号,至少需要10倍待测信号频率的带宽,采样频率也要尽量高,不然,要么采不到或者信号宽度误差 ...

好的明白了,方才我测试了添加延时后的代码,仅使用低电平延时SCL_LOW_DELAY()     NOP1()后用STC8H8K64TL芯片可以设置系统时钟为45MHZ并且运行稳定,刷屏速度目测比此前加快了约2.5倍,效果挺显著的。
作者: o535913    时间: 2023-5-9 10:21
你们不停的用同一句话回复楼主有意思吗, 别人说的话再复制重复一遍为了M币?

我比较好奇的是为什么不直接做成I2C接口的
作者: mmxx2015    时间: 2023-5-9 10:48
o535913 发表于 2023-5-9 10:21
你们不停的用同一句话回复楼主有意思吗, 别人说的话再复制重复一遍为了M币?

我比较好奇的是为什么不直接做 ...


据说做成I2C接口需要交版权费,I2C接口的版权在NXP手里,不知道SPI是不是要交钱。这种显示芯片通讯协议确实不伦不类。
作者: chanwah2000    时间: 2023-5-9 16:05
好像1640用的不是标准的协议,还是用软件模拟方便些,

前些天刚试了一下用来驱动数码管显示时钟的功能


[attach]1818872[/attach]

作者: longxiuwei    时间: 2023-5-9 16:07
感谢!!
作者: inthsunshine    时间: 2023-5-9 22:23
o535913 发表于 2023-5-9 10:21
你们不停的用同一句话回复楼主有意思吗, 别人说的话再复制重复一遍为了M币?

我比较好奇的是为什么不直接做 ...

协议比i2c简单,我就是在i2c基础上修改一下就可以用
作者: STC32位8051    时间: 2023-5-10 08:51
提示: 作者被禁止或删除 内容自动屏蔽
作者: zhuls    时间: 2023-5-10 16:37
我用的是1629A,单个IC多了个片选脚,对于这类没有级联功能 的IC,有片选脚无疑更方便软件的操作。抗干扰什么的优于纯2线的。
驱动6个1088点阵、1302、18B20、Beep、几个按键,就一个8h1k08(ssop20),还有多出的IO。。
作者: msvcp60    时间: 2023-5-12 05:36
纯技术贴要支持!楼主肯定也知道模拟io更简单,只是换种方式验证自己的技术思路。
作者: inthsunshine    时间: 2023-5-12 14:54
zhuls 发表于 2023-5-10 16:37
我用的是1629A,单个IC多了个片选脚,对于这类没有级联功能 的IC,有片选脚无疑更方便软件的操作。抗干扰什 ...

其实TM1627更好,带中断输出脚,有按键会产生中断信号,不需要频繁扫描键盘
作者: zhuls    时间: 2023-5-12 16:35
inthsunshine 发表于 2023-5-12 14:54
其实TM1627更好,带中断输出脚,有按键会产生中断信号,不需要频繁扫描键盘 ...

适合的才是最好的。
1629A可驱16*8,两个1088点阵一块1629A就够了,且电路无需太多的按键,开个中断比较费。
作者: 酷酷数码    时间: 2023-5-12 19:12
没点基础看不懂这个
作者: pontifex    时间: 2023-5-14 19:34
太专业了,不明白~~~
作者: mmxx2015    时间: 2023-5-17 02:39
慕名而来 发表于 2023-5-8 11:11
多谢,期待看到你的代码,其实我的这个三线spi屏也已经驱动成功很久了,现在使用中的是通过可寻址位变量 ...

基于STC8H8K64U的ILI9481 9bit SPI驱动测试程序,试试看能不能用。
[attach]1825328[/attach]

随便发送一些数据、随便指定D/CX信号的时序:
[attach]1825329[/attach]

[attach]1825330[/attach]

查看开头几个字节的信号,应该是符合ILI9481 9bit SPI时序。


这是完整工程,如果移植到其它程序,只需把spi.c、spi.h复制到目标工程中,按需配置引脚即可。

程序把命令和数据混合的表格逐个发送,使用的是一般指针,表格可以是常数表格,也可以是一段RAM。如果不习惯使用指针,可以按数组方式使用:去掉函数
  1. void SPI_Send_Bytes(INT8U *Source_Pointer,INT16U Send_Bytes)
复制代码
的指针,变成
  1. void SPI_Send_Bytes(INT16U Send_Bytes)
复制代码
调用是只需传递发送字节数即可。
SPI_Send_Bytes()和SPI中断中的装载数据变成:
  1. SPDAT=Display_Test_Table[s_spi_send_count];        //发送一个字节
复制代码




作者: 慕名而来    时间: 2023-5-17 11:53
mmxx2015 发表于 2023-5-17 02:39
基于STC8H8K64U的ILI9481 9bit SPI驱动测试程序,试试看能不能用。

很感谢楼主的热心回复,我先测试一下代码看看效果,再谢!
作者: wonxcn1    时间: 2023-5-19 08:22
有程序吗
作者: STC32位8051    时间: 2023-5-19 10:46
提示: 作者被禁止或删除 内容自动屏蔽
作者: ねね    时间: 2023-5-19 11:55
高手,学习一下!!
作者: tomyluo    时间: 2023-5-23 08:42
mmxx2015 发表于 2023-5-8 10:00
不用关中断啊,只需在中断中禁用SPI,发完stop、start再使能SPI。
RC的值是可以大概计算的。 ...

有没有办法可以不用RC延迟,用其他的芯片实现延迟?RC延迟波形会变差
作者: mmxx2015    时间: 2023-5-23 09:05
tomyluo 发表于 2023-5-23 08:42
有没有办法可以不用RC延迟,用其他的芯片实现延迟?RC延迟波形会变差

如果SPI硬件设计成时钟下降沿一会再改变MOSI、时钟高电平保持MOSI状态就可以,但SPI时序上只要求采样沿MOSI输出目标数据,不一定能满足。
作者: sunnyquan    时间: 2023-5-23 10:54
试试这个芯片IS31FL3743B

作者: mmxx2015    时间: 2023-5-23 11:12
sunnyquan 发表于 2023-5-23 10:54
试试这个芯片IS31FL3743B

其实,用TM1640只是因为之前别人说用这种芯片驱动数码管对收音机模块有干扰,我告诉别人通讯线加RC、SEG串电阻可改善,想实际验证一下是不是真可以改善。
作者: xueyeteng    时间: 2023-5-25 11:12
研究得透彻





欢迎光临 数码之家 (https://www.mydigit.cn/) Powered by Discuz! X3.4