最近用6块8*8全彩点阵做了一个16*24的全彩屏,每个点可以显示7种颜色,这个可以实现一些好玩的功能,比如俄罗斯方块。
一、原理
1. 点阵屏的16行使用2个74hc138组成4-16译码,之后用三极管9012驱动,用100的限流电阻
2. 点阵屏的24列使用9个74hc595驱动,第一个595驱动第一列8*8点阵的红led,第二个595驱动第一列8*8点阵的绿led,第三个595驱动第一列8*8点阵的蓝led,以此类推,使用100的限流电阻
3. GND与VCC之间接入104瓷片电容与470uF 16V电解电容,增加抗干扰能力
4. 使用74hc245驱动595,提高驱动能力,这样单片机的IO口通过245就可以一次驱动一行的9个595了
5. 点阵的行用高电位,列用低电位
二、接口
1. A、B、C、D为行选线
2. G为屏使能线,接在74hc138上
3. CLK、LATCH、DATA为595驱动线,分别为输入触发、输出触发、串行数据输入
4. GND、VCC
三、实物图
四、代码
1. 头文件
#ifndef __RGBDZH_H__
#define __RGBDZH_H__
#include <reg51.h>
#include <intrins.h>
#define BLOCK_ROW_COUNT 2
#define BLOCK_COL_COUNT 3
#define PIXEL_ROW_COUNT (BLOCK_ROW_COUNT*8)
#define PIXEL_COL_COUNT (BLOCK_COL_COUNT*8)
/*颜色定义*/
#define NONE 0x00
#define RED 0x01
#define GREEN 0x02
#define BLUE 0x04
#define YELLOW (RED|GREEN)
#define PURPLE (RED|BLUE)
#define LBLUE (GREEN|BLUE)
#define WHITE (RED|GREEN|BLUE)
// 端口定义
/*行选*/
sbit A_Port = P1^0;
sbit B_Port = P1^1;
sbit C_Port = P1^2;
sbit D_Port = P1^3;
/*使能*/
sbit En_Port = P1^4;
/*输入触发*/
sbit Clk_Port = P1^5;
/*输出触发*/
sbit Latch_Port = P1^6;
/*串口输入*/
sbit Data_Port = P1^7;
// 接口函数
void Lcd_Init();
void Lcd_Clear();
void Lcd_Refresh();
void Lcd_SetPixel( unsigned char x, unsigned char y, unsigned char color);
unsigned char Lcd_GetPixel( unsigned char x, unsigned char y);
#endif
2. 源文件
#include "RGBDZh.h"
// 开启:一次扫描1*24
// 关闭:一次扫描1*8, 一行分三次扫描
#define ENABLE_ROW_SCAN
#define COLOR_BASE_COUNT 3
#define CACHE_DATA_SIZE (PIXEL_ROW_COUNT*BLOCK_COL_COUNT*COLOR_BASE_COUNT)
static unsigned char xdata cache_data[CACHE_DATA_SIZE];
static unsigned char xdata cur_row = 0;
#ifndef ENABLE_ROW_SCAN
static unsigned char xdata cur_block = 0;
#endif
void Lcd_Init()
{
Lcd_Clear();
}
void Lcd_Clear()
{
unsigned int i;
for( i = 0; i < CACHE_DATA_SIZE; i ++)
cache_data[i] = 0xff;
cur_row = 0;
#ifndef ENABLE_ROW_SCAN
cur_block = 0;
#endif
}
void Lcd_Refresh()
{
char i, j;
/*74HC595*/
/*串入数据*/
for( i = BLOCK_COL_COUNT * COLOR_BASE_COUNT - 1; i >= 0; i --)
{
unsigned char buff = cache_data[BLOCK_COL_COUNT * COLOR_BASE_COUNT * cur_row + i];
for( j = 0; j < 8; j ++)
{
#ifndef ENABLE_ROW_SCAN
if( i / COLOR_BASE_COUNT != cur_block)
Data_Port = 1;
else
#endif
if(( buff & 0x01) == 0x01)
Data_Port = 1;
else
Data_Port = 0;
Clk_Port = 0;
_nop_();
_nop_();
Clk_Port = 1;
_nop_();
_nop_();
buff >>= 1;
}
}
/*并出数据*/
Latch_Port = 0;
_nop_();
_nop_();
Latch_Port = 1;
_nop_();
_nop_();
Latch_Port = 0;
_nop_();
_nop_();
/*74HC138*/
/*显示数据*/
En_Port = 1;
A_Port = cur_row & 0x01;
B_Port = ( cur_row >> 1) & 0x01;
C_Port = ( cur_row >> 2) & 0x01;
D_Port = ( cur_row >> 3) & 0x01;
En_Port = 0;
#ifndef ENABLE_ROW_SCAN
cur_block ++;
if( cur_block >= BLOCK_COL_COUNT)
{
#endif
cur_row ++;
if( cur_row >= PIXEL_ROW_COUNT)
cur_row = 0;
#ifndef ENABLE_ROW_SCAN
cur_block = 0;
}
#endif
}
void Lcd_SetPixel( unsigned char x, unsigned char y, unsigned char color)
{
unsigned int offset;
unsigned char mask;
if( x >= PIXEL_COL_COUNT || y >= PIXEL_ROW_COUNT)
return;
offset = BLOCK_COL_COUNT * COLOR_BASE_COUNT * y + x / 8 * COLOR_BASE_COUNT;
mask = 0x01 << ( 7 - x % 8);
// Red
cache_data[offset] |= mask;
if( color & RED)
cache_data[offset] &= ~mask;
// Green
cache_data[offset + 1] |= mask;
if( color & GREEN)
cache_data[offset + 1] &= ~mask;
// Blue
cache_data[offset + 2] |= mask;
if( color & BLUE)
cache_data[offset + 2] &= ~mask;
}
unsigned char Lcd_GetPixel( unsigned char x, unsigned char y)
{
unsigned char r = NONE;
unsigned int offset;
unsigned char mask;
if( x >= PIXEL_COL_COUNT || y >= PIXEL_ROW_COUNT)
return r;
offset = BLOCK_COL_COUNT * COLOR_BASE_COUNT * y + x / 8 * COLOR_BASE_COUNT;
mask = 0x01 << ( 7 - x % 8);
// Red
if(( cache_data[offset] & mask) == 0x00)
r |= RED;
// Green
if(( cache_data[offset + 1] & mask) == 0x00)
r |= GREEN;
// Blue
if(( cache_data[offset + 2] & mask) == 0x00)
r |= BLUE;
return r;
}
五、测试代码
#include "RGBDZh.h"
int main()
{
unsigned char index = 0;
Lcd_Init();
TMOD = 0x01;
TH0 = 0xfc;
TL0 = 0x66;
TR0 = 1;
EA = 1;
ET0 = 1;
while(1)
{
unsigned char colors[7] = { RED, GREEN, BLUE, YELLOW, PURPLE, LBLUE, WHITE};
unsigned int i;
for( i = 0; i < 16 * 24; i ++)
{
Lcd_SetPixel( i % 24, i / 24, colors[index++]);
if( index >= 7)
index = 0;
{
unsigned int j;
for(j=0;j<5000;j++);
}
}
Lcd_Clear();
}
return 0;
}
void disp() interrupt 1 using 3
{
TH0 = 0xfc;
TL0 = 0x66;
Lcd_Refresh();
}
请移步www.yintju03.com/blog