1、功能描述
设计16*64LED点阵屏,制作胸牌,显示如下效果,并且让字体有滚动效果(字体从下到上、从上到下、从左到右、从右到左显示)
2、PROTEUS中设计的电路图
3、源代码(代码中有详细注释)
#include <reg51.h>
#include <intrins.h>
sbit OE=P1^0;//锁存
sbit EN=P1^1;//行选输出允许
//阴码,按行取模,低位在前
unsigned char code font[][32]={
{0x00,0x03,0x00,0x03,0x00,0x0F,0x00,0x0F,0x00,0x3C,0x00,0x3C,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0x00,0x3C,0x00,0x3C,0x00,0x0F,0x00,0x0F,0x00,0x03,0x00,0x03},/*"C:\Users\FUTURE\Desktop\箭头.bmp",0*/
{0x40,0x00,0x80,0x00,0x80,0x00,0xFF,0x7F,0x20,0x00,0x20,0x00,0x20,0x00,0xE0,0x0F,
0x20,0x08,0x20,0x08,0x20,0x08,0x10,0x08,0x10,0x08,0x08,0x08,0x04,0x05,0x02,0x02},/*"方",0*/
{0x00,0x00,0x3C,0x1E,0x7E,0x3F,0xFE,0x7F,0xFE,0x7F,0xFE,0x7F,0xFE,0x7F,0xFE,0x3F,
0xFC,0x1F,0xF8,0x1F,0xF0,0x0F,0xE0,0x07,0xC0,0x03,0xC0,0x01,0x80,0x00,0x00,0x00},/*"C:\Users\FUTURE\Desktop\心.bmp",0*/
{0x08,0x00,0x10,0x20,0xFE,0x1E,0x00,0x02,0x44,0x02,0x28,0x02,0xFF,0x7E,0x10,0x12,
0x10,0x12,0xFE,0x12,0x10,0x12,0x54,0x12,0x92,0x12,0x11,0x11,0x14,0x11,0x88,0x10},/*"新",0*/
{0xC0,0x00,0xE0,0x00,0xF0,0x00,0xF8,0x00,0x7C,0x00,0x3E,0x00,0xFE,0x7F,0xFF,0xFF,
0xFF,0xFF,0xFE,0x7F,0x3E,0x00,0x7C,0x00,0xF8,0x00,0xF0,0x00,0xE0,0x00,0xC0,0x00},/*"C:\Users\FUTURE\Desktop\箭头(反).bmp",0*/
};
void delay(unsigned int xms)
{int i,j;
for(i=0;i<=xms;i++)
for(j=0;j<=110;j++);
}
//从下往上
void downtoup()
{
unsigned char i=0,k,m,j,x,y;
for(i=0;i<16;i++) //i:16帧
for(x=0;x<15;x++) //x:一帧重复显示20次,实际上控制的是上下滚动的速度
for(k=15-i,m=0;k<16;k++,m++) //k:第一帧从第15行开始显示,第二帧从第14行开始显示。。。。。。
//m:总是从第0行开始送字模
{
EN=1;//行选输出禁止
for(j=0,y=0;j<5;j++) //j:共5个字,一次送一个字的一行
//y:总是从第0列点阵屏开始
{
P0=font[j][2*m]; //一行的低8位
P3=y++; //指定哪个点阵
OE=0; //更新
OE=1; //锁存
P0=font[j][2*m+1]; //一行的高8位
P3=y++; //指定哪个点阵
OE=0; //更新
OE=1; //锁存
}
P2=k; //设置行选信号
EN=0; //行选输出允许
delay(1);
}
}
//从上往下
void uptodown()
{
unsigned char i=0,k,m,j,x,y;
for(i=0;i<16;i++) //i:16帧
for(x=0;x<15;x++) //x:一帧重复显示20次,实际上控制的是上下滚动的速度
for(k=0,m=15-i;k<=i;k++,m++) //k:每帧都是从第0行开始显示,第i帧共显示i行
//m:第一帧从第15行开始送字模,第二帧从第14行开始送字模
{
EN=1;//行选输出禁止
for(j=0,y=0;j<5;j++) //j:共8个字,一次送一个字的一行
//y:总是从第0列点阵屏开始
{
P0=font[j][2*m]; //一行的低8位
P3=y++; //指定哪个点阵
OE=0; //更新
OE=1; //锁存
P0=font[j][2*m+1]; //一行的高8位
P3=y++; //指定哪个点阵
OE=0; //更新
OE=1; //锁存
}
P2=k; //设置行选信号
EN=0; //行选输出允许
delay(1);
}
}
//从右往左,一次移动一个字
void righttoleft()
{
unsigned char i,k,j,x,y;
for(i=0;i<6;i++) //i:5帧,,第6帧是让最后显示空白
for(x=0;x<20;x++) //x:一帧重复显示20次,实际上控制的是上下滚动的速度
for(k=0;k<16;k++) //k:每帧16行都要显示
{
EN=1;//行选输出禁止
for(j=i,y=0;j<5;j++) //j:一帧显示i~7这几个字
{
P0=font[j][2*k]; //一行的低8位
P3=y++; //指定哪个点阵
OE=0; //更新
OE=1; //锁存
P0=font[j][2*k+1]; //一行的高8位
P3=y++; //指定哪个点阵
OE=0; //更新
OE=1; //锁存
}
while(y<10) //一帧显示i~7这几个字后,剩下的送字模0x00,即:不显示
{
P0=0x00; //一行的低8位
P3=y++; //指定哪个点阵
OE=0; //更新
OE=1; //锁存
P0=0x00; //一行的高8位
P3=y++; //指定哪个点阵
OE=0; //更新
OE=1; //锁存
}
P2=k; //设置行选信号
EN=0; //行选输出允许
delay(1);
}
}
//从左往右,一次移动一个字
void lefttoright()
{
unsigned char i,k,j,x,y;
for(i=0;i<6;i++) //i:5帧,,第6帧是让最后显示空白
for(x=0;x<15;x++) //x:一帧重复显示20次,实际上控制的是上下滚动的速度
for(k=0;k<16;k++) //k:每帧16行都要显示
{
EN=1;//行选输出禁止
y=0;
while(y<2*i) //一帧先0~i-1这几个字不显示,所以送字模0x00
{
P0=0x00; //一行的低8位
P3=y++; //指定哪个点阵
OE=0; //更新
OE=1; //锁存
P0=0x00; //一行的高8位
P3=y++; //指定哪个点阵
OE=0; //更新
OE=1; //锁存
}
for(j=0;j<5-i;j++) //j:一帧显示0~8-i这几个字
{
P0=font[j][2*k]; //一行的低8位
P3=y++; //指定哪个点阵
OE=0; //更新
OE=1; //锁存
P0=font[j][2*k+1]; //一行的高8位
P3=y++; //指定哪个点阵
OE=0; //更新
OE=1; //锁存
}
P2=k; //设置行选信号
EN=0; //行选输出允许
delay(1);
}
}
//从右往左,一次移动半个字
void righttoleft_half()
{
unsigned char i,k,j,x,y;
for(i=0;i<11;i++) //i:16帧
for(x=0;x<15;x++) //x:一帧重复显示20次,实际上控制的是上下滚动的速度
for(k=0;k<16;k++) //k:每帧16行都要显示
{
EN=1;//行选输出禁止
for(j=i,y=0;j<10;j++) //j:一帧显示16-i个半字
{
P0=font[j/2][2*k+j%2]; //送半字
P3=y++; //指定哪个点阵
OE=0; //更新
OE=1; //锁存
}
while(y<11) //剩下的i个半字送0x00,即:不显示
{
P0=0x00; //一行的低8位
P3=y++; //指定哪个点阵
OE=0; //更新
OE=1; //锁存
// P0=0x00; //一行的高8位
// P3=y++; //指定哪个点阵
// OE=0; //更新
// OE=1; //锁存
}
P2=k; //设置行选信号
EN=0; //行选输出允许
delay(1);
}
}
//从左往右,一次移动半个字
void lefttoright_half()
{
unsigned char i,k,j,x,y;
for(i=0;i<11;i++) //i:10帧 16
for(x=0;x<15;x++) //x:一帧重复显示20次,实际上控制的是上下滚动的速度
for(k=0;k<16;k++) //k:每帧16行都要显示
{
EN=1;//行选输出禁止
y=0;
while(y<i) //先送i个0x00,即:不显示
{
P0=0x00; //一行的低8位
P3=y++; //指定哪个点阵
OE=0; //更新
OE=1; //锁存
}
for(j=0;j<10-i;j++) //j:一帧显示16-i个半字
{
P0=font[j/2][2*k+j%2]; //送半字
P3=y++; //指定哪个点阵
OE=0; //更新
OE=1; //锁存
}
P2=k; //设置行选信号
EN=0; //行选输出允许
delay(1);
}
}
void bink(){
unsigned char i,j,k,n=0;
while(n<15){
for(i=0;i<16;i++) //按行,共16行,一次点亮所有8个字的一行
{
EN=1;//行选输出禁止
for(j=0,k=0;j<5;j++) //共8个字,一次送一个字的一行
{
P0=font[j][2*i]; //一行的低8位
P3=k++; //指定哪个字
OE=0; //更新
OE=1; //锁存
P0=font[j][2*i+1]; //一行的高8位
P3=k++; //指定哪个字
OE=0; //更新
OE=1; //锁存
}
P2=i; //设置行选信号
EN=0; //行选输出允许
delay(1);
}
n++;
}
}
void main()
{
int i=0;
while(1){
downtoup();
while(i<3){
bink();
delay(400);
i++;
}
i=0;
uptodown();
righttoleft();
lefttoright();
righttoleft_half();
lefttoright_half();
while(i<3){
bink();
delay(400);
i++;
}
}
}