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

51单片机课程设计——led点阵广告牌程序设计上学期期末的课设题目是 led 点阵广告牌 当时的要求如下 1 能够显示不同字符的 LED 点阵广告牌 2 按键切换不同的显示效果 如闪烁 静止 平移等 3 按键切换不同的显示内容 4 能够显示图形或自定义字符 5 其他功能 创新部分 6 系统调试 分析 总结与功能实现 当时用的是我用是的普中科技的 STC89C51RD 的单片机 不过只要是 51 单片机 换哪个 51 内核的芯片都可

一、设计思路

#include  
     #include  
     #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; 

二、通过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 low R_CLK = 1; //片选 R_CLK = 0; //set dataline low } 
//点阵显示数组 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}; 

三、检测独立按键

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时回到最外层循环,之后回到刚才的循环重新从第一个文字开始显示。

//文字闪烁 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仿真

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/208273.html原文链接:https://javaforall.net

(0)
上一篇 2026年3月19日 上午11:58
下一篇 2026年3月19日 上午11:58


相关推荐

  • 马来西亚最大的电商平台_东南亚最受欢迎的跨境电商平台

    马来西亚最大的电商平台_东南亚最受欢迎的跨境电商平台一直以来,马来西亚电商市场几乎被Shopee和Lazada两大电商平台所统治,国际巨头占据主要市场。马来西亚电商平台TOP10中,Shopee和Lazada两大电商平台共占据了83.58%的网站流量,是马来电商入驻首选平台。然而直到2020年,Shopee超过了Lazada,拉开了距离,Shopee月均流量已达到Lazada的两倍以上。与此同时,马来西亚本土电商PGMall也在2020年的竞争中战胜Zalora与Lelong,稳固了他在马来西亚前三甲的地位。目前,无需注册马来西亚本地公司即可直接在

    2022年10月5日
    5
  • UTF-8和GBK有啥区别?

    UTF-8和GBK有啥区别?粉丝求助 如何解决 把编辑器和浏览器的字符集统一设置成 utf 8 或者 gbk 即可 主要区别 1 GBK 是在 bai 国家标准 GB2312 基础上扩容后兼容 GB2312 的标准 好像还不 du 是国家标准 zhiGBK 编码 dao 专门用来解决中文编码的 是双字节的 不论中英文都是双字节的 2 UTF 8 编码是用以解决国际上字符的一种多字节编码 它对英文使用 8 位 即一个字节 中文使用 24 位 三个字节 来编码 对于英文字符较多的论坛则用 UTF 8 节省空间 另外 如果是外国

    2026年3月17日
    2
  • 用PMML实现机器学习模型的跨平台上线

    用PMML实现机器学习模型的跨平台上线在机器学习用于产品的时候,我们经常会遇到跨平台的问题。比如我们用Python基于一系列的机器学习库训练了一个模型,但是有时候其他的产品和项目想把这个模型集成进去,但是这些产品很多只支持某些特定的生产环

    2022年8月5日
    7
  • python中bool()函数

    python中bool()函数python中bool()函数

    2022年5月29日
    51
  • 一文带你了解常见的数据指标都有哪些【数据分析】[通俗易懂]

    一文带你了解常见的数据指标都有哪些【数据分析】[通俗易懂]为了进一步提升自己分析业务的能力,首先得先了解好在日常业务分析当中往往会用到那些数据指标。接下来我给大家整理了常见的一些数据指标,建议收藏后慢慢阅读。目录用户获取渠道到达量渠道转化率渠道ROI日应用下载量日新增用户数用户获取成本一次会话用户数用户活跃活跃用户PV和UV用户会话次数用户访问时长功能使用率用户留存留存率用户流失率退出率和跳出率市场营销用户生命周期用户生命周期价值用户忠诚指数用户流失指数用户价值指数结束语用户获取渠道到达量这个俗称曝光量,如果在CSDN有发过博客的朋友应该知道“展现量”这

    2022年5月10日
    56
  • 标志寄存器操作

    标志寄存器操作文章目录 0x01 常见操作指令 0x02 标志寄存器一 ZF 标志二 PF 标志三 SF 标志四 CF 标志五 OF 标志六 DF 标志位和串传送指令 0x01 常见操作指令 在 CISC 中对于标志寄存器存在一些指令对标志寄存器操作 常见的有 LAHF SAHF PUSHF POPF LAHF 指令可以将标志寄存器的低八位送入 AH 中 即将标志寄存器中的 SF ZF AF PF CF 这五个标志位传送到 AH 的对应位置上 标志位寄存器位置如下 外链图片转存失败 源站可能有防盗链机制 建议将图片保存

    2026年3月18日
    2

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号