【自学51单片机】5 --- 定时器介绍、数码管静态显示、逻辑运算符和逻辑电路符号

2023-10-26

1、逻辑运算和逻辑电路

  • 引入逻辑概念:在生活中,逻辑存在 ‘真’‘假’ 两个逻辑值,而逻辑对应到C语言和数字电路中, ‘真’ 对应C语言或数字电路中的一切 ‘非0值’,而 ’假‘ 对应为 ’0值‘

1.1 C语言逻辑运算符

  假定两个字节变量A和B,两者进行某种逻辑运算后结果为F。

  以下为逻辑运算符(按变量整体值进行运算)

  • && 逻辑与:F = A && B,当 A、B 的值都为真(即非 0 值,下同)时,其运算结果 F
    为真(具体数值为 1,下同);当 A、B 值任意一个为假(即 0,下同)时,结果 F 为假(具体数值为 0,下同)。
  • || 逻辑或:F = A || B, A、B 值任意一个为真, F 为真; A、B 值都为假, F 为假。
  • ! 逻辑非:F = !A,A 值为假, F 为真; A 值为真, F 为假。

 以下为按位运算符(按变量的每一个位进行运算)

  • & 按位与:F = A & B,将 A、B 两个字节中的每一位都进行与运算,得到的每一位结果组合为总结果 F,例如 A = 0b00111100,B = 0b11011101,则结果 F 就等于0b00011100。
  • | 按位或: F = A | B,例如 A = 0b00111100,B = 0b11011101, F 就等于 0b11111101。
  • ~ 按位取反: F = ~A,就是将 A 字节内的每一位进行非运算(就是取反),例如 A = 0b00111100, F 就等于 0b11000011;
  • ^按位异或:异或的意思是,如果运算双方的值不同(即相异)则结果为真,双方值相
    同则结果为假。F = A ^ B,A = 0b00111100,B = 0b11011101 , 结果 F 就等于 0b11100001。

1.2 逻辑电路符号

以下图为数字电路常用电路符号,重点认识国外流行符号,通过查阅来记住即可。

逻辑电路符号

2、定时器学习(重点非难点)

2.1 时钟周期和机器周期的介绍

  • 时钟周期:是时序中最小的时间单位,计算方法:时钟周期 = 1 / 时钟源频率。(注:1. 单位为秒  2.时间源频率就是单片机的晶振,博主STC89C52RC的晶振电路晶振为:11.0592M)
  • 机器周期:单片机完成一个操作的最短时间。标准架构下的51单片机的一个机器周期等于12个时钟周期(12 / 时钟周期 S),有的增强型51单片机一个机器周期等于4个时钟周期或等于1个时钟周期,以下讲解标准框架下的51单片机。

2.2 定时器的介绍

单片机中定时器和计数器是内部的同一模块,计数器功能读者自己去了解,我们来介绍定时器功能。
定时器用于定时,标准51单片机有T0和T1两个定时器。定时器内部有一个寄存器,该寄存器的值每通过一个机器周期自动加1,可以把机器周期理解为定时器的计数周期,如同钟表,每经过一秒,数字自动加1,而寄存器每通过12/11059200秒,数值自动加1。当钟表加到60秒后,秒自动跳为0,这种情况在单片机和计算机中叫溢出,定时器不同工作模式,溢出的情况也不同,假如16位定时器,加到65535后,再加1就溢出,溢出后值直接变为0。

2.2.1 定时器寄存器介绍

 定时器这模块有6个寄存器,下面来一一介绍,读者用到这些寄存器查手册即可。

  • 定时值存储寄存器
    定时值存储寄存器
     表5-1中有四个寄存器,用于存储定时器的计数值,其中TH0和TL0用于定时器0,TH1和TL1用于定时器1。
  • TCON–定时器控制寄存器
    位分配
    (注:可位寻址指的是可以对该寄存器的每个位单独操作,比如该寄存器的一位TR1,可以直接用程序进行TR1 = 1操作)
    位描述
    (注:只要写到硬件置 1 或者清 0 的,就是指一旦符合条件,单片机将自动完成的动作,只要写软件置 1 或者清 0 的,是指我们必须用程序去完成这个动作)

 表 5-2 是定时器控制寄存器 TCON 的位分配,表 5-3 是则是对每一位的具体含义的描述。TCON寄存器中TF0和TR0用于定时器0,TF1和TR1用于定时器1。我们以定时器1为例讲解,定时器0同理,TR1等于1,定时器值每过一个机器周期加1,若等于0,则停止加1。 TF1的作用是告诉们定时器溢出了,比如定时器16位模式下,每经过一个机器周期会使TL1加1,加到255后,再加1后,TL1变为0,而TH1加1,如此循环,待TL1和TH1为255后,再加1就会溢出,此时TL1和TH1变为0,TF1自动变成1,提供给读者一个溢出信号。

  • TMOD–定时器模式寄存器

位分配
(注:不可位寻址指的是不可以对该寄存器的每个位单独操作,对 TMOD 里的位比如M1 (T1)= 1 这样的操作就是错误的。我们要操作就必须一次操作这整个字节,也就是必须一次性对 TMOD 所有位操作)
 上表为TMOD的位分配。

位描述
 表5-5为TMOD的位描述,GATE位读者自行了解,C/T位为选择定时器或计数器功能,C/T=0为选择定时器功能,C/T=1为选择计数器功能。


 表5-6为TMOD4中模式介绍,模式0和3现在很少应用,读者自行了解,下面介绍模式1和2。
模式1: 是 THn 和 TLn 组成了一个 16 位的定时器,计数范围是 0~65535,溢出后,只要不对 THn 和 TLn 重新赋值,则从 0 开始计数。
模式2: 是 8 位自动重装载模式,只有 TLn做加 1 计数,计数范围 0~255,THn 的值并不发生变化,而是保持原值,TLn 溢出后,TFn就直接置 1 了,并且 THn 原先的值直接赋给 TLn,然后 TLn 从新赋值的这个数字开始计数。 比如该模式下,TH1 = 0x66,TL1=0x00,每经过一个机器周期TL1加1,当TL1=0xFF时,再加1后TF1就会变为1,并且TL1会被赋值为TH1的值后计数,即TL1从0x66开始计数,而TH1的值保持不变。

2.2.2 定时器模式工作电路逻辑图

  • 定时器模式一工作电路逻辑图

模式一
讲解:以定时器1为讲解,定时器0同理,OSC为时钟源频率,d为单片机机器周期对于时钟周期的倍数。

  1. 当C/T = 0打开定时器功能,C/T = 1打开计数器功能。
  2. 要达到控制效果,TR1和或门构成的电路要进行与运算,与运算两个为真才为真,所以TR1要为1,并且或门构成的电路进行或运算后结果要为1,
  3. 或门输出为1的方式有两种9:(1).当INT1引脚为1时,不过GATA位为什么,或运算后结果都为1,定时器1模式1开启。(2). 当GATA为0时,经过非运算后为1,不管INT1为什么,进行或运算结果都为1,定时器1模式1开启。
  • 定时器模式二工作电路逻辑图
    模式二
    讲解: 模式二的电路逻辑图和模式一的相似,就不进行详细讲解,此模式下定时器作为可自动重装载的8位计数器(TLn), TLn的溢出,不仅置为TFn,而且将THn的内容重新装载到TLn,THn内容由软件预置,重装时THn内容不变。

2.3 定时器的应用

2.3.1 使用定时器的步骤

下面以使用定时器0为例,定时器1同理。

  1. 设置定时器模式寄存器TMOD,选择好定时器工作模式。
  2. 设置计数寄存器TH0和TL0的初值。
  3. 设置定时器控制寄存器TCON,使TR0 置1让定时器开始计数。
  4. 通过判断TCON中的TF0位,监测定时器的溢出情况。

2.3.2计算如何用定时器定时时间

 我们知道标准51单片机机器周期为12个时钟周期,以STC89C52RC单片机为例,它的机器周期为:12/11059200秒,如果定时0.02s,设要经过x个机器周期,那么 x* (12/11059200) =0.02, 通过计算x等于18432,因16位定时器溢出值为65536,那么先让TH0和TL0等于初值y,经过18432个机器周期后溢出,这样就实现了定时0.02s,y值通过65536- 18432计算出为47104,转换为十六进制就是0xB800(链接:进制转换方法),即TH0 = 0xB8,TL0 = 0x00。

2.3.3通过定时器控制小灯的闪烁

  • 控制小灯进行0.5HZ频率闪烁的程序
#include<reg52.h>

sbit LED = P0^7;
sbit ADDR3 = P1^3;
sbit ADDR2 = P1^2;
sbit ADDR1 = P1^1;
sbit ADDR0 = P1^0;
sbit ENLED = P1^4;

void main()
{
	unsigned char cnt = 0;//定义一个计数变量,记录T1的溢出次数
	ENLED = 0;
	ADDR3 = 1;
	ADDR2 = 1;		
	ADDR1 = 1;
	ADDR0 = 0;
	TMOD = 0x10;//配置T1的工作模式
	TH1 = 0xB8;
	TL1 = 0x00;//为T1赋初值
	TR1 = 1;//启动T1

	while(1)
	{
		if(TF1 == 1)//判断T1是否溢出
		{
			 cnt++;// 计数值自加1
			 TF1 = 0;//T1溢出后,清零中断标志
			 TH1 = 0xB8;//并在重新赋初值
			 TL1 = 0x00;
			 if(cnt >= 50)//判断是否溢出50次
			 {
			 	LED = ~LED;//LED取反,1--->0、0--->1
				cnt = 0;//达到50次后计数值清零
			 }
		}	
	}

}
  • 通过定时器控制左右流水灯程序
#include<reg52.h>

sbit ADDR0 = P1^0;
sbit ADDR1 = P1^1;
sbit ADDR2 = P1^2;
sbit ADDR3 = P1^3;
sbit ENLED = P1^4;

void main()
{
	unsigned char cnt = 0;//定义计数变量,记录溢出次数
	unsigned char dir = 0;//定义移位方向变量,用于改变流水灯流向
	unsigned char shift = 0x01;//定义循环移位变量shift,并赋初值0x01	
	
	ENLED = 0;//使能U3
	ADDR3 = 1;
	ADDR2 = 1;
	ADDR1 = 1;
	ADDR0 = 0;
	TMOD = 0x10;//设置T1为模式一
	TH1 = 0xB8;//为T1赋初值
	TL1 = 0x00;
	TR1 = 1;//开启T1

	while(1)//主循环,程序无限执行该循环
	{
		P0 = ~shift;//P0等于循环移位变量shift取反,控制8个LED小灯
		while(TF1 == 0);//当TF1=0时循环执行空语句,直到定时器溢出
		TF1 = 0;//TF1清零
		TH1 = 0xB8;//重新为T1赋初值
		TL1 = 0x00;
		cnt++;//每溢出一次,cnt加一
		if(cnt >= 10)//判断是否溢出10次
		{
			cnt = 0;//溢出次数置零
			if(dir == 0)//移位方向变量为0时,左移
			{
				shift = shift << 1;//循环移位变量shift左移一位
				if(shift == 0x80) //左移到最左端,改变移位方向变量
				{
					dir = 1;	
				}
			}else				//移位方向变量不为零时,右移
			{
				shift = shift >> 1;//循环移位变量右移一位
				if(shift == 0x01) //右移到最右端,改变移位方向变量
				{
					dir = 0;
				} 
			}
		}
	}

}

3、数码管学习

3.1 数码管介绍

 一个数码管由8个LED小灯组成。数码管分为共阳数码管和共阴数码管,共阳数码管的8个LED小灯阳极连在一起, 阳极为公共端,由阴极控制单个小灯亮灭。共阴数码管同理,数码管内部结构见下图5-4。
数码管内部结构
 下图5-3为数码管的原理图

数码管原理图
  com引脚为公共端,图中有两个com公共端,为什么有两个公共端呢? 一方面,为了起对称效果,刚好10个引脚,另一方面,因并联电流之和等于总电流,可以降低单条线路承受的电流。

3.2 数码管静态显示原理

 下图为KST-51开发板中数码管电路图
数码管电路图
 从上图可以知道数码管每个LED小灯阳极都接在5v(VCC)上,所以上图6个数码管都是共阳数码管,下面讲解数码管点亮原理。

  1. 首先根据分析点亮数码管要先导通数码管对应连接的三极管,即让每个三极管的基极b输出低电平,也就是控制三八译码器将对应Y编号的引脚输出为低电平即能导通三极管,我们第三章中已经介绍了如何应用三八译码器,使用时查看芯片手册即可,就不再介绍。
  2. P0的所有引脚对应连接DB编号引脚,控制P0引脚的输出电平,即可让数码管显示不同的数值。比如让数码管显示8,那么P0要为0b10000000,转换为十六进制就为0x80(链接:进制转换方法)。

3.3数码管真值表

 数码管的 8 个段,我们直接当成 8 个 LED 小灯来控制,那就是 a、b、c、d、e、f、g、dp 一共 8 个 LED 小灯。我们控制这8个小灯来让数码管显示不同数值,而数码管显示的数字字符对应给 P0 的赋值,我们叫做数码管的真值表。 数码管真值表见下表5-7。

数码管真值表

3.4 数码管的应用

  • 让数码管静态显示字符程序
#include<reg52.h>

sbit ADDR0 = P1^0;
sbit ADDR1 = P1^1;
sbit ADDR2 = P1^2;
sbit ADDR3 = P1^3;
sbit ENLED = P1^4;

void main()
{
	ENLED = 0;//使能U3,导通三极管Q9,
	ADDR3 = 1;
	ADDR2 = 0;
	ADDR1 = 1;
	ADDR0 = 1;
	P0 = 0x80;//点亮数码管DS4的a、b、c、d、e、f和g段,让数码管显示字符8
	while(1);//让数码管DS4一直显示字符8
}
  • 数码管静态显示秒表先计时后倒计时程序

 先介绍C51中的关键字code,前面定义变量时使用关键字unsigned char或unsigned int,这样定义的变量都是放在单片机RAM中,并且程序中可以随意更改这些变量的值,而运用code关键字修饰下定义的变量,则可以存储到程序空间FLASH中,大大节省单片机RAM空间,但程序中不能更改这些变量的值。下面我们来看看运用了code关键字的程序。

#include<reg52.h>

sbit ADDR0 = P1^0;
sbit ADDR1 = P1^1;
sbit ADDR2 = P1^2;
sbit ADDR3 = P1^3;
sbit ENLED = P1^4;

//用数组存储数码管真值表,数组将在下一章详细介绍
unsigned char code Ledchar[] = {
	0xC0, 0xF9, 0xA4, 0xB0, 0x99, 0x92, 0x82, 0xF8,
	0x80, 0x90,	0x88, 0x83, 0xC6, 0xA1, 0x86, 0x8E
};

void main()
{
	unsigned char cnt = 0;//定义溢出计数变量,记录溢出次数
	signed char sec = 0;//记录经过的秒数
	unsigned char dir = 0;//定义选择变量,0代表秒表,1代表倒计时	

	ENLED = 0;//使能U3,导通三极管Q8,准备点亮数码管DS5
	ADDR3 = 1;
	ADDR2 = 1;
	ADDR1 = 0;
	ADDR0 = 0;

	TMOD = 0x01;//配置T0为工作模式一
	TH0 = 0xB8;//为T0赋初值
	TL0 = 0x00;
	TR0 = 1;//打开定时器T0

	while(1)
	{
		if(TF0 == 1)//判断T0是否溢出
		{
			TF0 = 0;//软件将溢出标志清零
			TH0 = 0xB8;//为T0重新赋值
			TL0 = 0x00;
			cnt++;//计数值自加1,
			if(cnt >= 50)//判断T0是否溢出50次
			{
				cnt = 0;//达到50次后计数值清零
				if(dir == 0)//选择变量dir等于0,实现秒表功能
				{
					 P0 = Ledchar[sec];//当前秒数对应的真值表中的值送到P0口
					 sec++;//秒数记录自加一
					 if(P0 == 0x8E)//当P0值使数码管显示字符F时,
					 {
					 	dir = 1;//将选择变量置为1,准备实现倒计时功能
						sec = 14;//将秒数置为14
					 }
				}else //实现倒计时功能
				{
					P0 = Ledchar[sec];//当前秒数对应的真值表中的值送到P0口
					sec--;//秒数记录自减一
					if(sec < 0)//当秒数小于0后
					{
						dir = 0;//将选择变量置为0,准备实现秒表功能
						sec = 1;//将秒数置为1
					}
				}
			}

		}
			
	}

}

4、收获

  重温第五章对定时器的使用无疑更加熟悉了,编程上没有啥问题,前几天忙家里的一些事耽误了进度,一天一章的目标也啪啪打脸,接下来会加倍学习的。奥里给奥里给!!!

表情包

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

【自学51单片机】5 --- 定时器介绍、数码管静态显示、逻辑运算符和逻辑电路符号 的相关文章

  • vue3 实现点击可左右滑动

    具体代码如下
  • WINDOWS的远程桌面。

    http baike baidu com view 372045 htm 1 远程桌面的功能 远程桌面连接组件是从Windows 2000 Server开始由微软公司提供的 在WINDOWS 2000 SERVER中他不是默认安装的 该组件
  • Flutter 页面跳转和数据传值 pop回指定页面(路由实践)

    flutter搭建app 感觉相对简化了很多 布局核心就是万事皆widget 在之前我们不管是iOS 安卓原生 还是rn 我们在页面跳转和回转 我们都要对页面进行管理 从iOS 到安卓 到rn 路由被强调话了 web前端的一些重要设计思想被
  • .NET6用起来-Autofac

    本文的主角是Autofac 它是一款非常奈斯的依赖注入框架 暂时先不讨论 先分享几个名词 DI 依赖注入 IOC 控制反转 IOC容器 通过Demo 认识这些名词 Demo很简单 创建一个Asp NET Core项目 新增一个用户服务类 U

随机推荐