【有图有真相】STM32驱动全彩点阵,有木有感兴趣的啊

2019-08-12 16:50发布

        最近搞了个全彩点阵,有点伤心,,,打样的PCB质量伤不起啊,各种问题,都不太想接着做了。不知有木有感兴趣的哥们啊,共享下我的东西吧。。。
        先上图:



                     焊好了各种芯片。。。




                    焊好点阵块,点阵好贵的啊。。。





                     用手摸一摸信号线,看到了希望啊。。。




                    显示ASCII,后来加入了SPI FLASH ,搞了GBK字符集,支持所有中文显示了




                     这个大家认识吧。。嘿嘿。。手机拍摄的效果没有人眼看上去的好,况且隔得近,这么大个点得隔几米远看起来才细腻啊。。。




                    这个是阿狸,嘿嘿。。。看起来不是很像大家也是知道的,32*16的分辨率啊!


原理图见附件,代码在下面:


行驱动,采用的是74HC138:


这个大家都会的,译码器。。。


void LED_SelectLine(u8 line) { switch(line) { case 0:HC138C_LOW();HC138B_LOW();HC138A_LOW();   HC138S1_HIGH();HC138S2_LOW();break; case 1:HC138C_LOW();HC138B_LOW();HC138A_HIGH(); HC138S1_HIGH();HC138S2_LOW();break; case 2:HC138C_LOW();HC138B_HIGH();HC138A_LOW(); HC138S1_HIGH();HC138S2_LOW();break; case 3:HC138C_LOW();HC138B_HIGH();HC138A_HIGH(); HC138S1_HIGH();HC138S2_LOW();break; case 4:HC138C_HIGH();HC138B_LOW();HC138A_LOW(); HC138S1_HIGH();HC138S2_LOW();break; case 5:HC138C_HIGH();HC138B_LOW();HC138A_HIGH(); HC138S1_HIGH();HC138S2_LOW();break; case 6:HC138C_HIGH();HC138B_HIGH();HC138A_LOW(); HC138S1_HIGH();HC138S2_LOW();break; case 7:HC138C_HIGH();HC138B_HIGH();HC138A_HIGH(); HC138S1_HIGH();HC138S2_LOW();break; case 8:HC138C_LOW();HC138B_LOW();HC138A_LOW(); HC138S1_LOW();HC138S2_HIGH();break; case 9:HC138C_LOW();HC138B_LOW();HC138A_HIGH(); HC138S1_LOW();HC138S2_HIGH();break; case 10:HC138C_LOW();HC138B_HIGH();HC138A_LOW(); HC138S1_LOW();HC138S2_HIGH();break; case 11:HC138C_LOW();HC138B_HIGH();HC138A_HIGH(); HC138S1_LOW();HC138S2_HIGH();break; case 12:HC138C_HIGH();HC138B_LOW();HC138A_LOW(); HC138S1_LOW();HC138S2_HIGH();break; case 13:HC138C_HIGH();HC138B_LOW();HC138A_HIGH(); HC138S1_LOW();HC138S2_HIGH();break; case 14:HC138C_HIGH();HC138B_HIGH();HC138A_LOW(); HC138S1_LOW();HC138S2_HIGH();break; case 15:HC138C_HIGH();HC138B_HIGH();HC138A_HIGH();HC138S1_LOW();HC138S2_HIGH();break; default:HC138S1_HIGH();HC138S2_HIGH();break; } }
列驱动采用的是德州仪器的一款IC:TLC5941,这种全彩屏一般都是用的FPGA做吧,在这我搞STM32试了下,面积不能太大。全彩驱动起来特别要速度,一个点由红绿蓝3个led组成,得控制每个led的亮度,数据量比较大呀。。。搞个小屏玩玩还是可以的。。。

void TLC_GPIO_Init(void) { GPIO_InitTypeDef GPIO_InitStructure;  SPI_InitTypeDef  SPI_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA| RCC_APB2Periph_GPIOB | RCC_APB2Periph_AFIO |  RCC_APB2Periph_GPIOF | RCC_APB2Periph_GPIOE, ENABLE);   RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1 ,ENABLE);
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_All;   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;   GPIO_Init(GPIOE, &GPIO_InitStructure); 
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2; // XLAT          MODE       BLANK      GPIO_Init(GPIOF, &GPIO_InitStructure);   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7;   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;   GPIO_Init(GPIOA, &GPIO_InitStructure);   SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;   SPI_InitStructure.SPI_Mode = SPI_Mode_Master;   SPI_InitStructure.SPI_DataSize = SPI_DataSize_16b;   SPI_InitStructure.SPI_CPOL = SPI_CPOL_High;   SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;   SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;   SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_4;   SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;   SPI_InitStructure.SPI_CRCPolynomial = 7;   SPI_Init(SPI1, &SPI_InitStructure);
  SPI_Cmd(SPI1, ENABLE);  
}
void TLC5941_Init(void) { GSCLK_Init();    // Enable GSCLK TLC_GPIO_Init(); // GPIO Init }
u16 TLC_SendData(u16 dat) {   while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET);     SPI1->DR = dat;   while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET);   return (SPI1->DR); }
void TLC_Set(u16 *p) { u8 i; /* Turn off all outputs */ BLANK_HIGH(); /* XLAT Pin set low */ XLAT_LOW();     /* NOTE : XLAT pin must be low when the MODE pin gose high-to-low or  low-to-high to change back and forth between GS_MODE and DC_MODE */ /* Enter DC_MODE */ MODE_HIGH(); /* Send dot correction data 6*16 = 96 bits */ for(i=0;i<6;i++) { TLC_SendData(*p); p++; }   /* XLAT Pin set high */ XLAT_HIGH();  /* XLAT Pin set low */ XLAT_LOW();   /* Turn on all outputs */ BLANK_LOW();  }
void TLC_Display(u16 *p) { u8 i; /* Turn off all outputs */ BLANK_HIGH(); /* XLAT Pin set low */ XLAT_LOW(); /* Enter GS_MODE */ MODE_LOW(); /* Send GS data 12*16 = 192 bits */ for(i=0;i<12;i++) { TLC_SendData(*p); p++; }   /* XLAT Pin set high */ XLAT_HIGH();  /* XLAT Pin set low */ XLAT_LOW();   /* Turn on all outputs */ BLANK_LOW();  }

驱动是老老实实对着手册敲的啊,有问题望指正哈。

此外,这款IC还需要一个PWM参考时钟,在芯片速度极限内,速度越快, {MOD}彩饱和度越高,看起来越鲜艳,当然,速度一块干扰问题又来了,这里用了STM32的定时器输出方波,STM32方波速度一开快了就变三角波了,呵呵

void GSCLK_Init(void) { TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure; TIM_OCInitTypeDef  TIM_OCInitStructure; GPIO_InitTypeDef GPIO_InitStructure; RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);   RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD | RCC_APB2Periph_AFIO, ENABLE); GPIO_PinRemapConfig(GPIO_Remap_TIM4,ENABLE);   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;       GPIO_Init(GPIOD, &GPIO_InitStructure);
  TIM_TimeBaseStructure.TIM_Period = 2;//Auto-Reload Register (ARR)   TIM_TimeBaseStructure.TIM_Prescaler = (u16)(SystemCoreClock / 24000000) - 1;   TIM_TimeBaseStructure.TIM_ClockDivision = 0;   TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;   TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure);
TIM_OCInitStructure.TIM_Pulse = 2;//Capture Compare Register(CCR)   TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_Toggle;   TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;   TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;   TIM_OC1Init(TIM4, &TIM_OCInitStructure);   TIM_OC1PreloadConfig(TIM4, TIM_OCPreload_Enable);   TIM_ARRPreloadConfig(TIM4, ENABLE);   TIM_Cmd(TIM4, ENABLE); }

就这么多了,希望对大家有用,有兴趣的哥们也搞个玩玩啊。。














        


        

友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
45条回答
subo19920716
2019-08-15 16:20
 回复【26楼】 tao475824827 :
---------------------------------
你好,做成32行的话可能有一点点压力,如果是扫32行的话亮度就会降低,甚至可能闪屏,做成16行扫的,得增加芯片,同时单片机也要一次发送两行的数据,全彩点阵的数据量比较大。

这个东西我也研究过一下,小面积用单片机,用类似于TLC5941这样的芯片驱动,应该是不成问题的,这个原理和74HC595是一样的。如果想玩大的,这种方案是行不通的。首先TLC4951
这个芯片很贵,面积大了成本会很高,而且这个芯片也不太好买。市场上的全彩屏用的都不是这样的方案,都是专门的横流IC驱动的,像台湾聚积的。这些驱动IC原理和74HC595也类似,
595是恒压,这个是横流,一个是16通道,一个是8通道。用这些芯片做,成本可以降低很多,这些芯片一般价格低于1元。

可能你会有一个疑问,74HC595我们平时用的时候输出都是 1 和 0 两种状态,那怎么让74HC595产生半亮类似于PWM效果呢?用专业的话讲就是怎么产生灰度。
在这里可以充分的利用74HC595的OE使能脚,用PWM控制OE即可。例如我要让接在595的Q0脚LED亮度为1/16,Q1的亮度为2/16,Q2为3/16 ...... 那么从Q0 ~ Q2接的LED亮度依次增强。
此时可以将OE的PWM分为4种,分别为1/16,2/16,4/16,8/16。那么Q0可由第一种PWM表现出来,Q1可由第二种PWM表现出来,Q3可由第一种和第二种PWM叠加表现出来,依次类推....
所以一帧数据我们需要发送四次,同时每次的OE占空比都不同,这样一帧下来后,给人的感觉就是每个led的亮度都不一样。用此种方法控制RGB三原 {MOD},就可以实现全彩了。这只是基本原理,
你可以在此基础上拓展出更加高效的算法出来。

这样也会带来一个问题,平时发送一次的数据,要分四次发送,这样要求处理器性能更强。如果是用STM32驱动,小面积应该是没有问题的。

74HC595是恒压的,而且是8通道,可能你想用专门做全彩点阵的驱动IC来做,横流16通道,可以带来更均匀的亮度以及更简单的布线。我了解的几款台湾聚积的芯片,和595还是有一些区别的,
这类芯片含有一些LED专门用的命令信号,而这些命令的发送与获得,是靠时钟的脉冲数和一根专用线实现的,也就是说SPI在发送一个字节的第几位时,你得在另外一根信号线上给一个上升/下降沿。这样也给我们带来一个麻烦事,就是STM32的硬件SPI口不能配置成这种芯片这样的时序,那么软件模拟的话速度要大打折扣了。

所以要有一个“定制”的这样的逻辑帮你刷屏就一切都好办了,这应该也就是为什么那些全彩点阵控制卡全部是FPGA做的原因了吧。

说了这么多,总结一下吧。哥们如果你有兴趣玩这个,可以尝试用CPLD,FPGA这样的器件去驱动。
用LED专门的驱动芯片,搞一片SDRAM作为点阵屏的缓存,用CPLD/FPGA源源不断的产生这样的“刷屏”逻辑,把SDRAM的数据往屏上搬,那么就可以保证不闪屏和高亮度。
同时你可以用CPLD/FPGA搞一个兼容STM32的FSMC的接口,那么就和你玩LCD是一样的了,速度也很快了。甚至FPGA搞一个SPI口,你用51单片机驱动这个屏都会很爽了。




一周热门 更多>