上学期期末的课设题目是led点阵广告牌,当时的要求如下:
(1)能够显示不同字符的LED点阵广告牌;
(2)按键切换不同的显示效果(如闪烁,静止,平移等);
(3)按键切换不同的显示内容;
(4)能够显示图形或自定义字符;
(5)其他功能(创新部分);
(6)系统调试、分析、总结与功能实现。
当时用的是我用是的普中科技的STC90C51RD+的单片机,不过只要是51单片机,换哪个51内核的芯片都可以,只要电路和程序匹配就可以。
我用的那款普中科技的51单片机可以直接连线决定线路的布置,不需要自己去重新焊一个电路板。
然后我根据任务要求连接了电路,写了对应的程序,还有proteus仿真。
另外,觉得有趣可以点个赞;有什么有趣的想法可以评论一下,我感兴趣的话会做一下。

一、设计思路

首先是P1连接8个独立按键,P3.4,P3.5,P3.5三个I/O口通过模拟SPI(51单片机没有硬件的SPI总线控制器)控制led点阵。
下面是包含头文件,定义独立键盘,选用模拟SPI的三个I/O口的程序内容,其中也包括重定义函数变量的内容,可以有效地减少编写程序时的负担。

#include <reg51.h>
#include <intrins.h>#define  GPIO_KEY P1  //独立键盘用P1口//--重定义函数变量--//
#define uchar unsigned char
#define uint  unsigned int
#define ulong unsigned long//--定义SPI要使用的 IO--//
sbit MOSIO = P3^4;
sbit R_CLK = P3^5;
sbit S_CLK = P3^6;

之后设计显示在led点阵上的文字,符号。(当时设计的是我和组员的名字还有一些自定义的符号)。
要实现的效果是:打开电源后按下K1可以一堆汉字会从上而下移动,按下K2汉字会闪烁显示(闪烁显示就是显示一个字零点几秒钟,然后先后显示其他字),按下K3是我自定义的那些字符闪烁显示,然后进入每个功能后都可以按下K8退出这个功能,之后可以按下K1,K2或K3进入这三个功能。

二、通过I/O口模拟SPI发送数据

(1)传输数据函数与对应模块的仿真

以下是普中科技单片机自带的通过I/O口模拟SPI发送数据的函数,因为有配套的字模生成软件,所以对这个部分我就不写太多东西了,有想要字模软件的可以在文末的百度网盘链接自己下载。

//通过74HC595发送四个字节的数据
void HC595SendData(uchar BT3, uchar BT2,uchar BT1,uchar BT0)
{  uchar i;//--发送第一个字节--//for(i=0;i<8;i++){MOSIO = BT3 >> 7 ;  //从高位到低位BT3 <<= 1;S_CLK = 0;S_CLK = 1;     }//--发送第二个字节--//for(i=0;i<8;i++){MOSIO = BT2 >>7;      //从高位到低位BT2 <<= 1;S_CLK = 0;S_CLK = 1; }//--发送第三个字节--//for(i=0;i<8;i++){MOSIO = BT1 >> 7;     //从高位到低位BT1 <<= 1;S_CLK = 0;S_CLK = 1; }//--发送第四个字节--//for(i=0;i<8;i++){MOSIO = BT0 >> 7;     //从高位到低位BT0 <<= 1;S_CLK = 0;S_CLK = 1;}//--输出--//R_CLK = 0; //set dataline lowR_CLK = 1; //片选R_CLK = 0; //set dataline low
}

这个部分使用了4个74HC595,下面是对应的仿真图片,里面RX8是排阻,可以不要,我这个图片里有是因为普中科技给的原理图里有这个排阻,我做仿真的时候直接照猫画虎画上去了,其实完全不需要,普中的板子上有这个是因为要把各个模块分开,连接的时候用排线连接就可以,POS和NEG可以理解为16 * 16LED点阵的行和列。

LED点阵要求是16 * 16的,需要使用4个8 * 8的LED点阵组合起来,在proteus中的制作方法在 这里,我拼接16 * 16LED点阵是按照这个做的,之后按照普中给的原理图写引脚的网络标号,在proteus对应着标了一遍(注意:这个图的网络标号是错的),然后仿真出来的结果有问题,我重画了很多次都有问题,可能是原理图有问题,也可能是别的原因,使用普中科技的板子的朋友可以注意一下,我按照这个原理图画仿真怎么画也不对,最后干脆16个行分别标上POS1到POS16,16个列标上NEG1到NEG16结果对了。
下面是最终可以使用的点阵仿真图:

下面是原理图(照着画网络标号有问题,其他的没有问题):

下面是照着原理图画的仿真(画了两次都不能用,出现的图案与预期不符):

(2)要传输的数据

传输的数据需要选择一些汉字,字符或者自定义符号。
以下为一些姓氏和自定义的字符对应的数组,tab0是用来确定显示位置的,下面会提到。

//点阵显示数组
uchar code tab0[] = {0x00, 0x01, 0x00, 0x02, 0x00, 0x04, 0x00, 0x08, 0x00, 0x10, 0x00, 0x20, 0x00, 0x40, 0x00, 0x80,0x01, 0x00, 0x02, 0x00, 0x04, 0x00, 0x08, 0x00, 0x10, 0x00, 0x20, 0x00, 0x40, 0x00, 0x80, 0x00};
//--张--//
uchar code tab1[] = {128,1,191,49,176,49,176,25,176,13,190,7,134,
1,230,255,134,7,190,13,176,13,176,25,176,49,176,103,158,195,140,1};
//--王--//
uchar code tab1[] = {0,0,252,31,128,0,128,0,128,0,128,0,128,0,248,
15,128,0,128,0,128,0,128,0,128,0,254,63,0,0,0,0};
//--李--//
uchar code tab2[] = {128,0,128,0,254,63,160,2,144,4,136,8,6,48,240,
3,0,1,128,0,254,63,128,0,128,0,224,0,0,0,0,0};
//--任--//
uchar code tab3[] = {16,0,16,28,208,3,8,2,8,2,12,2,10,2,232,63,8,2,
8,2,8,2,8,2,8,2,200,31,0,0,0,0};
//--徐-//
uchar code tab4[] = {16,2,16,2,8,5,132,8,82,16,176,47,8,2,12,2,202,
31,8,2,72,18,72,34,40,34,136,3,0,0,0,0};
//--杨--//
uchar code tab5[] = {24,0,152,63,24,24,24,12,127,6,24,3,156,255,60,
219,126,219,126,219,155,217,152,205,216,204,120,198,24,123,152,49};
//--桃心--//
uchar code xin[] = {0,0,28,56,252,63,254,127,255,255,207,243,135,
225,7,224,15,240,30,120,60,60,120,30,240,15,224,7,192,3,128,1};
//--五角星--//
uchar code char1[] = {128,1,128,1,192,3,192,3,192,3,96,6,127,254,6,
96,28,56,48,12,48,12,152,27,248,30,56,28,12,48,0,0};
//--圆--//
uchar code char2[] = {0,0,224,7,120,30,28,56,28,56,14,112,14,112,14,
112,14,112,14,112,28,56,28,56,120,30,224,7,0,0,0,0};
//--三角--//
uchar code char3[] = {0,0,128,1,128,1,192,3,192,3,96,6,96,6,48,12,48,
12,24,24,24,24,12,48,12,48,254,127,0,0,0,0};
//--菱形--//
uchar code char4[] = {128,0,64,1,32,2,16,4,8,8,4,16,2,32,1,64,2,32,
4,16,8,8,16,4,32,2,64,1,128,0,0,0};
//--箭头--//
uchar code char5[] = {0,0,0,0,0,0,0,2,0,4,0,8,0,16,0,32,126,64,0,
32,0,16,0,8,0,4,0,2,0,0,0,0};

之后会将要显示的数组在混合起来成为一个新的指针数组,这个数组是用来直接在点阵显示的函数中使用的,*p的指针数组中多余很多是被我删掉的名字,只留下了姓。

uchar *p[] = {tab1, tab2, tab3, tab4, tab5, tab6, tab7, tab8,tab9, tab10, tab11, tab12, tab13,  tab14};
uchar *c[] = {char1, char2, char3, char4,char5};

三、检测独立按键

主函数中首先是while(1),无限循环,只要没有检测到键值(即独立按键中有任意键被按下),就一直循环,并且执行清屏的程序(即调用标题二中的传输数据功能,分别传输0xff,0xff,0,0四个数据)如果检测到键值就进入对应的功能中,进入每个功能对应的函数。
以下是主函数内容:

void main(void)
{while(1){HC595SendData(0xff,0xff,0,0); //清屏    keyNum=Key_Scan();     //读取键值switch (keyNum){case(0xFE) :    //返回按键K1的数据translation();//文字从上到下平移break;case(0xFD) :   //返回按键K2的数据twinkle1();        //文字闪烁break;case(0xFB) :      //返回按键K3的数据twinkle2();        //符号闪烁break;
//          case(0xF7) :      //返回按键K4的数据
//              ;
//              break;
//          case(0xEF) :      //返回按键K5的数据
//              ;
//              break;
//          case(0xDF) :      //返回按键K6的数据
//              ;
//              break;
//          case(0xBF) :      //返回按键K7的数据
//              ;
//              break;case(0x7F) :    //返回按键K8的数据HC595SendData(0xff,0xff,0,0);              //清屏break;default:break;}           }
}

读取键值

前面有提到定义P1为独立按键,即程序中的GPIO_KEY,当独立按键按下时GPIO_KEY != 0xFF,这时消除抖动(即延时十毫秒)再检测一次,如果检测为按下按键则将键值保存到keyValue中,之后松开按键或500ms后仍未松开按键,都会将读取到的键值返回。

unsigned char Key_Scan()
{unsigned char keyValue = 0 , i; //保存键值//--检测按键1--//if (GPIO_KEY != 0xFF)     //检测按键K1是否按下{Delay10ms(1);  //消除抖动if (GPIO_KEY != 0xFF)    //再次检测按键是否按下{keyValue = GPIO_KEY;i = 0;while ((i<50) && (GPIO_KEY != 0xFF))    //检测按键是否松开{Delay10ms(1);i++;}}}return keyValue;   //将读取到键值的值返回
}

四、具体功能

(1)文字自上而下移动

K1按键对应的是文字自上而下移动的功能,以下为对应的程序,其中内嵌的第三个循环for(k = 0; k < 16; k++)中k从0到15遍历,对应LED点阵的1到16行,内嵌的第二个循环for(ms = 10; ms > 0; ms–)决定显示同一个内容的时间,内嵌的第一个循环为while(keyNum!=0x7F),只要keyNum!=0x7F一直成立,就无限循环。

i.如何实现随时按下K8退出该功能,重新回到主函数

在最小的循环中完成内嵌一个检测键值的程序keyNum=Key_Scan();然后判断是否为0x7F(即按下K8时的键值),若是则退出该循环,回到第二个循环,第二个循环中也有判断键值是否为K8的程序,同理,若是,回到第一个循环,while(keyNum!=0x7F)同样会判断键值是否为0x7F,若不是则退出循环,回到主函数。

ii.如何实现文字从上而下移动

刚进入这个功能还未进入循环时,赋值j=0(如果这里不赋值j=0也可以,只是下次进入这个功能会接着这次结束时显示的图像继续向下平移),在内嵌的第三个循环,也就是最小的的那个循环中给LED点阵发送数据,且是一次发送一行数据,循环16次,每次k+1即可显示全整个LED点阵,k加到16时退出最小的循环,第二个循环for(ms = 10; ms > 0; ms–)决定进入最小循环的次数即显示的时间,显示完规定的时间后,退出第二个循环,回到第三个循环,j+1,之后再进入最小循环时发送的前两位数据对应的指针数组中的位置会各自加2j,即显示的文字或字符向上移动一位,最下方空缺出来的一行会由下一个文字或字符的第一行代替,之后同理,则形成了文字向上移动的效果,一个字需要16行,从0开始,当j=15要显示的文字或字符数量时,再令j=0,重新从第一个字开始显示。

以下是文字移动的程序:

//文字由上而下平移
void translation()
{j=0;while(keyNum!=0x7F){for(ms = 10; ms > 0; ms--)   //移动定格时间设置{for(k = 0; k < 16; k++)    //显示一个字{                            HC595SendData(~(*(p[0] + 2*(k+j) + 1)),~(*(p[0] + 2*(k+j) )),tab0[2*k],tab0[2*k + 1]); //因为字模软件取的数组是高电平有效,所以列要取反     keyNum=Key_Scan();if(keyNum==0x7F)break;}          HC595SendData(0xff,0xff,0,0);                                          //清屏 if(keyNum==0x7F)break;            }   j++;if(j == (14*15) ){j = 0; }}}

以下是文字移动的效果(这时第一个字已经消失了近一半,下一个字也显示出一小半,分别是“王”字和“李”字):

(2)文字闪烁显示

i.如何实现随时按下K8退出该功能,重新回到主函数

与文字从上而下移动的功能同理,只不过文字闪烁功能有四个循环,比文字移动多一个,同样是最小循环中检测键值,若检测到keyNum==0x7F,则逐级退出,最后返回主函数。

ii.如何实现文字闪烁显示

与文字移动有些类似的地方,在最小的循环中发送数据从LED点阵第一行显示到最后一行,上一级循环决定最小循环一共运行几次,即显示一个字的时间,再上一级循环中每次i+1决定显示下一个文字,当i=14时回到最外层循环,之后回到刚才的循环重新从第一个文字开始显示。

第二个循环中有多少要显示的文字,就循环多少次,例如我原先共设计了14个文字,则 for(i = 0; i < 14; i++) 中i<14。
以下是文字闪烁的程序:

//文字闪烁
void twinkle1()
{while(keyNum!=0x7F){for(i = 0; i < 14; i++)     //总共14个字{for(ms = 50; ms > 0; ms--) //显示50次,即肉眼可识别的停留时间{for(k = 0; k < 16; k++)            //显示一个字{                            //--因为字模软件取的数组是高电平有效,所以列要取反--//HC595SendData(~(*(p[i] + 2*k + 1)),~(*(p[i] + 2*k )),tab0[2*k],tab0[2*k + 1]); keyNum=Key_Scan();if(keyNum==0x7F)break;}HC595SendData(0xff,0xff,0,0);              //清屏    if(keyNum==0x7F)break;                }if(keyNum==0x7F)break;}}
}

以下是文字闪烁的效果,一瞬间只显示一个文字:

(3)符号闪烁显示

其原理与文字闪烁显示完全相同,只不过这个程序里包含的指针数组里的全是自定义的符号。

以下是符号闪烁的程序:

//符号闪烁
void twinkle2()
{while(keyNum!=0x7F){for(i = 0; i <5; i++)       //总共5个字{for(ms = 50; ms > 0; ms--)  //显示50次,即肉眼可识别的停留时间{for(k = 0; k < 16; k++)            //显示一个字{                            //--因为字模软件取的数组是高电平有效,所以列要取反--//HC595SendData(~(*(c[i] + 2*k + 1)),~(*(c[i] + 2*k )),tab0[2*k],tab0[2*k + 1]); keyNum=Key_Scan();if(keyNum==0x7F)break;}HC595SendData(0xff,0xff,0,0);              //清屏if(keyNum==0x7F)break;}if(keyNum==0x7F)break;}}
}

以下是符号闪烁的效果,一瞬间只显示一个自定义符号:

(4)创新部分

做这个程序的时候快要期末考试了,就没有费心思去做创新部分,但其实很简单,例如,可以把符号也弄成从上而下移动的,可以一会儿闪烁一会移动,比如把要显示的东西横置过来,然后闪烁显示一个人的名字,之后移动显示I LOVE YOU.甚至如果有无源蜂鸣器的话,还可以在显示的同时放首歌。

五、proteus仿真

下面是我用proteus做的仿真,仿真效果就不放了,就是那个LED点阵上显示之前在单片机上的LED点阵相同的东西罢了。

PS:字模软件网盘链接:
链接:https://pan.baidu.com/s/1xrshrLyE3dNWbLnDDi8TxQ
提取码:j9u8

51单片机课程设计——led点阵广告牌程序设计相关推荐

  1. 温度报警程序c语言设计,51单片机课程设计:基于DS18B20的温度报警器

    51单片机课程设计:基于DS18B20的温度报警器 本程序用于读取DS18B20温度,同时具备报警功能,工程分为3个文件,main.c.temp.c.temp.h,经本人修改部分代码,适用于吉林农业大 ...

  2. 51单片机课程设计:基于DHT11的温湿度报警器

    51单片机课程设计:基于DHT11的温湿度报警器 本程序适用于51系列单片机,主要用于读取DHT11温湿度模块数值,显示在数码管上,同时还具备温湿度报警功能,当超出预设值,蜂鸣器报警,可在吉林农业大学 ...

  3. 8155与单片机c语言设计,51单片机课程设计报告-基于8155的8LED显示电子码表设计.doc...

    51单片机课程设计报告 --基于8155的8LED显示电子码表设计 实验目的 本次课程设计是基于51单片机在理论课程的基础上,通过电路设计.理论计算.实际编程.调试.测试.分析查找故障,解决在实际设计 ...

  4. 51单片机课程设计《三路步进电机控制》

    说明:最近抽出了几天时间完成了单片机的课程设计,用了51单片机做了三路步进电机控制器,美名其曰3d打印机控制器(其实是瞎搞的,与3D打印机毫无关系),因为单片机课程设计是在大四上学期,与考研复习时间冲 ...

  5. 【51单片机】MAX7219 LED点阵GUI设计

    文章目录 一.主要功能 二.硬件资源 1.硬件准备 2.硬件连接 三.软件设计 1.软件结构 2.主要代码 四.实验现象 联系作者 一.主要功能 LED点阵显示初始信息,可通过K3键切换显示模式,可实 ...

  6. 单片机课设-LED点阵广告牌设计

    单片机课设系列文章-2-LED点阵广告牌设计   文章目录  

  7. 51单片机课程设计——利用51单片机的定时器设计一个时钟论文

    计科在读,分享自己做过的作业,欢迎指正,有需要课程设计论文的可以私信我 摘要 单片机是一种数字集成电路芯片,是指集成在一块芯片上的微型计算机.一个比较完整的单片机应该包括微处理器(CPU). 存储器( ...

  8. 51单片机学习:LED点阵实验(显示图像)

    实验名称:LED点阵实验(显示图像) 接线说明:     实验现象:下载程序后,8*8LED点阵显示心形 注意事项:LED点阵旁的J24黄色跳线帽短接到GND一端                   ...

  9. 51单片机课程设计 || 基于AS608模块的指纹锁

    知乎:Fragtex CSDN: 川明_Fragtex 代码 代码速览: 源码 [闲鱼]https://m.tb.cn/h.U1SDh0Z?tk=npyX2Dqp114 CZ0001 「我在闲鱼发布了 ...

  10. c语言c51单片机点亮8个灯,单片机课程设计-8个LED灯来回点亮

    <单片机课程设计-8个LED灯来回点亮>由会员分享,可在线阅读,更多相关<单片机课程设计-8个LED灯来回点亮(20页珍藏版)>请在人人文库网上搜索. 1.目录第一章 绪论-3 ...

最新文章

  1. seq2seq与Attention机制
  2. 如何在7分钟内黑掉40家网站?
  3. 你这辈子可能都不需要看《计算机程序设计艺术》了!
  4. 【剑指offer】找出数组中出现一次的两个数
  5. 实现分页的通用存储过程
  6. 云电脑是什么_云电脑和我们现在平时用的电脑有什么区别?
  7. java面板换一个斜的圆形_java – 如何从底部设计圆形视图?
  8. 关于IT测试中的一些问题。
  9. jQuery、Ajax,DataTable数据如何转换成Json格式
  10. 基于springBoot的薪资管理系统
  11. 国民生产总值饼状图_预期寿命和国内生产总值
  12. mac 上的android 模拟器下载地址,在MAC上运行Android手机模拟器
  13. lisp 焊接符号标注_焊接符号标注及表示方法
  14. Android 在一个APP内打开另一个APP
  15. Mono.Cecil - 0.6
  16. 【巡店软件系统开发】2-1 WEB软件宣传网站
  17. 跳动公差与其他几何公差(一)
  18. JUR 项目评级:BB ,展望稳定 | TokenInsight
  19. 个人所得税计算以及个人所得税专项扣除相关信息
  20. maya python教程下载_[转载]技术教程-MayaPython教程四之实战篇

热门文章

  1. 广西农业职业技术学院计算机,学科分类与代码-广西农业职业技术学院.doc
  2. java考试知识点整理
  3. Win10下配置IIS并调试ASP程序
  4. 接口测试之Postman使用全图文指南(原来使用Postman测试API接口如此简单)
  5. linux操作系统常用命令
  6. PHP SQL注入攻击与防御
  7. 天翼校园客户端linux,GitHub - YianAndCode/f-surfing: 佛大广东天翼校园客户端在 Linux 下的解决方案...
  8. 亚马逊云科技携海信集团打造全球服务实践案例标杆
  9. 社会工程学之ip获取和定位
  10. MySQL 递归查询