1.设计任务
利用AT89C51单片机为核心控制元件,设计一个LED点阵显示屏,设计的系统实用性强、操作简单,实现了智能化、数字化。
(1)本设计的理论基础是单片机原理与应用,模电和数电。比如AT89C51芯片的一些工作原理是在MCS—51的基础上通过改进完成的。
(2)本设计完成了16*16LED点阵动态显示两个以上汉字,并可以利用按键控制其移动、切换。
2. 设计要求
2.1系统方案论证
根据设计任务,分析设计系统的组成,给出实现设计任务的几种方案,分析比较几种设计方案的优略,本着尽量以软件代替硬件,同时力求电路简单,工作可靠的原则,确定总体设计方案。
2.2系统硬件电路设计
根据系统设计方案进行软、硬件的分配,软、硬件设计分别进行。硬件设计包括单片机最小系统和扩展接口及配置,硬件结构在设计时要选择合适的元器件,硬件电路要简洁、工作可靠,需用Proteus绘制整个系统的电路仿真原理图。
2.3软件设计
根据该系统要求的功能进行软件设计,简述软件的功能,并根据每个模块的功能绘制软件流程图,根据流程图编写程序并汇编调试通过;列出软件清单,软件清单要求加以注释。
uchar code table1[][32*10]={ //阴码 逐行 逆向
{
0x08,0x00,0x08,0x3F,0x08,0x20,0x08,0x10,0x3F,0x08,0x24,0x04,0x24,0x04,0xA4,0x7F,
0x24,0x04,0x12,0x04,0x14,0x04,0x08,0x04,0x14,0x04,0x22,0x04,0x21,0x05,0x00,0x02,/*"好",0*/
0x08,0x00,0x08,0x3F,0x08,0x20,0x08,0x10,0x3F,0x08,0x24,0x04,0x24,0x04,0xA4,0x7F,
0x24,0x04,0x12,0x04,0x14,0x04,0x08,0x04,0x14,0x04,0x22,0x04,0x21,0x05,0x00,0x02,/*"好",1*/
0x44,0x10,0x88,0x10,0x88,0x08,0x00,0x04,0xFE,0x7F,0x02,0x40,0x01,0x20,0xF8,0x07,
0x00,0x02,0x80,0x01,0xFF,0x7F,0x80,0x00,0x80,0x00,0x80,0x00,0xA0,0x00,0x40,0x00,/*"学",2*/
0x00,0x00,0xFE,0x1F,0x00,0x10,0x00,0x10,0x10,0x10,0x20,0x10,0x40,0x10,0x40,0x10,
0x00,0x16,0x80,0x11,0x70,0x10,0x0E,0x10,0x04,0x10,0x00,0x10,0x00,0x0A,0x00,0x04,/*"习",3*/
0x00,0x00,0xFC,0x1F,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0xFF,0x7F,0x80,0x00,
0x40,0x01,0x40,0x01,0x20,0x02,0x20,0x02,0x10,0x04,0x08,0x08,0x04,0x10,0x03,0x60,/*"天",4*/
0x00,0x00,0xFC,0x1F,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0xFF,0x7F,0x80,0x00,
0x40,0x01,0x40,0x01,0x20,0x02,0x20,0x02,0x10,0x04,0x08,0x08,0x04,0x10,0x03,0x60,/*"天",5*/
0x40,0x00,0x20,0x00,0x10,0x00,0xFE,0x3F,0x02,0x20,0x02,0x20,0xE2,0x23,0x22,0x22,
0x22,0x22,0x22,0x22,0x22,0x22,0xE2,0x23,0x22,0x22,0x02,0x20,0x02,0x28,0x02,0x10,/*"向",6*/
0x40,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0xC0,0x1F,0x40,0x00,
0x40,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0xFF,0x7F,0x00,0x00,/*"上",7*/
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,0x08,0x1C,0x0E,0x22,0x08,0x20,
0x08,0x10,0x08,0x08,0x08,0x04,0x3E,0x3E,
0x00,0x00,0x1C,0x18,0x22,0x14,0x20,0x14,
0x18,0x12,0x20,0x3E,0x22,0x10,0x1C,0x10,/*"1234",0*/
0x00,0x00,0x3E,0x1C,0x02,0x02,0x02,0x02,
0x1C,0x1E,0x20,0x22,0x20,0x22,0x1E,0x1C,
0x00,0x00,0x3E,0x1C,0x20,0x22,0x10,0x22,
0x10,0x3E,0x08,0x22,0x04,0x22,0x04,0x1C,/*"5678",0*/
0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x02,
0x38,0x07,0xFC,0x0F,0xFC,0x0F,0xFC,0x0F,
0xFC,0x0F,0xF8,0x07,0xF8,0x07,0xF0,0x03,
0xE0,0x01,0xC0,0x00,0x00,0x00,0x00,0x00,/*"爱心",0*/
0x00,0x00,0x22,0x1C,0x22,0x08,0x22,0x08,
0x3E,0x08,0x22,0x08,0x22,0x08,0x22,0x1C,
0x00,0x00,0x3C,0x22,0x10,0x12,0x10,0x0A,
0x10,0x06,0x10,0x0A,0x12,0x12,0x0C,0x22,/*"hijlk",0*/
0x00,0x00,0xFC,0x1F,0x02,0x10,0x02,0x10,
0x02,0x10,0x32,0x33,0x32,0x23,0x02,0x20,
0x02,0x20,0x12,0x22,0xB2,0x23,0xF2,0x23,
0x02,0x10,0x02,0x10,0xFE,0x1F,0x00,0x00,/*"笑脸",0*/
0x22,0x7C,0x12,0x10,0x0A,0x10,0x06,0x10,
0x06,0x10,0x0A,0x10,0x12,0x10,0x22,0x1E,
0x00,0x00,0x82,0x7E,0x44,0x20,0x28,0x10,
0x10,0x08,0x28,0x04,0x44,0x02,0x82,0x7E,/*"KJXZ",0*/
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,
}
};
uchar show_temp[32]; //用于显示的缓存
uchar zuoyou_temp[16]; //用于左右移动的显示之外的缓存
char code Hang[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f}; //用于行码 ,选择行用的 595
void delay(int z) //延时程序
{
int x,y;
for(x=55;x>0;x--)
for(y=z;y>0;y--);
}
void wordByt(char b) //写(拆分)一个字节数据 传给595芯片
{
char i;
for(i=0;i<8;i++)
{
b=b>>1; //右移一位,暂存近CY
R=CY; //取出最低位
CLK=0; //上升沿
CLK=1;
}
}
int i=0;
void main()
{
int num, speed; //num用于显示 speed用于显示的速度的
uint temp; //缓存 一字节数据
uchar hanzi_witch = 1; //显示汉字那组数据 还是显示ASCII那组数据
hanzi_num = 8; /*当前组数据 汉字的个数 更改第2处*/
key_u = 1; //按键高电平
key_d = 1;
key_r = 1;
key_l = 1;
key_m = 1;
key_change = 1;
order = 'm'; //开机默认逐字切换功能
move = 0; //移动变量为0 从头开始
while (1)
{
if (key_u == 0) /*向上移动的按键 让模式为 ‘u’ ,从头开始*/
{
order = 'u';
move = 0;
}
if (key_d == 0) /*向下移动的按键按下 从头开始*/
{
order = 'd';
move = 0;
for (i = 0; i < 16; i++) //初始化要显示的缓存数组(复制过来)
{
show_temp[i * 2] = table1[hanzi_table_num - 1][i * 2];
show_temp[i * 2 + 1] = table1[hanzi_table_num - 1][i * 2 + 1];
}
}
if (key_r == 0) /*向右移动的按键按下 从头开始*/
{
order = 'r';
move = 0;
for (i = 0; i < 16; i++) //初始化要显示的缓存数组(复制过来)
{
show_temp[i * 2] = table1[hanzi_table_num - 1][i * 2];
show_temp[i * 2 + 1] = table1[hanzi_table_num - 1][i * 2 + 1];
zuoyou_temp[i] = table1[hanzi_table_num - 1][i * 2 + 32 + 1]; //以及关系到下一个汉字的后一半内容,也缓存过来 用于衔接上一个文字
}
}
if (key_l == 0) /*向左移动的按键按下 从头开始*/
{
order = 'l';
move = 0;
for (i = 0; i < 16; i++) //初始化要显示的缓存数组(复制过来)
{
show_temp[i * 2] = table1[hanzi_table_num - 1][i * 2];
show_temp[i * 2 + 1] = table1[hanzi_table_num - 1][i * 2 + 1];
zuoyou_temp[i] = table1[hanzi_table_num - 1][i * 2 + 32]; //以及关系到下一个汉字的前一半内容,也缓存过来 用于衔接上一个文字
}
}
if (key_m == 0) /*逐个字切换的按键按下 从头开始*/
{
order = 'm';
move = 0;
}
/*--------------------------------------------------------------------------------------------*/
if (key_change == 0) /*显示内容数组变化 按键按下 切换内容序号*/
{
move = 0;
hanzi_witch++;
if (hanzi_witch >= 3) hanzi_witch = 1;
if (hanzi_witch == 1) //1 是汉字数组 汉字3个 索引为1
{
hanzi_num = 8; /*汉字更改第3处*/
hanzi_table_num = 1;
}
if (hanzi_witch == 2) //2 是字符数组 页面4个 索引为2
{
hanzi_num = 6; /*特定数字更改第1处*/
hanzi_table_num = 2;
}
order = 'm'; //默认为 逐页变化的
while (key_change == 0); //等待按键松开
}
/*-------------------------------------------------------------------------------------------*/
for (num = 0; num < 16; num++) //显示处理 16*16图像 逐行显示 ,共显示16行
{
if (num < 8) //前8行
{
wordByt(Hang[num]);
wordByt(0xff);
}
else //后8行
{
wordByt(0xff);
wordByt(Hang[num - 8]);
}
if ((order == 'u') || (order == 'm')) //向上移动 和 逐字变化 时,直接计算从原始数据获取显示
{
wordByt(table1[hanzi_table_num - 1][2 * num + move * 2]);
wordByt(table1[hanzi_table_num - 1][2 * num + 1 + move * 2]);
}
if ((order == 'd') || (order == 'l') || (order == 'r')) //向下 向左 右 模式,显示处理后的缓存数组内容
{
wordByt(show_temp[2 * num]);
wordByt(show_temp[2 * num + 1]);
}
STB = 1; //输出锁存中的数据,下降沿 显示一行
STB = 0;
delay(2); // 延时一下
}
if (order == 'l') /*向左移动*/
{
if (++speed > 6) //速度控制(数字小速度快)
{
speed = 0;
move++; //移位 移动1列
for (i = 0; i < 16; i++) //数据处理
{
if (show_temp[i * 2 + 1] & 0x01 == 0x01) show_temp[i * 2] = ((show_temp[i * 2]) >> 1) | 0x80; //先向左移动一列 数组内容
else show_temp[i * 2] = ((show_temp[i * 2]) >> 1) & 0x7f;
if (zuoyou_temp[i] & 0x01 == 0x01) show_temp[i * 2 + 1] = ((show_temp[i * 2 + 1]) >> 1) | 0x80; //判断下一图像的一列,根据0或1插入上面移动1列后的数组里
else show_temp[i * 2 + 1] = ((show_temp[i * 2 + 1]) >> 1) & 0x7f;
zuoyou_temp[i] = zuoyou_temp[i] >> 1; //下一图像跟着移动1列
}
if (move % 8 == 0) //移动当前图像的8步之内 更新下一个图像的前一半内容到缓存数组里
{
if (move / 8 % 2 == 0) //上一边
for (i = 0; i < 16; i++)
{
zuoyou_temp[i] = table1[hanzi_table_num - 1][(move / 16 + 1) * 32 + i * 2];
}
if (move / 8 % 2 == 1) //下一边 //移动当前图像的8-15步 更新下一个图像的后一半内容到缓存数组里
for (i = 0; i < 16; i++)
{
zuoyou_temp[i] = table1[hanzi_table_num - 1][(move / 16 + 1) * 32 + i * 2 + 1];
}
}
if (move > 16 * hanzi_num) //判断是否完成一个数组数据
{
move = 0; //从头开始
for (i = 0; i < 16; i++) //复制数据到缓存数组中
{
show_temp[i * 2] = table1[hanzi_table_num - 1][i * 2];
show_temp[i * 2 + 1] = table1[hanzi_table_num - 1][i * 2 + 1];
zuoyou_temp[i] = table1[hanzi_table_num - 1][i * 2 + 32]; //以及关系到下一个汉字的前一半内容,也缓存过来 用于衔接上一个文字
}
}
}
}
if (order == 'r') /*向右移动*/
{
if (++speed > 6) //速度控制(数字小速度快)
{
speed = 0;
move++; //移位
for (i = 0; i < 16; i++) //先向右移动一个 显示数据的处理
{
temp = show_temp[i * 2] >> 7; // 移动根据后一半图像的1列数据,转换添加到右移1列后的前一半图像
if (temp & 0x01 == 0x01) show_temp[i * 2 + 1] = ((show_temp[i * 2 + 1]) << 1) | 0x01;
else show_temp[i * 2 + 1] = ((show_temp[i * 2 + 1]) << 1) & 0xfe;
temp = zuoyou_temp[i] >> 7; //根据下1个图像的前半部分的1列数据,判断添加到上1个图像的1列中
if (temp & 0x01 == 0x01) show_temp[i * 2] = ((show_temp[i * 2]) << 1) | 0x01;
else show_temp[i * 2] = ((show_temp[i * 2]) << 1) & 0xfe;
zuoyou_temp[i] = zuoyou_temp[i] << 1; //缓存也移动1列
}
if (move % 8 == 0)
{
if (move / 8 % 2 == 0) //上一边//移动当前图像的8步之内 更新下一个图像的上一半内容到缓存数组里
for (i = 0; i < 16; i++)
{
zuoyou_temp[i] = table1[hanzi_table_num - 1][(move / 16 + 1) * 32 + i * 2 + 1];
}
if (move / 8 % 2 == 1) //下一边//移动当前图像的8步之内 更新下一个图像的下一半内容到缓存数组里
for (i = 0; i < 16; i++)
{
zuoyou_temp[i] = table1[hanzi_table_num - 1][(move / 16 + 1) * 32 + i * 2];
}
}
if (move > 16 * hanzi_num) //判断是否完成一个汉字
{
move = 0; //从头开始
for (i = 0; i < 16; i++) //复制数据 从新开始
{
show_temp[i * 2] = table1[hanzi_table_num - 1][i * 2];
show_temp[i * 2 + 1] = table1[hanzi_table_num - 1][i * 2 + 1];
zuoyou_temp[i] = table1[hanzi_table_num - 1][i * 2 + 32 + 1]; //以及关系到下一个汉字的后一半内容,也缓存过来 用于衔接上一个文字
}
}
}
}
if (order == 'd') /*向下移动*/
{
if (++speed > 5) //速度控制(数字小速度快)
{
speed = 0;
move++; //移位
for (i = 14; i >= 0; i--) //缓存数据先向下移动一个
{
show_temp[(i + 1) * 2] = show_temp[i * 2];
show_temp[(i + 1) * 2 + 1] = show_temp[i * 2 + 1];
}
//第一行数据由下一个图像的最后一行数据填充
show_temp[0] = table1[hanzi_table_num - 1][(move / 16 + 2) * 32 - (move * 2) % 32];
show_temp[1] = table1[hanzi_table_num - 1][(move / 16 + 2) * 32 + 1 - (move * 2) % 32];
if (move > 16 * hanzi_num) //判断是否完成一个汉字
{
move = 0; //从头开始
for (i = 0; i < 16; i++) //复制数据,重新开始
{
show_temp[i * 2] = table1[hanzi_table_num - 1][i * 2];
show_temp[i * 2 + 1] = table1[hanzi_table_num - 1][i * 2 + 1];
}
}
}
}
if (order == 'u') /*向上移动 它的数组数据顺序符合向上的,所以数据不必处理*/
{
if (++speed > 5) //速度控制(数字小速度快)
{
speed = 0;
move++; //移位
if (move > 16 * hanzi_num) //判断是否完成一个汉字
move = 0; //从头开始
}
}
if (order == 'm') /*逐个字显示*/
{
if (++speed > 25) //速度控制(数字小速度快)
{
speed = 0;
move += 16; //移位 下一个图像
}
}
}
完整代码点开链接私信 免费 获取。
【iBot机器人工作室的个人空间-哔哩哔哩】 https://b23.tv/ryUWVKa