打印

关于多屏LED显示的问题,请指教

[复制链接]
3987|20
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
zpf111|  楼主 | 2007-8-20 18:29 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
首先我说下我的思路,如果有错误请指点出来,谢谢!
先从code区取出要显示的字码,再一位位的送到595,一直到6个汉字的字码传送完毕,138译码该行,再开显示。共16次完成一次屏扫描。
但是后来出现了问题。用AT89S52时,如果显示汉字大于4个的话就会闪烁。而我之间没有延时,是不断的扫描的。
后来改用W77E58,恢复正常。
但是这次要求显示3屏的(每屏6个汉字),又闪了,没办法,把晶振从11.0892提高到36点多,可以正常显示。
因此我认为是送数据过程中耗费了很所时间,所以扫描的频率不够,因此会闪。
但是我有一个疑问:如果是这样的话,那么外面那么多大屏怎么会不闪?他们用的是什么不同的显示方法?
请各位朋友帮帮忙,怎样才能在不提高cpu成本的情况下使LED不闪。(主要就是送数据以及扫描有什么更好的办法),菜鸟在此致谢!

相关帖子

沙发
xwj| | 2007-8-20 18:43 | 只看该作者

是你的软件效率太差,用串口模式0,或一次送8位

使用特权

评论回复
板凳
zpf111|  楼主 | 2007-8-20 18:49 | 只看该作者

回xwj

谢谢您的指点。
但是硬件是已经设计好的,只能一位位的从p1的一个口送,我才取得是嵌入汇编的方法移位过去的。
还有别的什么方法么?

使用特权

评论回复
地板
xwj| | 2007-8-20 19:00 | 只看该作者

错了就改啊,设计系统就得先满足最紧迫的需要,好钢用在

只有这样才能得到最好的整体性价比

使用特权

评论回复
5
zpf111|  楼主 | 2007-8-20 19:02 | 只看该作者

谢谢xwj

我只是打工的,能做的就是按照要求写点程序。。。

使用特权

评论回复
6
hq_y| | 2007-8-20 19:35 | 只看该作者

软件效率太差,18个汉字1/8扫描,11.0592M晶振,没有问题

外面的大屏,我认为可能是使用硬件的spi扫描,也可以是使用cpld硬件直接驱动;

8位mcu中,avr的MIPS是最好的;

使用特权

评论回复
7
z_no1| | 2007-8-20 19:46 | 只看该作者

出来混的,生死要由自己来定。

你自己在软件编程水平达到或超过大师级和说服老板不改板子就做不出来中选一样吧。18个汉字,按16*16算,扫一次4608个位。一秒要扫100次才不闪。波特率要在460,800BPS以上。算上其他的时间,波特率最少要1M。建议要用W77E58的话还不如用ARM7。还便宜点。当然你要会用。

使用特权

评论回复
8
winloop| | 2007-8-21 08:41 | 只看该作者

居然还有人在用89S52。。。

老板让你用89S52做128个字的屏你也能干?

使用特权

评论回复
9
lenglx| | 2007-8-21 08:47 | 只看该作者

给个以前的参考例子

一个96*32的LED屏,双色,按汉字数计算应当是6*2,控制器用AT89S52.



显示部分的代码:


; Display buffer: 0x000-0x200
; 0x000-0x010: display datas for line#1
; ...
; 0x100-0x110: display datas for line#17
; ...
DATAS   SEGMENT DATA
CODES   SEGMENT CODE
AUXR1   DATA    0A2H
RED1    BIT P1.5
RED2    BIT P1.6
CLK BIT P1.7
CSEG    AT 000BH
    JMP DISPLAY
RSEG    DATAS
    CURLINE:    DS  1
    P1BAK:      DS  1
USING 1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
OUT_1_DOT   MACRO     val
    MOV C, B.val
    MOV RED1, C
    MOV C, ACC.val
    MOV RED2, C
    SETB    CLK
    CLR CLK
ENDM
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
RSEG    CODES
Display:
    PUSH    PSW
    PUSH    ACC
    PUSH    B
    PUSH    DPH
    PUSH    DPL
    PUSH    AUXR1
    MOV AUXR1, #0
    MOV PSW, #08H
    MOV A, P1
    MOV P1BAK, A
    MOV P1, #0      ; 选择1#存储器(RAM)
    CLR TR0
    MOV TL0, #0FCH  ;1.1ms
    MOV TH0, #0F8H
    SETB    TR0
    MOV A, CURLINE
    SWAP    A
    MOV DPL, A
    MOV R4, #12     ; 96 DOTS
_LOOP:
    MOV DPH, #0
    MOVX    A, @DPTR
    MOV B, A
    MOV DPH, #1
    MOVX    A, @DPTR
    OUT_1_DOT 0
    OUT_1_DOT 1
    OUT_1_DOT 2
    OUT_1_DOT 3
    OUT_1_DOT 4
    OUT_1_DOT 5
    OUT_1_DOT 6
    OUT_1_DOT 7
        
    INC DPL
    DJNZ    R4, _LOOP
    ;锁存数据
    SETB    P1.3
    SETB    P1.4
    MOV A, CURLINE
    SETB    ACC.4   ; st
    ;CLR    ACC.5   ; eh off
    MOVX    @R0, A
    CLR ACC.4
    SETB    ACC.5
    MOVX    @R0,A

    INC CURLINE
    ANL CURLINE, #0FH
 POSThttps://bbs.21ic.com/club/bbs/SaveOwnerEd   POP AUXR1
    POP DPL
    POP DPH
    POP B
    POP ACC
    POP PSW
    RETI

END     
原理图:
https://bbs.21ic.com/upfiles/img/20078/200782184134221.pdf
 

使用特权

评论回复
10
lenglx| | 2007-8-21 08:55 | 只看该作者

怎么文字老是有些杂七杂八的字符呢

后面的几句如下:
    INC CURLINE
    ANL CURLINE, #0FH

    MOV A, P1BAK
    MOV P1, A

    POP AUXR1
    POP DPL
    POP DPH
    POP B
    POP ACC
    POP PSW
    RETI

使用特权

评论回复
11
古道热肠| | 2007-8-21 10:38 | 只看该作者

LED屏的软硬件设计

    提高刷新率的办法,不外乎以下几种
1、数据移出到HC595时,采用汇编程序实现功能函数
2、采用硬件SPI高速输出数据到HC595
3、采用硬件发码电路(并转串移位输出),提高数据的输出速度。
4、数据移位时不关显示,待数据全部移位到HC595中时,用锁存输出数据将二级锁存器的内容输出才关闭显示。
5、采用6时钟单片机如Philips公司或STC公司的单片机进行提速

采用11.0592MHZ时钟,做128*32点阵的屏时,虽然全力优化,也无法避免闪烁。后用18.432M双倍速单片机能正常显示。
   LED屏最难做的是屏幕内容平滑左移,请教LengLx和有过类似开发经验的朋友如何实现的。

使用特权

评论回复
12
古道热肠| | 2007-8-21 10:44 | 只看该作者

下面这段代码拿去试试速度,已到极限了

LED单元板列驱动使用了数据线,时钟线,只有二级锁存器的锁存信号是分开的,HC595的OE合用的。

//LED屏驱动

; #pragma src  (LED_ShiftRegistControl.a51) small


; #include "..incincludes.h"

; extern uchar ucColDataBuff_High[16];
; extern uchar ucColDataBuff_Low[16];


; sbit c_Col_SData = P1^5;
; sbit c_Col_SClk = P1^7;
; sbit c_Col_SOut_High = P1^0;
; sbit c_Col_SOut_Low = P1^1;

; sbit c_Col_SOE  = P1^2;

; /*
; void ShT_LEDBoard_ColShiftOut(void)
; {
;     uchar ucByteCount;
;     uchar ucBitCount;
;     uchar ucTemp;

;     c_Col_SOE = 0;
;     c_Col_SClk = 0;
;     c_Col_SOut_High = 0;
;     
;     for(ucByteCount=0; ucByteCount<16; ucByteCount++)
;     {
;         ucTemp = ucColDataBuff_High[ucByteCount];
;     
;         for(ucBitCount=0; ucBitCount<8; ucBitCount++)
;         {
;             if(ucTemp & 0x80)
;             {
;                 c_Col_SData = 0;        //When Shift Register Latch Out Value is Zero,the Led is Light
;             }
;             else
;             {
;                 c_Col_SData = 1;
;             }

;             c_Col_SClk = 1;
;             ucTemp <<= 1;
;             c_Col_SClk = 0;
;         }
;     }
;     
;     c_Col_SOut_High = 1;
;     c_Col_SOut_High = 0;


;     for(ucByteCount=0; ucByteCount<16; ucByteCount++)
;     {
;         ucTemp = ucColDataBuff_Low[ucByteCount];
;     
;         for(ucBitCount=0; ucBitCount<8; ucBitCount++)
;         {
;             if(ucTemp & 0x80)
;             {
;                 c_Col_SData = 0;        //When Shift Register Latch Out Value is Zero,the Led is Light
;             }
;             else
;             {
;                 c_Col_SData = 1;
;             }

;             c_Col_SClk = 1;
;             ucTemp <<= 1;
;             c_Col_SClk = 0;
;         }
;     }
;     c_Col_SOut_Low = 1;
;     c_Col_SOut_Low = 0;

;     c_Col_SOE = 0;
; }
; */

; void ShT_LEDBoard_ColShiftOut(void)

    RSEG  ?PR?ShT_LEDBoard_ColShiftOut?LEDSHIFTREGISTERCONTROL
ShT_LEDBoard_ColShiftOut:
    USING    0
            ; SOURCE LINE # 82
; {
            ; SOURCE LINE # 83
;     uchar ucByteCount;
;     uchar ucBitCount;
;     uchar ucTemp;


     Clr Col_SOE ;
;     c_Col_SClk = 0;
    Clr Col_SClk
;     c_Col_SOut_High = 0;
    Clr Col_SOut_High
;     
;     for(ucByteCount=0; ucByteCount<16; ucByteCount++)
    MOV      A,#LOW (ucColDataBuff_High)
    MOV      R0,A

    Mov R2,#16
ShiftOutByte_HighScreen:
          Mov R3,#8
        Mov A,@R0
        CPL A
    
    ShiftOutBit_HighScreen:
        Rlc A
        Mov Col_SData,c
        
        SetB Col_SClk
        Clr  Col_SClk

        DJNZ R3,ShiftOutBit_HighScreen

        Inc R0
        DJNZ R2,ShiftOutByte_HighScreen

    SetB Col_SOut_High
    Clr  Col_Sout_High

        
    MOV      A,#LOW (ucColDataBuff_Low)
    MOV      R0,A

    Mov R2,#16
ShiftOutByte_LowScreen:
          Mov R3,#8
        Mov A,@R0
        CPL A
    
    ShiftOutBit_LowScreen:
        Rlc A
        Mov Col_SData,c
        
        SetB Col_SClk
        Clr  Col_SClk

        DJNZ R3,ShiftOutBit_LowScreen

        Inc R0
        DJNZ R2,ShiftOutByte_LowScreen

    SetB Col_SOut_Low
    Clr  Col_Sout_Low
        
    Clr Col_SOE
;     {
;         ucTemp = ucColDataBuff_High[ucByteCount];
;     
;         for(ucBitCount=0; ucBitCount<8; ucBitCount++)
;         {
;             if(ucTemp & 0x80)
;             {
;                 c_Col_SData = 0;        //When Shift Register Latch Out Value is Zero,the Led is Light
;             }
;             else
;             {
;                 c_Col_SData = 1;
;             }

;             c_Col_SClk = 1;
;             ucTemp <<= 1;
;             c_Col_SClk = 0;
;         }
;     }
;     
;     c_Col_SOut_High = 1;
;     c_Col_SOut_High = 0;


;     for(ucByteCount=0; ucByteCount<16; ucByteCount++)
;     {
;         ucTemp = ucColDataBuff_Low[ucByteCount];
;     
;         for(ucBitCount=0; ucBitCount<8; ucBitCount++)
;         {
;             if(ucTemp & 0x80)
;             {
;                 c_Col_SData = 0;        //When Shift Register Latch Out Value is Zero,the Led is Light
;             }
;             else
;             {
;                 c_Col_SData = 1;
;             }

;             c_Col_SClk = 1;
;             ucTemp <<= 1;
;             c_Col_SClk = 0;
;         }
;     }
;     c_Col_SOut_Low = 1;
;     c_Col_SOut_Low = 0;

;     c_Col_SOE = 0;


;     ucTemp = ucColDataBuff_High[ucByteCount];
            ; SOURCE LINE # 89
;    MOV      R7,ucByteCount?040
;    MOV      A,#LOW (ucColDataBuff_High);
;    ADD      A,R7
;    MOV      R0,A
;    MOV      A,@R0
;    MOV      R7,A
;    MOV      ucTemp?042,R7
;     
;     ucTemp = ucColDataBuff_Low[ucByteCount];
            ; SOURCE LINE # 91
;    MOV      R7,ucByteCount?040
;    MOV      A,#LOW (ucColDataBuff_Low)
;    ADD      A,R7
;    MOV      R0,A
;    MOV      A,@R0
;    MOV      R7,A
;    MOV      ucTemp?042,R7
; }
            ; SOURCE LINE # 92
    RET      
; END OF ShT_LEDBoard_ColShiftOut

    END

使用特权

评论回复
13
吴杰宏| | 2007-8-21 10:50 | 只看该作者

这个CPU 太老了

2楼说的对的,用窜口吧 ,或者加几个延迟试试看.
现在的LED 都升级了,你的CPU 级别太低,会影响功能的

使用特权

评论回复
14
xwj| | 2007-8-21 10:57 | 只看该作者

呵呵,你这算什么极限速度啊?

说了用51的串口模式0,每一位只要1个周期
18.432M双倍速单片机的话显示320*240点阵都没问题(40Hz)

            i=OSD_WINX;
//            TI=1;
            do
            {
//                while(!TI);
//                TI=0;
                SBUF=*pp_show;
                pp_show++;
#ifdef OSD_xdata
                _nop_();
#else
                _nop_();_nop_();_nop_();
#endif
            }
            while (--i); //发送下一字节

//本程序由xwj设计的UltraEdit脚本加亮显示,如需要脚本访问我的Blog 或发送邮件至:xwjfile@21cn.com


这是用于单色OSD的,如果是LED屏,最好还是8位或16位送数

只要你能充分发掘硬件的功能,就算是51都能相当厉害的哦!

使用特权

评论回复
15
lenglx| | 2007-8-21 11:00 | 只看该作者

像左移这样的代码,最好用汇编

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;24点阵左移
?PR?MoveLeft?ALL     SEGMENT CODE 
?BI?ALL              SEGMENT BIT 
RSEG  ?BI?ALL
             bc:   DBIT   1

    PUBLIC  MoveLeft24
    PUBLIC  MoveLeft16
; void  ModeLeft24()

    RSEG  ?PR?MoveLeft?ALL
MoveLeft24:
     
    MOV R5, #LOW(BUF)
    MOV DPL, #LOW(BUF)
    MOV DPH, #HIGH(BUF)
        MOV R3, #24 ;24行数据
ML_LOOP2:
    SETB    C
    MOV R4, #12;每行12个字节(96点)
ML_LOOP:
    MOVX    A, @DPTR
    RRC A
    MOVX    @DPTR,A
    MOV BC, C
    DEC DPL
    DJNZ    R4, ML_LOOP

    MOV A, R5
    ADD A, #BYTES_PER_LINE
    MOV DPL, A
    MOV R5, A
    JNC ML_NXT
    INC DPH
ML_NXT:
    DJNZ    R3, ML_LOOP2

    RET 

当然,这段程序是特殊的应用在某个具体的屏上面的,不怎么通用.
但这段程序的目的就是尽量提高左移所用的时间,所以也没考虑通用的问题.

使用特权

评论回复
16
lenglx| | 2007-8-21 11:14 | 只看该作者

呵呵.

是,用串口实现移位能提高速度.
但普通的51只有一个串口,有可能不能供你扫描用.比如实时显示的情况下,MCU要从上位机不停的接收数据,然后显示,这时只有使用IO口来显示了.

没怎么具体计算过,使用普通的51的话(并使用IO扫描),假设扫描频率控制在75HZ,估计128*32的双色屏也就到极限了(扫描所用的时间如果占CPU的60以上,估计显示方式就成问题了.)

另外还有一种做法,屏体比较大的情况下,显示数据是在外部RAM中的,可以在电路上设计使得:读XRAM的时候,就将XRAM中的内容锁存到一个移位寄存器中(就是将单片机的RD信号与一个选择信号,作为锁存信号),这样也能使扫描速度提高不少.

但我现在一般都没怎么使用51了,确实速度太慢了点,不怎么好控制比较大的LED屏.

使用特权

评论回复
17
lenglx| | 2007-8-21 11:20 | 只看该作者

另外补充一点:

看你们所说的左移,好像都是直接在扫描的时候实现的.

但其实真正的LED控制不是这样做的,应当是一个显示缓冲区.
显示方式的实现就是更改缓冲区的内容.

这样你可以为显示屏分区,以便不同的区显示不同的内容.

而且如果有更多的显示方式需要实现,那种在扫描过程控制"左移"这样的做法,也不可行.

使用特权

评论回复
18
lenglx| | 2007-8-21 11:24 | 只看该作者

用DS80C320做的

一个带灰度的LED控制器.

照片用手机拍的,颜色有失真.

使用特权

评论回复
19
lenglx| | 2007-8-21 11:29 | 只看该作者

不至于图片显示成这样吧

使用特权

评论回复
20
古道热肠| | 2007-8-21 11:42 | 只看该作者

为什么不是极限呢?

    **作数据时,先是将数据从SRAM中的点阵全部移到51单片机内部Idata空间,这段时间显示是开着的,待数据要从单片机移到单元板时,关闭显示,将数据快速移出到单元板,移完行列数据后,再开显示。
    XWJ的方法虽然好,但只能以字节方式操作,与SPI高速串行输出原理一样的。如果要将数据移9位,恐怕就办不到了,我实现屏体显示内容左移动时就用到了这种技术。
   

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

3

主题

8

帖子

1

粉丝