- 打卡等级:初来乍到
- 打卡总天数:5
- 最近打卡:2025-04-23 14:03:23
中级会员
- 积分
- 452
|
本帖最后由 sbk100 于 2023-3-1 15:25 编辑
先上电路
在本次实验中,采用了 8 位数码管动态扫描显示,其硬件原理图如图 2-1 所示。它将所有数码管的 8 个段线相应的连接到 JP81,程序中我们将 JP81 连接到单片机
的 P0 口,由 P0 口控制字段输出。而各位数码管的共阴极由单片机的 P1 控制 SL0-SL7 来实现 8 位数码管的位输出控制。
这样,对于一组数码管动态扫描显示需要由两组信号来控制:一组是用来控制显示的字形,称为段码;另一组用来选择第几位数码管工作,称为位码。
由于各位数码管的段线是连接到一起的,所以段码的输出对各位数码管来说都是相同的。因此,在同一时刻如果各位数码管的位选线都处于选通状态的话,8位数码管
将显示相同的字符。若要各位数码管能够显示出与本位相应的字符,就必须采用扫描显示方式。即在某一时刻,只让某一位的位选线处于导通状态,而其它各位的位选线处
于关闭状态。同时,段线上输出相应位要显示字符的字型码。这样在同一时刻,只有选通的那一位显示出字符,而其它各位则是熄灭的,如此循环下去,就可以使各位数码
管显示出将要显示的字符。虽然这些字符是在不同时刻出现的,而且同一时刻,只有一位显示,其它各位熄灭,但由于人眼有视觉暂留效应,只要每秒扫描的次数足够多,
就能看到连续稳定地显示。
数码管是由 7 个条形的 LED 和右下方一个圆形的 LED 组成,这样一共有 8 个段线,恰好适用于 8 位的并行系统。数码管有共阴极和共阳极两种,共阴极数码管的公共
阴极接地(如图 2-2),当各段阳极上的电平为“1”时,该段点亮,电平为“0”时,该段熄灭。(本次实验采用共阴极数码管)
共阳极数码管的公共阳极接+5V,当各段阴极上的电平为“0”时,该段点亮,电平为“1”时,该段熄灭。
共阴极数码管的字型代码如图 2-4。
以上的常规编码仅在共阴数码管,且 I/O 口的 0-7 对应数码管的 a-dp 时使用,如果是非常规编码需要将数码管对应的 a-dp 按照 I/O 接口的顺序重新排列,编码
例如:将 b 与 c 对调。
I/O 口工作模式
I/O 口配置
STC15 系列单片机最多有 46 个 I/O 口:P0.0~P0.7,P1.0~P1.7,P2.0~P2.7,P3.0~P3.7,P4.0~P4.7,P5.0~P5.5。其所有 I/O 口均可由软件配置成 4 种工作类
型之一,如下表所示。4 种类型分别为:准双向口/弱上拉(标准 8051 输出模式)、推挽输出/强上拉、仅为输入(高阻)或开漏输出功能。每个 I/O 口由 2 个标准寄
存器中的相应位控制每个引脚的工作类型。STC15 系列单片机的 I/O 口上电复位后为准双向/弱上拉(传统 8051 的 I/O 口)模式。每个 I/O 口驱动能力均可达到 20mA,
但 40-pin 及 40-pin 以上单片机的整个芯片最大不要超过 120mA,20-pin 以上及32-pin 以下(含 32)单片机的整个芯片不要超过 90mA。
例:P0 口设定<P0.0~P0.7>(P0 口地址:80H)
举例:MOV P0M1,#10100000B
P0.7 为开漏,P0.6 为强推挽输出,P0.5 为高阻输入,其他为准双向口。
实验测试
连接:
P0 端口接动态数码管的段选 JP81
P1 端口接动态数码管的位选 JP82
实验现象:8 位数码管上分别显示 0-7 数字
/************************************************
* * 程序功能:动态数码管的显示
* * 接线说明:P0端口接动态数码管的段选JP81
* P1端口接动态数码管的位选JP82
* * 实验现象:8位数码管上分别显示0-7数字
* *************************************************/
#include "hal.h"
#define DataPort P0
#define PosPort P1
//数码管字形表,供显示时查询
uchar code disptable[18]=
{ //定义表格一定要使用code,这样会做到程序存储区中
0x3F, //"0"的字形表,0B00111111
0x06, //"1"的字形表,0B00000110
0x5B, //"2"的字形表,0B01011011
0x4F, //"3"的字形表,0B01001111
0x66, //"4"的字形表,0B01100110
0x6D, //"5"的字形表,0B01101101
0x7D, //"6"的字形表,0B01111101
0x07, //"7"的字形表,0B00000111
0x7F, //"8"的字形表,0B01111111
0x6F, //"9"的字形表,0B01101111
0x77, //"A"的字形表,0B01110111
0x7c, //"b"的字形表,0B01111100
0x39, //"C"的字形表,0B00111001
0x5e, //"d"的字形表,0B01011110
0x79, //"E"的字形表,0B01111001
0x71, //"F"的字形表,0B01110001
0x00 // 全灭消隐
};
/*共阴数码管位选编码*/
uchar code Position[] = {0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};
uchar dos =0; //数码管位选
uchar dis_1ms_ok = 0; //扫描标志位
/*******************************************************
* //函数名称:Timer0Init()
* //函数功能:定时器0初始化函数 1毫秒@12MHz
* //入口参数:无
* //返回参数:无
* ********************************************************/
void Timer0Init(void)
{
TIMER_CLK_DIV(0,1); //设置定时器0时钟12T模式
TIMER_TIME(0); //设置定时器0定时模式
TIMER_MODE(0,0); //设置定时器0模式0
TL0 = 0x18; //设置定时初值
TH0 = 0xFC; //设置定时初值
CLR_TIMER_FLAG(0); //清除TF0标志
}
/*******************************************************
* 函数名称:Timer0_ISR()
* 函数功能:定时器0中断服务程序
* 入口参数:无
* 返回参数:无
* ********************************************************/
void Timer0_ISR() interrupt T0_VECTOR using 1
{
dis_1ms_ok = 1; //扫描时间1ms到
}
/*******************************************************
* 函数名称:dispaly()
* 函数功能:数码管动态扫描显示0-7
* 入口参数:无
* 返回参数:无
* ********************************************************/
void display()
{
PosPort = 0xff;//消隐
DataPort = disptable[dos];//送数据段
PosPort = Position[dos]; //送位选
dos++;
if(dos>=8) //判断位选是否超过8
{
dos=0; //清零
}
}
数码管显示子程序:首先为消除上一位显示对当前显示的影响,先在位码上输出全 0,完成消隐。然后输出当前显示位的段码和位码完成一位的显示。轮流显示
8 位数码管,就可以完成 8位数码管的显示。为了无闪烁并且亮度足够需要每个 LED灯每秒至少点亮 25 次,并采用推挽输出模式。这里我们每位点亮 1ms,即8位扫描
完一次需要 8ms,1s 扫描 125 次。
void main()
{
IO_PORT_SET(0,0xff, IO_OUT);//P0口设置为推挽输出
Timer0Init(); //定时器0的初始化
TIMER_INT_EN(0,ON); //开启定时器0中断
INT_GLOBAL_ENABLE(ON); //开启全局中断
TIMER_RUN(0,START); //定时器0开始计时
while(1)
{
if(dis_1ms_ok)
{
dis_1ms_ok = 0;
display();
}
}
}
|
|