最近搞了个全彩点阵,有点伤心,,,打样的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);
}
就这么多了,希望对大家有用,有兴趣的哥们也搞个玩玩啊。。
---------------------------------
有5mm点直径的全彩便宜些哦,还有那些厂家的单元板貌似更便宜,但是他们大多用的是595类的驱动芯片,或者是类似两个595串联的芯片。如果用这种方案做全彩,大部分用的是fpga啊,用stm32恐怕吃不消哦,这个速度要求特别快啊。原子哥要做什么?透漏下,呵呵。用双 {MOD}点阵很好啊,便宜着呢。。
一周热门 更多>