点阵广告屏设计 仿真+原理图+程序+流程图可以实现从左往右或从下往上滚动显示
仿真原理图如下(proteus仿真工程文件可到本帖附件中下载)
单片机源程序如下:
/*********************************************************************
修改时间:2020年10月7日19:42
功能:16*16LED点阵显示
目的:用两种滚动模式显示”创新实验班制作“
显示方式:列扫描方式
取模软件:PCtoLCD2002完美版
**********************************************************************/
#include <reg52.h>
#define uchar unsigned char
#define uint unsigned int
sbit datal595=P1^0; //列数据线
sbit datah595=P1^1; //行数据线
sbit clk595=P1^2; //数据输入时钟线
sbit str595=P1^3; //输出存储器锁存时钟线
sbit oe595=P1^4; //oe输出使能
//取模方式:阳码、逐行式、逆向、十六进制、C51格式自定义 (使用Pctolcd2002软件)
uchar code displaydata[]= //在ROM中定义一个可变长度数组,供用户填充一定个数的字模
{ //可填充的最大字模数取决于您所选用的单片机ROM空间大小
0x00,0x00, /*表头*/
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
//在以下位置插入字模
0x40,0x00,0x20,0x00,0xD0,0x3F,0x4C,0x40,0x43,0x44,0x44,0x48,0xC8,0x47,0x10,0x40,
0x20,0x70,0x00,0x00,0xF8,0x0F,0x00,0x40,0x00,0x80,0xFF,0x7F,0x00,0x00,0x00,0x00,/*"创",0*/
0x40,0x20,0x44,0x12,0x54,0x4A,0x65,0x82,0xC6,0x7F,0x64,0x02,0x54,0x0A,0x44,0x92,
0x00,0x60,0xFC,0x1F,0x44,0x00,0x44,0x00,0xC4,0xFF,0x42,0x00,0x40,0x00,0x00,0x00,/*"新",1*/
0x10,0x04,0x0C,0x84,0x04,0x84,0x84,0x44,0x14,0x47,0x64,0x24,0x05,0x14,0x06,0x0C,
0xF4,0x07,0x04,0x0C,0x04,0x14,0x04,0x24,0x04,0x44,0x14,0x84,0x0C,0x04,0x00,0x00,/*"实",2*/
0x02,0x08,0xFA,0x18,0x82,0x48,0x82,0x84,0xFE,0x44,0x80,0x3F,0x40,0x40,0x20,0x44,
0x50,0x58,0x4C,0x41,0x43,0x4E,0x4C,0x60,0x50,0x58,0x20,0x47,0x40,0x40,0x00,0x00,/*"验",3*/
0x84,0x10,0x84,0x30,0xFC,0x1F,0x84,0x08,0x84,0x88,0x00,0x42,0xF8,0x21,0x00,0x18,
0xFF,0x07,0x00,0x00,0x84,0x20,0x84,0x20,0xFC,0x3F,0x84,0x20,0x84,0x20,0x00,0x00,/*"班",4*/
0x40,0x00,0x50,0x00,0x4E,0x3E,0x48,0x02,0x48,0x02,0xFF,0xFF,0x48,0x12,0x48,0x22,
0x48,0x1E,0x40,0x00,0xF8,0x0F,0x00,0x40,0x00,0x80,0xFF,0x7F,0x00,0x00,0x00,0x00,/*"制",5*/
0x00,0x01,0x80,0x00,0x60,0x00,0xF8,0xFF,0x07,0x00,0x40,0x00,0x30,0x00,0x0F,0x00,
0xF8,0xFF,0x88,0x08,0x88,0x08,0x88,0x08,0x88,0x08,0x08,0x08,0x08,0x00,0x00,0x00,/*"作",6*/
//至此字模插入结束
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
};
/*----------------------------------
函数名字:delay_ms
形式参数:无字符整型 i:延时多少
函数功能:以1ms为单位的函数延时
返 回 值:无
------------------------------------*/
void delay_ms(uint i)
{
uint j;
for(;i>0;i--)
for(j=110;j>0;j--);
}
/*----------------------------------
函数名字:senddata
形式参数:无字符整型 datah:行的数据
无字符整型 datal:列的数据
函数功能:把数据发送给芯片74HC595
返 回 值:无
------------------------------------*/
void senddata(uint datah,uint datal) //向行和列的4个595同时发送数据,显示其中的一列数据
{
uchar i=0;
uint m,n;
oe595=0;
str595=0;
for(;i<16;i++) //行和列各有两片595驱动,所以行和列分别需要连续送两个字节数据
{
clk595=0;
m=datah; //行为高电平驱动
n=~datal; //列为低电平驱动
m&=0x8000;
n&=0x8000;
datah595=(bit)m; //在每个clk周期,同时送出行和列的1bit串行数据
datal595=(bit)n;
datah<<=1;
datal<<=1;
clk595=1;
}
str595=1; //一列数据送完,锁存到输出端进行显示
str595=0;
}
/*----------------------------------
函数名字:char_max
形式参数:无字符字符型 *dat:两个8位数据的第一个数据的地址
函数功能:受到取模软件的限制,需要对字模表的数据进行重新排列
将两个8位的数据拼成显示所需16位的数据
返回值 :uint:返回排列好的值
------------------------------------*/
uint char_max(uchar *dat)
{
uint l,h;
h = (uint)*(dat+1); //16位中的高字节数据
h <<= 8;
h &=0xff00;
l = (uint)*dat; //16位中的低字节数据
l &= 0x00ff;
return l|h;
}
/*----------------------------------
函数名字:horizontal
形式参数:无字符字符型 time:字符移动的速度
无字符字符型 counth:移动全部字符所需的列数
无符号字符型指针 p:字符显示数据的首地址
函数功能:显示字符水平移动
返回值 :无
------------------------------------*/
void horizontal(uchar time,uint count,uchar *p) //垂直移动
{
uint datah,datal; //datah是行数据,datal是列选通
uchar x,y;
uint z;
for(z=0;z<count;z++) //显示字模表中的所有汉字(包括有用字模前后的的清屏数据)
{
for(y=0;y<time;y++) //该屏数据重复显示time次后刷新,实际上这是水平移动的速度
{
for(x=0;x<16;x++) //发送一整屏数据,16个16位
{
p += 2;
datah = char_max(p);
datal = 0x0001<<x; //列选通位移到相应的列上进行选通
// datah=~datah; //去掉此行前面的注释则水平移动程反白显示
senddata(datah,datal); //将行和列数据发送出去进行一列的显示
}
p-=32; //指针恢复为这个汉字首地址,准备重复显示该屏数据time次
} //该屏数据经过了time次的显示,显示数据准备更新
p+=2; //指向了该汉字的下一列,左移一列汉字
} //移动了字模表中的所有汉字,左移过程结束
oe595=1;
}
/*----------------------------------
函数名字: vertical
形式参数: 无字符字符型 a:半角标志 ;如果 a=16 则字符显示数据中出现了半角字
无字符字符型 time:字符移动的速度
无字符字符型 counth:移动全部字符所需的行数
无符号字符型 指针 p:字符显示数据的首地址
函数功能: 显示字符垂直移动
返回值 : 无
------------------------------------*/
void vertical(uchar a,uchar time,uint countv,uchar *p) //水平移动
{
uint datah,datal; //datah是行数据,datal是列选通
uchar x,y,e,w=0;
uint z;
uint datah1,datah2;
uchar *q;
q=p+32;
for(z=countv;z>0;z--) //显示字模表中的所有汉字(包括有用字模前后的的清屏数据)
{
for(e=0;e<16;e++) //拼字的过程,从一个汉字完整地过渡到下一个汉字
{
for(y=0;y<time;y++) //该屏数据重复显示time次后刷新,实际上这是垂直移动的速度
{
for(x=0;x<16;x++) //发送一整屏数据,16个16位
{
/*处理p所指向汉字某一列的拼接*/
p += 2;
datah1 = char_max(p);
datah1>>=w; //这行语句改为左移同时下处改为右移,则显示向下移动
/*处理下一个汉字相应列的拼接*/
q += 2;
datah2 = char_max(q);
datah2 <<= (16-w); //这行语句改为右移同时上处改为左移,则显示向下移动
/*准备显示这列数据*/
datah = datah1|datah2; //此时进行拼接某汉字某一列的运算操作
datal = 0x0001<<x; //列选通位移到相应的列上进行选通
//datah=~datah; //去掉此行前面的注释则垂直移动程反白显示
senddata(datah,datal);
} //一整屏数据发送完毕
p-=32;q-=32; //指针恢复为这个汉字首地址,准备重复显示该屏数据time次
} //该屏数据经过了time次的显示,显示数据准备更新
w++; //显示上移w行的拼接数据移位位数加1
if(w>=16) w=0; //如果上移了15行,w归0,结束此次拼字循环
} //此次拼字循环结束
/*开始对下一组汉字进行拼字操作*/
if((a==16)&&(z==2)) //如果字模表中含有半个汉字并且显示最后一组汉字
{ p+=32;q+=16; } //则q+16,相当于用16个零填充不足的半个汉字
else //其它情况下
{ p+=32;q+=32; } //p和q一律指向下一个汉字
} //拼完字模表中的所有汉字,上移过程结束(注:上移是现象,拼字是本质)
oe595=1;
}
void main(void)
{
uchar time=8; //调整这个值的大小将会改变汉字移动的速度
uint size=sizeof(displaydata); //计算出上述在ROM中定义的可变长度字模表填充数据后的大小
uint countv=((size-2)>>5)-1; // 8 //这些个汉字垂直移动全部完成所需要的拼字次数
uint counth=countv<<4; //128 //这些个汉字水平移动全部完成所需要的左移列数
uchar a=(uchar)((size-2)%32); //判断字模表中是否会出现一个半角的数字或符号或字母
if(a==16) //如果余数为16,说明出现了半角情况
{
counth+=8; //这时左移时需要多移动8列
countv+=1; //而右移时需要多拼一个汉字
}
while(1)
{
horizontal(time,counth,displaydata); //将字模表中的所有汉字进行水平移动
delay_ms(2000);
vertical(a,time,countv,displaydata); //将字模表中的所有汉字进行垂直移动
delay_ms(2000);
}
}
全部资料51hei下载地址:
16X16点阵灯.zip
(131.64 KB, 下载次数: 169)
|