AutoLeaders控制组——51单片机学习笔记(一)

单片机

【所使用单片机为STC89C52RC单片机】

本人单片机图片:
在这里插入图片描述

单片机介绍

单片机,英文Micro Controller Unit,简称MCU。
内部集成了CPU,RAM,ROM,定时器,中断系统,通讯接口等一系列电脑的常用硬件功能。
单片机的任务是信息采集(依靠传感器),处理(依靠CPU)和硬件设备(例如电机,LED等)的控制。

所属系列为8051,即51单片机。
8051最开始指在80年代生产的8051内核的单片机。后延伸为只要是8051内核的单片机,都统称为51单片机。

单片机命名规则:

在这里插入图片描述

单片机内部结构

结构图:
在这里插入图片描述

管脚图:
在这里插入图片描述

原理图:
在这里插入图片描述
VCC是正极(高电平),GND是负极(低电平)
【原理图很重要,对学习新外设很有帮助】

软件

1、Keil:可以创建项目编写程序
2、stc-isp:烧录(下载)程序的软件

一、LED

点亮LED

LED:发光二极管

从上面的原理图可以查到LED原理图
在这里插入图片描述

电阻的作用:限流,防止电流过大烧毁LED

从图中可以看到,LED左端连的VCC(高电平,即1),右端是P2口,为了有电流通过从而点亮LED,因此P2口应为低电平,即0。(感觉P2类似地址)

则根据原理图,要使第一个LED灯亮就需要P2_0为0,其他为1,因此可以写出下面代码:

#include <REGX52.H>

void main(){
	P2 = 0xFE; //1111 1110
	while(1); //死循环,以免程序反复运行
 }

【<REGX52.H>是一个头文件,里面定义了P2,所以必须要有,可以右键快速添加】

LED周期闪烁

周期,就要有延时函数。
可以借助stc-isp的软件延时功能生成延时函数。
在这里插入图片描述

因此,就可以写出使LED灯周期闪烁的代码:

#include <REGX52.H>
#include <INTRINS.H>   //_nop_函数的头文件
void Delay500ms()		//@11.0592MHz
{
	unsigned char i, j, k;

	_nop_();
	i = 4;
	j = 129;
	k = 119;
	do
	{
		do
		{
			while (--k);
		} while (--j);
	} while (--i);
}

void main(){
	while(1){
		P2 = 0xFE;//1111 1110
		Delay500ms();
		P2 = 0xFD;//1111 1101
		Delay500ms();
	}
}

LED流水灯

流水灯就是使八个LED灯依次亮起。
经过上面两个,运用学c的知识,自己就可以写出一个流水灯代码了。

#include <REGX52.H>
#include <INTRINS.H>

void Delay1ms(unsigned int xms)		//@11.0592MHz
{
	while(xms--)
	{
		unsigned char i, j;

		_nop_();
		i = 2;
		j = 199;
		do
		{
			while (--j);
		} while (--i);
	}
}


void main()
{
	while(1)
	{
		P2 = 0xFE;//1111 1110
		Delay1ms(200);
		P2 = 0xFD;//1111 1101
		Delay1ms(200);
		P2 = 0xFB;//1111 1011
		Delay1ms(200);
		P2 = 0xF7;//1111 0111
		Delay1ms(200);
		P2 = 0xEF;//1110 1111
		Delay1ms(200);
		P2 = 0xDF;//1101 1111
		Delay1ms(200);
		P2 = 0xBF;//1011 1111
		Delay1ms(200);
		P2 = 0x7F;//0111 1111
		Delay1ms(200);
	}
}

或者使用位运算符,将主函数简化:

void main()
{
	P2 = 0xFE;
	while(1)
	{
		Delay1ms(200);
		P2 = (P2<<1) + 1;
		if(P2 == 0xFF){
			P2 = 0xFE;
		}
	}
}

二、独立按键

1、先看一下独立按键的原理图
在这里插入图片描述

从图中可以知道,独立按键是P3口控制的。

再者就是,右上方都接了GND,低电平,即0,那么如果按键按下的话,对应的P3接口就是0。
因此,可以通过判断P3接口是不是0,从而判断出按键有没有被按下,哪个按键被按下了。

注意:第一个独立按键是P3_1,而第二个是P3_0。

2、按键消抖:

对于机械开关,当机械触点断开、闭合时,由于机械出点的弹性作用,一个开关在闭合时不会马上稳定地接通,在断开时也不会一下子断开,所以在开关闭合及断开的瞬间会伴随一连串的抖动,如图所示
在这里插入图片描述
因此我们需要用延时函数消磨掉这段时间,从而消除这种抖动。

运用综上所述的两点,我们就可以写出以下程序

实操一:独立按键控制LED闪灭

#include <REGX52.H>

void Delay(unsigned int x)		//@11.0592MHz
{
	while(x--)
	{
		unsigned char i, j;
		i = 2;
		j = 199;
		do
		{
			while (--j);
		} while (--i);
	}
}

void main()
{
	while(1)
	{
		if(P3_1==0){
			Delay(20);
			while(P3_1==0);
			Delay(20);		//消抖
			P2_0 = ~P2_0;	//~各位取反
		}
	}
}

实操二:独立按键控制LED显示二进制加减,清零

#include <REGX52.H>

void Delay(unsigned int x)		//@11.0592MHz
{
	unsigned char i, j;

	while(x--)
		{
		i = 11;
		j = 190;
		do
		{
			while (--j);
		} while (--i);
	}
}

void main()
{
	P2 = 0xFF;
	while(1){
		if(P3_1 == 0)
		{
			Delay(20);
			while(P3_1 == 0);
			Delay(20);
			P2--;
		}
		if(P3_0 == 0){
			Delay(20);
			while(P3_0 == 0);
			Delay(20);
			P2++;
		}
		if(P3_2 == 0){
			Delay(20);
			while(P3_2 == 0);
			Delay(20);
			P2 = 0xFF;
		}
	}
}

实操三:独立按键控制LED灯移位

#include <REGX52.H>

void Delay(unsigned int x)		//@11.0592MHz
{
	while(x--)
	{
		unsigned char i, j;
		i = 11;
		j = 191;
		do
		{
			while (--j);
		} while (--i);
	}
}

void main()
{
	P2 = 0xFE;//1111 1110
	while(1)
	{
		if(P3_1 == 0)
		{
			Delay(20);
			while(P3_1 == 0);
			Delay(20);
			P2 = (P2<<1)+1;
			if(P2 == 0xFF)
			{
				P2_0 = 0;
			}
		}
		if(P3_0 == 0)
		{
			Delay(20);
			while(P3_0 == 0);
			Delay(20);
			P2 = (P2>>1) + 0x80;
			if(P2 == 0xFF)
			{
				P2_7 = 0;
			}
		}
	}
}

三、数码管

数码管介绍

LED数码管:数码管是由多个发光二极管封装在一起组成“8”字型的器件。

单个数码管引脚定义

数码管的接法,有共阳和共阴之分。共阴时,拉高电压即可点亮。共阳时,拉低电平点亮。
在这里插入图片描述
【右侧的上图是共阴极连接,下图是共阳极连接。】

以共阴极连接为例(所用单片机就是共阴极),共用的3,8一端就叫做位选(位:四位一体的数码管的位数),另一端叫做段选。
如果要显示“6”,则A,C,D,E,F,G要亮,即段选端要为1,而B,DP要为0。
因此,段码就为1011 1110

四位一体数码管引脚定义

在这里插入图片描述
举一反三:如果是共阴极连接(右上图),想要第三位显示“1”的话,那么就要位码为1101,段码为0110 0000。

数码管显示原理图

在这里插入图片描述
74HC138译码器
控制哪一位的数码管亮起,且将原本需要8个I/O输入口减少成了三个P2口,且需为低电平。
C为高位,A为低位,且有效端口为低电平。
例:若P2_4=0, P2_3=0, P2_2=0, 则有效端为Y0,且只有Y0为低电平,即0.

74HC245(位于下图):
双向数据缓冲器。因为单片机输出能力有限,需要该芯片提高输入能力。

从图中可以看到,数码管的段码(若是共阴极,段码也称阳码)连的是P0输入端口。

因此,显示数码管步骤应为:
①赋值P2_3,P2_3,P2_4控制位数;
②赋值P0,控制显示;
注意:P0_7为高位,高位对高位,注意二进制数字顺序

静态数码管显示

由上面所学知识,我们就可以编写代码显示数码管了

#include <REGX52.H>

void main(){
	P2_4 = 1;
	P2_3 = 1;
	P2_2 = 1;
	P0 = 0x7D;
	while(1){
	}
}

每次显示数码管的时候都要敲这么多代码,因为可以写一个显示数码管的函数,如下:

#include <REGX52.H>

unsigned nixietable[] = {0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x6F};

void nixie(unsigned char location, num){
	switch(location){
		case 1: P2_4 = 1; P2_3 = 1; P2_2 = 1; break;
		case 2: P2_4 = 1; P2_3 = 1; P2_2 = 0; break;
		case 3: P2_4 = 1; P2_3 = 0; P2_2 = 1; break;
		case 4: P2_4 = 1; P2_3 = 0; P2_2 = 0; break;
		case 5: P2_4 = 0; P2_3 = 1; P2_2 = 1; break;
		case 6: P2_4 = 0; P2_3 = 1; P2_2 = 0; break;
		case 7: P2_4 = 0; P2_3 = 0; P2_2 = 1; break;
		case 8: P2_4 = 0; P2_3 = 0; P2_2 = 0; break;
	}
	P0 = nixietable[num];
}

void main(){
	nixie(3,6);
	while(1){
	}
}

动态数码管显示

即,动态清零,数字消影,来实现动态数码管显示。这是单片机不断扫描来成像的,硬件设备简单,但也因此将耗费大量CPU时间,资源。

例子:

#include <REGX52.H>
#include "Delay.h"

unsigned nixietable[] = {0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x6F};

void nixie(unsigned char location, num){
	switch(location){
		case 1: P2_4 = 1; P2_3 = 1; P2_2 = 1; break;
		case 2: P2_4 = 1; P2_3 = 1; P2_2 = 0; break;
		case 3: P2_4 = 1; P2_3 = 0; P2_2 = 1; break;
		case 4: P2_4 = 1; P2_3 = 0; P2_2 = 0; break;
		case 5: P2_4 = 0; P2_3 = 1; P2_2 = 1; break;
		case 6: P2_4 = 0; P2_3 = 1; P2_2 = 0; break;
		case 7: P2_4 = 0; P2_3 = 0; P2_2 = 1; break;
		case 8: P2_4 = 0; P2_3 = 0; P2_2 = 0; break;
	}
	P0 = nixietable[num];
	Delay(1);	//数字消影,若不清除数字,数字会产生错乱,出现”影子“
	P0 = 0x00;	//动态清零,若不清零,则段选和位选容易串位
}

void main(){
	while(1){
		nixie(1,0);
		nixie(2,3);
		nixie(3,0);
		nixie(4,1);
	}
}

数码管驱动方式

1、数码管直接扫描,如上;
2、专用驱动芯片:内部自带显存、扫描电路,单片机只需告诉他显示什么即可。(得另买,了解就得了)

任务

任务代码:

#include <REGX52.H>
#include "Delay.h"
#include "Nixie.h"

unsigned char n=0,j=0,k=0,tem=0,mode,time;
void Display(unsigned char mode)
{
	switch(mode)
	{
		case 1:
			nixie(1,10);nixie(2,1);nixie(7,0);nixie(8,1);
			break;
		case 2:
			if(time<250){
				time++;
				nixie(1,10);nixie(2,2);
				if(n < 10)
				{
					nixie(7,0);nixie(8,n);
				}
				else
				{
					nixie(7,1);nixie(8,0);
				}
				Delay(1);
			}
			else{
				time = 0;
				if(n < 10)
				{
					n++;
				}
				else
				{
					n = 0;
				}
			}
			break;
		case 3:
			time++;
			nixie(1,10);nixie(2,3);nixie(7,0);nixie(8,3);
			if(j == 0)
			{
			nixie(5,11);nixie(6,11);
			}
			if(time>125)
			{
				Delay(1);
				j=~j;
				time = 0;
			}
			break;
		case 4:
			nixie(1,10);nixie(2,4);nixie(7,k);nixie(8,k);
			break;
	}
}

void main()
{
	while(1){
		if(P3_1==0){Delay(20);if(P3_1==0)tem=1;}
		if(P3_0==0){Delay(20);if(P3_0==0)tem=2;}
		if(P3_2==0){Delay(20);if(P3_2==0)tem=3;}
		if(P3_3==0){Delay(20);
			while(P3_3==0)Display(4);
			Delay(20);
			{
				if(tem!=4)k=0;
				else 
				{
					if(k<9)k++;
					else k = 0;
				}
				tem=4;
			}
		}
		if(tem)
			mode = tem;
		Display(mode);
	}
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值