**
前言
**
我借同学的光驱把光盘中的文件拷出来后,开始尝试玩一玩单片机。
目前做的比较难的是8X8Led点阵的使用,元件感觉有点多啊。
我用的是普中科技HC6800-ES V2.0的开发板,很多人说什么普中垃圾,我觉得还是他们自己C语言和数电等知识还没弄懂之类的吧。还有老师的教程到8X8LED点阵这里,很多人说有问题,我甚至见过一篇博客写这个教程但是在结果后写:没有显示… dots…
也是,视频里说了有个地方需要短接的,至于是哪里,请往下看!
像以往一样,做个预想,这篇结束时,可以尽量在LED点阵上显示文字等。
**
8X8LED阵列
**
我用的单片机中的LED阵列是左边这种。
行,是D7~D0,而列是P07 ~ P00。
如果想点亮哪盏灯,需要找到那盏灯对应的行和列。行输出1,而对应的列输出0就行了。原理是相当简单。
比如说我想点亮左上角第一个LED,行输出为 0x80 (D7~D0 = 1000 0000),列输出为 0x7f (P07 ~P00 = 0111 1111) 。
**
**
74HC595是中间那片。
74HC595是硅结构的CMOS器件。兼容低电压TTL电路,遵循JEDEC标准。具有8位移位寄存器和一个存储寄存器,三太输出功能。
而两个寄存器有不同的时钟,但都是根据上升沿触发。
74HC595原理和使用
单片机芯片通过P35P34P36三个IO口来控制D0~D7的输出。
当然如果不用74HC595而直接让LED点阵连接单片机也可以,但这里不谈那个。
值得注意的一点是,OE这个口为低电平有效。如果其有效,那么输出就有效。这个有JOE这个开关来控制。单片机短接片一般没被操作时,短接片是OE短接VCC,为了让OE有效,应该让其短接GND。
同一种芯片的引脚的名字可能不同,但是引脚是一样的。
当我想要使用这块芯片实现,串行输入并行输出的时候,
电源口就不说了,输入口(SER)准备好输入数字(8个)的第一个。两个时钟信号(SRCLK、RCLK)初始化为0。(非SRCLR)复位口为1(不复位)。JOE段子接GND,让OE为低电平(输出有效)。
移位寄存器时钟信号(SRCLK)出现上升沿,串行输入口输入一个数字
第二步运行8次,8次后,需要输入的8位数字就都放在了对应的位置上
存储寄存器时钟信号(RCLK)出现上升沿,8个并行输出口同时输出。
点亮阵列左上角的LED灯
sbit类型是取端口(一位),将其命名为一个变量。
还需要注意的是,每次编程直接使用SER、data、RCLK是不行的,容易出现重定义。每次自己还是取另类一点的变量名。
#include #include typedef unsigned int u16; typedef unsigned char u8; sbit My_SRCLK = P3^6;//移位寄存器时钟信号 sbit My_RCLK = P3^5;//存储寄存器时钟信号 sbit My_SER = P3^4;//串行输入口 void Hc595_SendByte(u8 My_data){ u8 a; My_SRCLK = 0; My_RCLK=0; for(a=0;a<8;++a){ My_SER = My_data>>7; //每次只输入一位 My_data<<=1; My_SRCLK = 1;//出现上升沿 串行输入一位 _nop_();//延迟一毫秒(一个指令周期) _nop_();//延迟一毫秒(一个指令周期) My_SRCLK = 0; } My_RCLK=1;//出现上升沿 并行输出8位 _nop_(); _nop_(); My_RCLK = 0; } void main(){ Hc595_SendByte(0x80);//行输入 1000 0000 P0 = 0x7f;//列输入 0111 1111 while(1){} } 显示结果: 如果JOE与GND没短接的话会出问题。 去掉JOE处的短接片后,如果用手指触碰接口的针多次,LED阵列的那盏灯会灭(如果按复位按钮,等也会灭)。解决方法是按USB口旁边的开关重启就行了。 显示数字零 普中HC6800-ES V2.0开发板资料常用辅助开发软件文字取模软件 里有一个取字模软件,可以选择特定的阵列,然后处理后得到自己的位选和段选分别的十六进制。 这里准备一个:链接:https://pan.baidu.com/s/1yKKo6xzj9cvhLAgz6MTz4Q 提取码:s297 复制这段内容后打开百度网盘手机App,操作更方便哦 打开软件后,新建8X8的图像,模拟动画,放大格点,用鼠标在白色窗口中点上自己想要的,取模方式,C51 如果选择的是纵向(行选),那么列选是通用的 0x7f,0xbf,0xdf,0xef,0xf7,0xfb,0xfd,0xfe 如果选择的是横向(列选),那么行选是通用的 0x80,0x40,0x20,0x10,0x08,0x04,0x02,0x01 更改纵向还是横向在参数设置-》其他选项里 1.为了显示正确,必须先选通用的,再选另外一边 2.一般另外一边在显示和延迟后需要消隐 #include #include typedef unsigned int u16; typedef unsigned char u8; sbit My_SRCLK = P3^6; sbit My_RCLK = P3^5; sbit My_SER = P3^4; u8 led_wei[]={ 0x7f,0xbf,0xdf,0xef,0xf7,0xfb,0xfd,0xfe }; u8 led_duan[]={ 0x00,0x00,0x3e,0x41,0x41,0x41,0x3e,0x00 }; //延迟 void delay(u16 i){ while(i--){} } void Hc595_SendByte(u8 My_data){ u8 a; My_SRCLK = 0; My_RCLK=0; for(a=0;a<8;++a){ My_SER = My_data>>7; My_data<<=1; My_SRCLK = 1; _nop_(); _nop_(); My_SRCLK = 0; } My_RCLK=1; _nop_(); _nop_(); My_RCLK = 0; } void main(){ u8 a=0; while(1){ P0=0x7f; for(a=0;a<8;++a){ P0=led_wei[a]; Hc595_SendByte(led_duan[a]); delay(100); Hc595_SendByte(0x00);//消隐 } } } 显示结果: 同样如果不短接JOE和GND,还是会出错(输出无效)。但是不碰JOE端子,显示还是正常的。 有这么个有趣的结果,如果不短接JOE和GND,用手指按着JOE端子VCC和JOE上。 手指接触VCC和JOE时,输出无效,一部分灯就没亮(不是灭了)。 当手指没有接触时,又恢复正常(一部分)。 然后陷入长久的循环中。 ** Point_Game ** 64个灯中,我打算选一个灯做Point Bird,这个Bird只会上升和下降。会有障碍从右边生成并移向左边,如果Bird撞到障碍或掉了下来,那么就判断为输。 一共3个模块, keyproc : 独立按键的控制 show:列选和行选 logic:游戏初始化,倒计时,移动,显示等 keyproc.h #ifndef _KEY_PROC_H_ #define _KEY_PROC_H_ #include"reg52.h" #include"intrins.h" typedef unsigned char u8; typedef unsigned int u16; sbit k1 = P3^1;//RXD //sbit k2 = P3^0;//TXD static int key = 0; void delay(u16 i); u8 Key_Process(); void Key_Zero(); #endif keyproc.c #include"keyproc.h" void delay(u16 i){ while(i--){} } void Key_Zero(){ key = 0; } u8 Key_Process(){ if(k1==0){ delay(1000); if(k1==0)key=~key; delay(1000); } return key; } 跨文件不要直接使用和传递全局变量,鉴于C语言的特性你也传递不了。跨文件只能用函数传递和返回变量 。(其实是可以的) 传递跨文件变量看我另一篇文章:C51:解决ERROR L104: MULTIPLE PUBLIC DEFINITIONS show.h #ifndef _SHOW_H_ #define _SHOW_H_ #include"keyproc.h" sbit g_SRCLK = P3^6;//移位寄存器时钟 sbit g_RCLK = P3^5;//存储寄存器时钟 sbit g_SER = P3^4;//串行输入 void ChooseRows(u8 iData); void ChooseCols(u8 iData); #endif show.c #include"show.h" /* LED阵列 P07 P06 P05 P04 P03 P02 P01 P00 D7 D6 D5 D4 D3 D2 D1 D0 */ void ChooseRows(u8 iData){ u8 a ; g_RCLK = 0; g_SRCLK = 0; for(a=0;a<8;++a){ g_SER = iData >> 7; iData<<=1; g_SRCLK = 1; _nop_(); _nop_(); g_SRCLK = 0; } g_RCLK = 1; _nop_(); _nop_(); g_RCLK = 0; } void ChooseCols(u8 iData){ P0 = iData; } logic.h #ifndef _LOGIC_H_ #define _LOGIC_H_ #include"show.h" #include"stdlib.h" #include"keyproc.h" //Point Bird的位置 static u8 bird_y = 4; //通用的列选 static u8 xdata led_cols[ ]={ 0x7f,0xbf,0xdf,0xef,0xf7,0xfb,0xfd,0xfe }; //特殊字符 static u8 xdata led_numbers_rows[6 ][8 ]={ 0x00,0x00,0x3e,0x41,0x41,0x41,0x3e,0x00, //0 0x00,0x00,0x22,0x42,0xFE,0x02,0x02,0x00, //1 0x00,0x21,0x43,0x45,0x49,0x31,0x00,0x00, //2 0x00,0x00,0x42,0x81,0x89,0x89,0x76,0x00, //3 0x04,0x02,0x01,0x02,0x04,0x08,0x10,0x20, //¡Ì 0x81,0x42,0x24,0x18,0x18,0x24,0x42,0x81 //¡Á }; //障碍 static u8 xdata led_walls_rows[ ] = { 0xF0,0xE1,0x07,0x1C,0x33,0x70,0x84,0xCC }; //显示数组 static u8 xdata leds_no_bird[8]={0}; static u8 xdata leds[8]={0}; void Init_Game(); void Move(); void Display(); void Lose(); #endif logic.c #include"logic.h" void Init_Game(){ u8 a,b,c; //初始化显示数组 for(a=0;a<8;++a) leds[a]=0; //初始化Point Bird的位置 bird_y = 4; //按k1启动游戏 while(1) if(Key_Process()) break; Key_Zero(); //倒计时 √ 3 2 1 0 for(a=0;a<5;a++){ for(b=0;b<100;b++)//ÏÔʾÎȶ¨ for(c=0;c<8;c++){ ChooseCols(led_cols[c]); ChooseRows(led_numbers_rows[4 - a][c]); delay(100); ChooseRows(0x00); } } } void Move(){ static u8 c = 0; u8 a,temp; u8 n = rand()%8; //Point Bird的移动 u8 value = Key_Process(); Key_Zero(); if(value){ if(bird_y ++ >= 7)bird_y = 7; } else bird_y--; //障碍移动 for(a=0;a<7;++a){ leds_no_bird[a]=leds_no_bird[a+1]; } leds_no_bird[7] = 0x00; //每隔3个生成一条障碍,并放入数组 if(c++ ==4 ){ leds_no_bird[7] |= led_walls_rows[n]; c=0; } ///复制 for(a=0;a<8;++a) leds[a]=leds_no_bird[a]; //最后处理Point Bird temp = leds[1]; temp |= (1< if(temp==leds[1]){ while(1) Lose();//× } else leds[1] = temp; } void Display(){ u8 a,b; for(b=0;b<100;b++) //使显示稳定 for(a=0;a<8;++a){ ChooseCols(led_cols[a]); ChooseRows(leds[a]); delay(100); ChooseRows(0x00); } } void Lose(){ u8 a,b; for(b=0;b<100;b++)//使显示稳定 for(a=0;a<8;++a){ ChooseCols(led_cols[a]); ChooseRows(led_numbers_rows[5][a]); delay(100); ChooseRows(0x00); } } main.c #include"logic.h" void main(){ Init_Game(); while(1){ Move(); Display(); } } 显示效果:
上一篇:单片机实验——8X8LED点阵显示技术(二)
下一篇:基于51单片机个8位数码管的简单拨号键盘
推荐阅读最新更新时间:2024-11-13 22:02
设计资源 培训 开发板 精华推荐
- XRT83SL38EVAL,基于 XRT83SL38 线路接口单元的评估系统
- 40p最小stc89c52单片机下载器
- [DCDC]SY7304核心,4A升压可调模块
- SI1000DK,开发套件由主板和基于Si1000 8051 MCU的子卡组成
- LT3091ER 正输出电流监视器的典型应用
- 使用 NXP Semiconductors 的 TDF8599B 的参考设计
- icebreaker++ :icebreaker FPGA 板,升级了 ECP5
- L7805C负输出电压电路的典型应用
- #第七届立创电赛#USB电流测量
- NCD9830GEVB,基于 NCD9830 8 位、8 通道 ADC 的评估板