下面的各个标题中的内容都是按照文档及各渠道的学习(主要看的是B站的江科大自化协)查询而记录的不同模块的最基本原理,没有多余的废话,一看就明白,每个实验都是上电通过OK的。由于复杂的操作都是由简单组合而成的,因此像网上的那些教程,比如跑马灯,动态数码管显示,本文均未给出具体代码,因为知道了如何去控制硬件,那上述操作就只需要处理代码逻辑就行了。
所有的实验,原理都是基于单片机STC89C516,同系列的其他单片机可能会有细节上的不同,可自行查询文档,原理基本都是相同的。同时,文章部分细节未记录,比如74H245的数据传送方向由DIR引脚的电平高低控制,而控制DIR引脚电平是用一个跳线帽控制的,需要的可以查询文档。
重要信息:
1.已知默认状态下,所有的IO口默认都是高电平。
2.IO口是弱上拉,就是说高电平的能力比低电平弱(通俗的说就是两个互接,结果为低电平)
1.LED
这个模块在 笔记一 里面已经有实验过了,这里重新放一张原理图,只需要控制:
// P20 ~ P27 一共 8 个 IO 口即可。

2.独立按键
由原理图可知,四个独立按键由P31到P33控制,当按键按下的时候,对应的IO的高电平被置为低电平,单片机就可以检测到对应IO口的电平高低,从而判断按键是否被按下。

这里我们写一个小Demo,按下 K1按键 D1(LED)亮,松开D1灭:
#include <REGX52.H>
void main() {
while(1) {
// K1 被按下时,P3_1 电位为低电平。看最前文的重要信息。
if (P3_1 == 0) {
// 开启 D1 LED 灯。
P2_0 = 0;
}
// K1 被松开时,关闭 D1 LED 灯。
else P2_0 = 1;
}
}
也是顺利的通过实验。

3.动态数码管
每个8字形的数码管,由7个小的横竖短杠灯和一个点组成,对应图中的a~g和dp编号。图中蓝色圈圈的是8个数码管的各单独数码管中的一组a到dp的共阴极接入线,如果我们想让哪个数码管显示某个数字,就给上面对应的标号低电平(对于蓝色画圈的)。

这蓝色圈圈的8个引脚由138译码器的3个IO口来控制,138译码器的原理图:

数码管对应显示的内容由上上个图红色画圈的地方来控制(红色画圈是给高电平亮,低电平不亮)。
示例,我们这里假如让第2个管显示5,则LED7对应的引脚为低电平(有效),LED7在136译码器中是Y6,则CBA对应值为110(6的二进制),显示内容为5,则对应的a,f,g,c,d要亮就是给高电平,根据画红圈部分可得到值:0110 1101(从下往上看),对应16进制6D,可以撸代码了。
#include <REGX52.H>
void main() {
P2_4 = 1;
P2_3 = 1;
P2_2 = 0;
// 0110 1101
P0 = 0x6D;
while(1) {
}
}
顺利通过,具体在哪个位置显示什么数值可定义为函数直接调用。

但是在同一时刻,我们只能控制一个数码管的显示及内容控制,由于它们的线路都是公用的(这是为了节省IO口而设计的),所以如果我们同时显示两个的话,它们显示的内容也只能是相同的,因为同一时刻,下面的电路只能控制显示某一个确定的内容,上面只能控制哪些灯亮,这样就不能同时让各管显示不同的内容,因此如果需要同时显示多个数码管,可以采用的方法是:利用人的视觉残留现象,轮流显示各管的内容,达到一个扫描的效果,看起来就好像同时在亮一样。
4.LCD1604
将LCD1604安装在单片机上,插槽为短的那一排,使用LCD1602时,与左侧3个LED灯冲突,数码管也不能用了,因为P0口被占用了。

LCD的驱动代码可以参考对应的文档,如下图所示,鉴于初学者还是优先把东西用起来,我就拿了B站的江科大自化协已经写好的驱动代码,我看了一下,作者的代码逻辑还是很清晰的,注释也很详细,我大概阅读了一下源码再对比一下LCD1604的文档,就差不多明白怎么去驱动了,这里先感谢原作者了,但是自己写肯定还是写不好的,所以先拿过来用了。

#include <REGX52.H>
// 作者: B站, 江科大自化协
// 地址:https://space.bilibili.com/383400717
//引脚配置:
sbit LCD_RS = P2^ 6;
sbit LCD_RW = P2^ 5;
sbit LCD_EN = P2^ 7;
#define LCD_DataPort P0
//函数定义:
/**
* @brief LCD1602延时函数,12MHz调用可延时1ms
* @param 无
* @retval 无
*/
void LCD_Delay()
{
unsigned char i, j;
i = 2;
j = 239;
do
{
while (--j);
} while (--i);
}
/**
* @brief LCD1602写命令
* @param Command 要写入的命令
* @retval 无
*/
void LCD_WriteCommand(unsigned char Command)
{
LCD_RS = 0;
LCD_RW = 0;
LCD_DataPort = Command;
LCD_EN = 1;
LCD_Delay();
LCD_EN = 0;
LCD_Delay();
}
/**
* @brief LCD1602写数据
* @param Data 要写入的数据
* @retval 无
*/
void LCD_WriteData(unsigned char Data)
{
LCD_RS = 1;
LCD_RW = 0;
LCD_DataPort = Data;
LCD_EN = 1;
LCD_Delay();
LCD_EN= 0;
LCD_Delay();
}
/**
* @brief LCD1602设置光标位置
* @param Line 行位置,范围:1~2
* @param Column 列位置,范围:1~16
* @retval 无
*/
void LCD_SetCursor(unsigned char Line, unsigned char Column)
{
if(Line==1)
{
LCD_WriteCommand(0x80 | (Column-1));
}
else if(Line==2)
{
LCD_WriteCommand(0x80 | (Column-1+0x40));
}
}
/**
* @brief LCD1602初始化函数
* @param 无
* @retval 无
*/

本文介绍了如何利用STC89C516单片机进行LED灯光控制、独立按键检测、动态数码管显示以及LCD1604液晶显示屏操作。通过实例演示和代码,展示了基本硬件原理和实用编程技巧,适合初学者入门。
最低0.47元/天 解锁文章
5013





