51单片机:与15系列的区别---最简单的几个模块

自从蓝桥杯省赛完成之后,就开始准备学习51单片机。相对于蓝桥杯比赛所用的板子来说,这个单片机还是有所不同的。在管脚,阴阳极上有些区分。因此,开贴做笔记记录一下。

首先介绍几个最为基础的模块。这几个模块改动都不大,原理也相近类似。

目录

一、LED灯

二、蜂鸣器

三、数码管

四、独立按键

五、矩阵按键

一、LED灯

根据原理图,可以看到LED1是P20管脚,与15系列的相同,将其置1就是亮起,置0就是熄灭。写法与15系列的单片机有些类似。

在LED灯的循环点亮的程序,与15单片机也相同。由于移位之后自动补0(亮起),所以我们要通过取反的程序来写。

 

拓展:左移右移通过库函数实现流水灯

我们需要调用另一个头文件:#include “intrins.h”,

在这里面,_cror_函数是右移;_crol_函数是左移。

注意:此函数与我们自己写的移位语句不同的是:移位语句左右移位之后,丢掉的位自动补0;而这两个函数在移位之后,移出去的位将会补在数的后面

对于这两个函数的使用:_crol_(要移动的变量,移动几位)

例如:LED=_crol_(LED,1); 我们要提前规定LED的值是0XFE,从0XFE向左开始逐渐移动1位。(后面的数字改成2之后,就是移动两位,隔一个灯移动一次)。

程序:LED灯循环,间隔1秒。

#include "reg52.h"
#include "intrins.h"

#define uchar unsigned char
#define uint unsigned int
	
#define LED		P2//采用宏定义的方法,将P2端口进行定义

uchar i=0;

void Delayms(uint ms);//1毫秒 

void main()
{
	while(1)
	{
		LED=0XFE;
		for(i=0;i<8;i++)
		{
			LED=_crol_(LED,1);
			Delayms(1000);
		}
	}
}

void Delayms(uint ms)//1毫秒延时函数
{
	uint i,j;
	for(i=ms;i>0;i--)
	for(j=115;j>0;j--);
}

二、蜂鸣器

有源蜂鸣器:内部频率不可改变,因此音色不可改变(15单片机上的,此类蜂鸣器控制简单,只需要置1或置0即可关闭或打开)。

无源蜂鸣器:可改变内部频率、改变音色(改变延时的时间);改变占空比(改变声音大小)。(51单片机上的,需要持续输出波形才可以使用蜂鸣器)。

通过原理图可以看出,与蜂鸣器相连接的是五线四项步进电机里的P25口。打开蜂鸣器:让蜂鸣器输出持续的波形信号(时刻发生改变);关闭蜂鸣器:让蜂鸣器输出高或低的脉冲信号(不改变)

波形信号的频率:1.5—5KHZ;我们可以使用频率1KHZ的,周期T=1ms(500微秒高电平,500微秒低电平)。

注意:蜂鸣器响的时间由i和延时的时间共同控制。

           延时的时间越长,声音就越低沉;延时的时间越短,声音就越尖细。

            占空比越大,声音越大。

程序:可改变占空比来改变蜂鸣器声音大小   延时程序复制的stc软件里的。

#include "reg52.h"

#define uchar unsigned char
#define uint unsigned int
	
sbit BEEP=P2^5;

uint i=2000;

void delay_10us(uint ten_us);//延时10微秒程序


void delay_10us(uint ten_us)//延时10微秒程序
{
	while(ten_us--);
}

void main()
{
	uint i=2000;//控制蜂鸣器发出声音的时间,
	            //蜂鸣器响的时间由i和延时的时间共同控制
	while(1)
	{
		while(i--)
		{
			BEEP=0;//蜂鸣器低电平
			delay_10us(10);
			BEEP=1;//蜂鸣器高电平
			delay_10us(190);
		}
		i=0;BEEP=0;//关闭蜂鸣器
	}
}

三、数码管

1、共阳共阴极数码管:

共阳极数码管是指将所有发光二极管的阳极接到一起形成公共极(COM)的数码管,共阳极数码管在应用时应将公共极 COM 接到+5V(低电平点亮)

共阴极数码管(本单片机)是指将所有发光二极管的阴极接到一起形成公共极(COM)的数码管,共阴极数码管在应用时应将公共极 COM 接到地线GND上。(高电平点亮)

所以这个板子上的数码管显示与15系列的正好相反。

2、74HC245芯片和74HC138芯片

   要学会阅读芯片手册。

      74HC245芯片是有个DIR管脚的,该管脚控制了电流的输出方向,高电平的时候是从A-B输出的;低电平是从B-A输出的。我们需要的是高电平。

      74HC138芯片俗称38译码器,三个输入端(A0、A1、A2),8个输出端(Y0、Y1、Y2、Y3、Y4、Y5、Y6、Y7)。通过阅读芯片手册中的真值表来了解如何通过输入端控制输出端(即控制哪个数码管位选的打开)。

真值表如下:L是低电平,H是高电平。当8个端口为低电平的时候,该数码管的位选就会打开。

 

注意:LED8和Y7都表示的板子上最左边第一个数码管。

LSA、LSB、LSC是对38译码器的三个输入管脚的定义,用来控制数码管的位选。

在显示一个数码管之后,就要对数码管进行消隐的操作(让段选为0X00),目的是让数码管的显示更加清晰,清除数码管底部的暗红色痕迹。

程序:8个数码管依次显示1-8

#include <reg52.h>

#define uchar unsigned char
#define uint unsigned int
	
#define SMG_duanxuan   P0//对整个P0端口进行定义 用宏定义
                         //是对整个段选端口进行定义
/**********************定义38译码器的输入管脚**************/

sbit LSA=P2^2;//对单个管脚进行定义用sbit
sbit LSB=P2^3;
sbit LSC=P2^4;

uchar code tab[]={0X3F,0X06,0X5B,0X4F,0X66,0X6D,0X7D,0X07,0X7F,0X6F,0X40,0X00};//0-9,横线,关闭
uchar Smg[8]={0};
uchar Smg_num=0;

void Delayms(uint ms);//1毫秒延时
void Smg_display();//数码管显示函数

void main()
{
	while(1)
	{
		Smg_display();
	}
}

void Smg_display()//数码管显示函数
{
	uchar Smg_num=0;
	
	for(Smg_num=0;Smg_num<8;Smg_num++)
	{
		switch(Smg_num)
		{
			case 0:LSA=1;LSB=1;LSC=1;break;//数码管1
			case 1:LSA=0;LSB=1;LSC=1;break;
			case 2:LSA=1;LSB=0;LSC=1;break;
			case 3:LSA=0;LSB=0;LSC=1;break;
			case 4:LSA=1;LSB=1;LSC=0;break;
			case 5:LSA=0;LSB=1;LSC=0;break;
			case 6:LSA=1;LSB=0;LSC=0;break;
			case 7:LSA=0;LSB=0;LSC=0;break;//数码管8
		}
		SMG_duanxuan=tab[Smg[Smg_num]];
		//P0=tab[Smg[Smg_num]];//直接控制P0口也行
		Smg[0]=1;Smg[1]=2;Smg[2]=3;Smg[3]=4;Smg[4]=5;Smg[5]=6;Smg[6]=7;Smg[7]=8;
		Delayms(1);
		SMG_duanxuan=0X00;//消隐,让数码管的显示更加清晰
	}
}

void Delayms(uint ms)//1毫秒延时
{
	uint i,j;
	for(i=ms;i>0;i--)
	for(j=114;j>0;j--);
}

四、独立按键

I/O口作为输入的实例   按键按下,I/O口为低电平。

按键的抖动:通常是5-10ms的范围,所以无论是按下还是松手,我们都要进行一个软件延时。一般延时5毫秒即可。

         

 

在这里要注意的是,不同于15单片机的地方在于按键的顺序,P31管脚是按键1,P30管脚是按键2.

程序:按下第一个按键,LED1亮起;按下第二个按键,LED2亮起;按下第三个按键,数码管1显示8;按下第四个按键,数码管2显示8;

#include <reg52.h>

#define uchar unsigned char
#define uint unsigned int

uchar code tab[]={0X3F,0X06,0X5B,0X4F,0X66,0X6D,0X7D,0X07,0X7F,0X6F,0X40,0X00};//0-9,横线,关闭
uchar Smg[8]={2,1,10,0,6,10,8,8};
uchar Smg_num=0;
	
/******************对4个独立按键的管脚进行定义*********************/

sbit KEY1=P3^1;
sbit KEY2=P3^0;
sbit KEY3=P3^2;
sbit KEY4=P3^3;

/******************对LED灯进行定义*********************/

sbit LED1=P2^0;
sbit LED2=P2^1;

/******************定义38译码器的输入管脚*******************/

sbit LSA=P2^2;   //对单个管脚进行定义用sbit
sbit LSB=P2^3;
sbit LSC=P2^4;
#define SMG_duanxuan   P0//对整个P0端口进行定义 用宏定义
                         //是对整个段选端口进行定义

void Keyscan();
void Smg_display();//数码管显示函数
void Delayms(uint ms);//1毫秒延时

void main()
{
	
	while(1)
	{
		Smg_display();
		Keyscan();
	}
}

void Smg_display()//数码管显示函数
{
	uchar Smg_num=0;
	
	for(Smg_num=0;Smg_num<8;Smg_num++)
	{
		switch(Smg_num)
		{
			case 0:LSA=1;LSB=1;LSC=1;break;//数码管1
			case 1:LSA=0;LSB=1;LSC=1;break;
			case 2:LSA=1;LSB=0;LSC=1;break;
			case 3:LSA=0;LSB=0;LSC=1;break;
			case 4:LSA=1;LSB=1;LSC=0;break;
			case 5:LSA=0;LSB=1;LSC=0;break;
			case 6:LSA=1;LSB=0;LSC=0;break;
			case 7:LSA=0;LSB=0;LSC=0;break;//数码管8
		}
		SMG_duanxuan=tab[Smg[Smg_num]];
		//P0=tab[Smg[Smg_num]];
		Delayms(1);
		SMG_duanxuan=0X00;//消隐,让数码管的显示更加清晰
	}
}

void Keyscan()
{
	if(KEY1==0)
	{
		Delayms(5);//软件消抖
		if(KEY1==0)
		{
			LED1=0;
		}
		while(!KEY1);//软件消抖
	}
	else if(KEY2==0)
	{
		Delayms(5);
		if(KEY2==0)
		{
			LED2=0;
		}
		while(!KEY2);
	}
	else if(KEY3==0)
	{
		Delayms(5);
		if(KEY3==0)
		{
			Smg[0]=8;
		}
		while(!KEY3);
	}
	else if(KEY4==0)
	{
		Delayms(5);
		if(KEY4==0)
		{
			Smg[1]=8;
		}
		while(!KEY4);
	}
}

void Delayms(uint ms)//1毫秒延时
{
	uint i,j;
	for(i=ms;i>0;i--)
	for(j=114;j>0;j--);
}

五、矩阵按键

根据原理图,我们可以看出我们可以看出:矩阵按键的管脚在P10—P17,

我们宏定义矩阵按键的管脚          #define KEYSCAN16   P1

程序的架构与15系里的基本类似,第一列是:让P1=0XF7,判定第一列是否被下,进行消抖检测,再次判断是否被按下,根据P1的值来进行程序的实现,抬手消抖。

不同之处在于列数和行数的表示方法有所不同,

第一列:0XF7;第二列:0XFB;第三列:0XFD,第四列:0XFE。

检测这一列中第几行被按下:第一行:0X7列;第二行:0XB列 第三行:0XD列;第四行:0XE列。

程序:

void Keyscan16()
{
	KEYSCAN16=0XF7;
	if(KEYSCAN16!=0XF7)
	{
		Delayms(5);
		if(KEYSCAN16!=0XF7)
		{
			switch(KEYSCAN16)
			{
				case 0X77:Smg[0]=1;break;
				case 0XB7:Smg[1]=2;break;
				case 0XD7:Smg[2]=3;break;
				case 0XE7:Smg[3]=4;break;
			}		
			while(KEYSCAN16!=0XF7);
		}
	}
	
	KEYSCAN16=0XFB;
	if(KEYSCAN16!=0XFB)
	{
		Delayms(5);
		if(KEYSCAN16!=0XFB)
		{
			switch(KEYSCAN16)
			{
				case 0X7B:Smg[4]=5;break;
				case 0XBB:Smg[5]=6;break;
				case 0XDB:Smg[6]=7;break;
				case 0XEB:Smg[7]=8;break;
			}		
			while(KEYSCAN16!=0XFB);
		}
	}
	
	KEYSCAN16=0XFD;
	if(KEYSCAN16!=0XFD)
	{
		Delayms(5);
		if(KEYSCAN16!=0XFD)
		{
			switch(KEYSCAN16)
			{
				case 0X7D:Smg[0]=6;break;
				case 0XBD:Smg[1]=6;break;
				case 0XDD:Smg[2]=6;break;
				case 0XED:Smg[3]=6;break;
			}		
			while(KEYSCAN16!=0XFD);
		}
	}
	
	KEYSCAN16=0XFE;
	if(KEYSCAN16!=0XFE)
	{
		Delayms(5);
		if(KEYSCAN16!=0XFE)
		{
			switch(KEYSCAN16)
			{
				case 0X7E:Smg[0]=8;break;
				case 0XBE:Smg[1]=8;break;
				case 0XDE:Smg[2]=8;break;
				case 0XEE:Smg[3]=8;break;
			}		
			while(KEYSCAN16!=0XFE);
		}
	}
}
  • 3
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
单片机原理与应用 综合实验报告 LCD1602字符液晶滚动演示程序 专业班级: 姓  名: 学 号: 时 间: 指导教师: 2012年 05月 23日 LCD1602字符液晶滚动演示程序 摘要:本设计以单片机作为LCD液晶显示系统控制器为主线,基于单片机89C51,采用的 液晶显示器是LCD1602,主要用来显示字母、数字、符号,滚屏、左右移动以及实时控制 功能。同时也对部分芯片和外围电路进行了介绍和设计,并附以系统结构框图加以说明 ,着重介绍了本系统应用的各硬件接口技术和各个接口模块的功能及工作过程。本设计 还介绍了显示原理、硬件电路和软件部分的设计原理。 关键词:1602液晶显示器 89C51单片机 并行通信 1 引言: 液晶显示器(LCD)具有功耗低、体积小、重量轻、超薄等许多其它显示器无法相比的 优点。近几年来被广泛用于单片机控制的智能仪器、仪表和低功耗电子产品中。液晶显 示器分为字符型LCD显示模块和点阵型LCD显示模块。字符型LCD是一种用5×7点阵图形来 显示字符的液晶显示器。点阵型液晶可显示用户自定义的任意符号和图形,并可卷动显 示,它作为便携式单片机系统人机交互界面的重要组成部分被广泛应用于实时检测和显 示的仪器仪表中。支持汉字显示的点阵型液晶在现代单片机应用系统中是一种十分常用 的显示设备,汉字BP机、手机上的显示屏就是点阵型LCD。点阵型LCD是现代单片机应用 系统中最常用的人机交互界面之 利用单片机控制液晶显示系统的原理,完成单片机液晶显示系统的设计,我希望能够 触类旁通,灵活应用其他型号的液晶显示控制器。将来如果有机会从事这方面的工作, 要运用的液晶显示控制器不一定是KS0108,但这次毕业设计中学到的东西为此打下了良 好的基础,相信自己能做好这方面的工作。 2 总体设计方案 2.1 设计思路 2.1.1 本设计主要是通过控制89C51单片同的引脚来控制LCD1602显示给定的符号、字母、数字 ,以及控制显示内容的垂直移动和水平移动。由于LCD1602的字符有相应的字符代码,不 用编写字库,因此在设计时对方案的选择就只考虑单片机与显示器的数据传送类型,即 串行通信和并行通信。 (1)方案确立: 方案一:串行通信 串行通信是反映一个数据的所有位按一定的顺序和方式,一位一位地通过串行输入/ 输出口进行传送。由于串行通信是数据的逐位顺序传送,在进行通信时,只需一根传输 线,其传送的数据位多且通信距离长。串行通信方式如图1所示。 方案二:并行通信 采用并行传送方式在微机与外部设备之间进行数据传送的接口叫并行接口。主要特点 :一是同时并行传送的二进位数就是数据宽度;二是在计算机与外设间采用应答式的联 络信号来协调双方的数据操作。传送的数据位1- 128位,一般为8位。单片机与外部设备之间也通常采用8位并行I/O接口进行短距离的通 信其传输距离近,传送方式单一,每次传送一个字或一个字节。并行通信方式如图2所示 。 图1 串行通信方式 图2 并行通信方式 由于本设计的传输距离不远,所用I/O口不多,所以方案二既可满足课程设计的基本 要求又能充分发挥其优势,电路简单,易控制,所以采用该方案。 2.2 设计方框图 图3 系统总体方框图 3 设计原理分析 本设计主要是通过控制89C51单片同的引脚来控制LCD1602显示给定的符号、字母、数 字,以及控制显示内容的垂直移动和水平移动。在控制LCD1602过程中主要是通过LCD16 02显示模指令和单片机的中断嵌套来实现的。由于在编程时最主要的就是使用LCD1602显 示模指令来实现写指令和写数据功能,所以下面我给出其显示模指令集、写操作时序及 RAM地址映射。 LCD1602显示模指令集: (1)清屏 功能:清DDROM值和AC值 (2)归位 功能:光标复位,光标返回到地址00H (3)输入方式设置 功能:设置光标,画面移动方式。 其中:I/D=1:数据读写操作后,AC 自加一; I/D=0:数据读写操作后,AC 自减一; S=1:数据读写操作,画面平移; S=0:数据读写操作,画面不动; (4)显示开关控制 功能:设置显示、光标和闪烁开关。 其中:D 表示显示开关,D=1 为开,D=0 为关; C 表示光标开关,C=1 为开,C=0 为关; B 表示闪烁开关,B=1 为开,B=0 为关。 (5)光标、画面位移 功能:光标、画面移动。 其中:S/C=1 画面移动一个字符位; S/C=0 光标移动一个字符位; R/L=1:右移;R/L=0 左移。 (6)功能设置 功能:工作方式设置(初始化指令)。 其中:DL=1,8 位数据接口; DL=0,4 位数据接口; N=1,两行显示;N=0,一行显示; F=1,5*10 点阵显示;F=0,5*7 点阵显示。 (7)CGRAM 地址
### 回答1: 51单片机的串口通信例程应该包含以下几个步骤: 1. 配置串口通信的引脚,一般来说要设置 RX 和 TX 引脚,还有数据位、停止位、校验位等参数。 2. 初始化串口,设置波特率、数据位、停止位、校验位等参数。 3. 在主函数中,使用串口发送函数将数据发送出去,例如使用 `UART_Send_Data` 函数,将字符串发送到串口。 4. 在主函数中,使用串口接收函数接收数据,例如使用 `UART_Receive_Data` 函数,将串口接收到的字符串保存到缓冲区中。 5. 在主函数中,使用相应的函数处理接收到的数据。 具体代码可以参考下面的例子: ```c #include <reg51.h> // 配置串口通信的引脚 sbit UART_RX = P3^0; sbit UART_TX = P3^1; // 初始化串口,设置波特率为 9600 void UART_Init() { SCON = 0x50; // 设置数据位、停止位、校验位等参数 TMOD = 0x20; // 设置计数器工作方式 TH1 = 0xFD; // 设置波特率 TL1 = 0xFD; TR1 = 1; // 开启计数器 ES = 1; // 开启串口中断 } // 串口发送函数,将字 ### 回答2: 编写一个51单片机串口通信例程的步骤如下: 1. 首先,需要设置串口的波特率、数据位、停止位和校验位等参数。可以使用串口控制寄存器(SCON)和波特率发生器(TH1)进行设置。 2. 初始化串口控制寄存器SCON,设置串口模式为模式1,打开串口中断允许位。 3. 设置波特率,根据波特率的公式,计算出需要设置的TH1的值,并将其赋给TH1寄存器。 4. 配置串口引脚,将引脚P3.0和P3.1分别设置为串口通信的接收和发送引脚。 5. 编写发送函数,将需要发送的数据以字节形式写入串口发送寄存器SBUF,发送函数可以使用循环发送,以保证数据完全发送。 6. 编写接收函数,可以使用串口中断接收数据,并将接收到的数据存储在一个缓冲区中。 7. 在主函数中调用发送函数,将需要发送的数据发送出去。 8. 在主函数中调用接收函数,将接收到的数据逐个取出并进行处理。 9. 可以结合其他功能模块,如定时器和中断等,实现更加复杂和高效的串口通信功能。 以上就是编写51单片机串口通信例程的基本步骤。具体的代码实现可以根据具体的硬件平台和需求进行调整和优化。 ### 回答3: 51单片机串口通信的例程主要包括初始化串口、发送数据和接收数据三个部分。 首先,需要设置串口的波特率、数据位、停止位和校验位等相关参数。例如,将波特率设置为9600bps,数据位设置为8位,停止位设置为1位,无校验位。采用以下代码实现串口的初始化: ```c #include <reg51.h> void init_serial() { TMOD |= 0x20; // 设置Timer1为模式2,8位自动重装计数器 TH1 = 0xFD; // 波特率为9600 TL1 = 0xFD; PCON |= 0x80; // 波特率不加倍 SCON = 0x50; // 串口工作在模式1,允许接收 TR1 = 1; // 启动Timer1 } ``` 接下来,可以编写发送数据的函数,例如,发送一个字节的数据并等待发送完成。 ```c void send_data(unsigned char dat) { SBUF = dat; // 将数据放入发送缓冲区 while (!TI); // 等待发送完成 TI = 0; // 发送完成标志复位 } ``` 最后,可以编写接收数据的函数,例如,循环接收并返回一个字节的数据。 ```c unsigned char receive_data() { while (!RI); // 等待接收完成 RI = 0; // 接收完成标志复位 return SBUF; // 返回接收的数据 } ``` 在主函数中,可以调用以上三个函数来实现串口通信。例如,发送数据0x55,并通过串口接收一个字节的数据。 ```c void main() { init_serial(); // 初始化串口 send_data(0x55); // 发送数据0x55 unsigned char received = receive_data(); // 接收一个字节的数据 } ``` 以上就是一个简单51单片机串口通信的例程,通过初始化串口、发送数据和接收数据实现了基本的串口通信功能。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值