51单片机学习笔记(一)

目录

· 初识单片机

· 单片机的外设

· 单片机控制硬件

        单片机控制设备的方式

       编写程序

        烧录程序

· LED模块

        1、点亮一个LED

        2、LED的闪烁

        3、 LED流水灯

· 独立按键模块

        1、按键控制LED亮灭

        2、按键控制LED状态

        3、按键控制LED表示二进制

        4、按键控制LED移位

· 数码管模块

         1、数码管的结构

         2、静态数码管显示

        3、动态数码管显示


· 初识单片机

单片机(Micro Controller Unit, 简称MCU),内部集成了RAM、ROM、CPU、定时器、中断系统、通讯接口等一系列常用硬件外设,常用于信息采集、处理和设备控制。

换句话说,单片机相当于一台迷你计算机,体积小,结构简单。

而此次学习的51单片机:兼容最早的MCS51指令集的一类单片机。


· 单片机的外设

此次使用的STC89C52RC单片机,有非常丰富的外接硬件。


· 单片机控制硬件

        单片机控制设备的方式

MCU集成有CPU,书写的代码在CPU中执行。

MCU 中还有寄存器(一种存储器),寄存器以8个为一组,每一位寄存器后面的导线上,有一个驱动器(用于增大电流),导线最终连接到 IO 口(1为高电平,0为低电平)

简而言之:CPU通过控制寄存器来控制硬件

另外,单片机不会自动停止一个程序,需要在程序中写入死循环使它不断被执行,从而停止在主函数中不断的执行。

while ( 1 ) {
    //执行代码;
}

       编写程序

需要用到软件 Keil 5

建立工程:

Project -> New uVision Project -> 选择路径 -> 保存(S)-> 否 -> 打开左侧Source Group1 ->

-> 右键新建 Add New Item To... ->  选择C File -> 文件名 -> Add -> 界面上方Option For Target...->

-> Output -> 勾选Create HEX File -> OK 

        烧录程序

需要用到软件STC-ISP

具体方法:选择单片机型号(这里选STC89C52RC/LE52RC)-> 串口号在接入电脑后选择USB->

 -> 打开程序文件 -> 下载/编程 -> 重启单片机

此时程序会烧录至芯片中。


· LED模块

                LED:发光二极管

                接口:P2

                8个LED( D1 ~ D8 )分别对应 P2_0 ~ P2_7 。

                

根据表中的进制转换,赋值给P2 口达到控制LED亮灭目的。

        1、点亮一个LED

点亮一个LED,控制P2口输出的0和1。

在告诉P2口输出时使用16进制(更为方便)。

#include <REGX52.H>

void main () {
	P2 = 0xFE ;    //1111 1110
}

        这行语句相当于让P2口输出一个 1111 1110 的电平,此时会点亮D1。

        2、LED的闪烁

控制LED的闪烁,即让P2口不断输出“ 1111 1110 ” “ 1111 1111 ” 两种电平。

其中间隔为500ms,就可以达到LED以1秒为周期闪烁。

而我们可以通过烧录程序的软件获取延时的函数。

通过STC-ISP 软件中带的 “软件延时计算器” 插件,调整参数,生成C代码,并将其复制到程序中,就得到了延时500ms的函数。(系统频率时晶振管的频率,指令集选Y1)

最后在头文件中加入 #include <INTRINS.H> 以运行函数中的 _nop_() ; 语句。

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

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;
		Delay500ms();
		P2=0xFF;
		Delay500ms();
	}
}

        3、 LED流水灯

流水灯即让P2口以一定的间隔让D1~D8依次亮起。

即以此输出“ 1111 1110 ” “ 1111 1101 ” “ 1111 1011 ” “ 1111 0111 ”......

#include <REGX52.H>
void Delay1ms(unsigned int xms)		
	unsigned char i, j;
	while (xms){
	i = 2;
	j = 199;
	do
	{
		while (--j);
	} while (--i);
	xms--;}
}

void main(){
	while(1){
		P2=0xFE;
		Delay1ms(100);
		P2=0xFD;
		Delay1ms(100);
		P2=0xFB;
		Delay1ms(100);
		P2=0xF7;
		Delay1ms(100);
		P2=0xEF;
		Delay1ms(100);
		P2=0xDF;
		Delay1ms(100);
		P2=0xBF;
		Delay1ms(100);
		P2=0x7F;
		Delay1ms(100);
	}
}

在该代码中 ,我们修改了一下延时函数,使其可以被修改延时时长。

具体方法是:(1)添加函数形参,使其可以被修改

                      (2)写while函数循环,每执行一次,对应时间减一,直到变为0,离开while


· 独立按键模块

        1、按键控制LED亮灭

按键对应端口为P3 口,从左到右K1到K4四个按键分别对应:

P3_1 ; P3_0 ; P3_3 ; P3_4

用按键控制 LED,即通过判断语句,当 P3 为 0 或者 1(分别对应按下和松开)。

#include <REGX52.H>

void main(){
	while(1){
		if(P3_1==0){
			P2_0=0;
		}else{
			P2_0=1;
		}
	}
}

代码满足当K1被按下时,P3_1输出低电平,此时对第一个LED D1输出低电平,使其亮起

反之松开后 P3_1输出高电平,此时对第一个LED D1输出高电平,使其熄灭。

        2、按键控制LED状态

与上一个类似,不同点在于,此时在判断后加入循环,使LED一直处于点亮状态,直到再次按下按键。

特殊的,机械按键在触发时不可避免的有波动,可能造成误判,因此需要在判断后加入延迟,以抵消机械按键的波动。

#include <REGX52.H>

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

void main(){
	while(1){
		if(P3_1==0){
			Delay1ms(20);
			while(P3_1==0);
			Delay1ms(20);
			P2_0=~P2_0;
		}
	}
}

        3、按键控制LED表示二进制

与上类似,只需要将对P2_0 一个LED的控制转变为对 P2 所有LED的控制,并每次按动按键都使P2 对应的值++,即可表示二进制。

#include <REGX52.H>

void Delay(unsigned int xms)		
{
	unsigned char i, j;
	while(xms--){
		i = 2;
		j = 199;
		do
		{
			while (--j);
		} while (--i);
	}
}

void main(){
	unsigned char LEDNum=0;
	while(1){
		if(P3_1==0){
			Delay(20);
			while(P3_1==0);
			Delay(20);
			LEDNum++;
			P2=~LEDNum;
		}
	}
}

        4、按键控制LED移位

这次需要两个按键K1 与 K2 , 即控制P3_1 与 P3_0。

当K1 被按动时,让LED灯向左位移,K2向右。

即:当 P3_1 ==0 时,P2向左移位(使用移位符<<); 反之,P3_0==0 时,P2>>;

#include <REGX52.H>

void Delay(unsigned int xms)
{
	unsigned char i, j;
	while(xms--){
		i = 2;
		j = 199;
		do
		{
			while (--j);
		} while (--i);
	}
}

void main(){
	unsigned char LEDNum=0;
	P2=~0x01;
	while(1){
		if(P3_0==0){
			Delay(20);
			while(P3_0==0);
			Delay(20);
			LEDNum++;
			if(LEDNum>=8){
				LEDNum=0;
			}
			P2=~(0x01<<LEDNum);
		}
		if(P3_1==0){
			Delay(20);
			while(P3_1==0);
			Delay(20);
			if(LEDNum==0){
				LEDNum=7;
			}else{
			LEDNum--;
			}
			P2=~(0x01<<LEDNum);
		}
	}
}

先定义了一个变量 LEDNum ,向左--,向右++,P2只需要在初始状态 0000 0001 做出对应移位 


· 数码管模块

         1、数码管的结构

数码管的断码表(可以理解为对应符号的 “编码” )

         2、静态数码管显示

数码管对应P0 口,将数字的断码赋给 P0 口,即可显示对应的数字。

显示位置有1~8位,由 P2_4 , P2_3 , P2_4 ,控制P0 显示的位置。

#include <REGX52.H>

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

void Nixie(unsigned char Location,Number){
	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[Number];
}

void main(){
	while(1){
		Nixie(7,2);
	}
}

        3、动态数码管显示

与上非常类似,显示后加入一段很短的延时显示下一个数字,如此循环

在while死循环中一直执行,数字会不断以极小间隔闪烁,看上去像同时亮起。

#include <REGX52.H>

unsigned char NixieTable[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F};
void Delay3ms()		//@11.0592MHz
{
	unsigned char i, j;
	i = 6;
	j = 93;
	do
	{
		while (--j);
	} while (--i);
}


void Nixie(unsigned char Location,Number){
	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[Number];
}

void main(){
	while(1){
		Nixie(5,2);
		Delay3ms();
		Nixie(6,0);
		Delay3ms();
		Nixie(4,5);
		Delay3ms();
	}
}

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值