自从蓝桥杯省赛完成之后,就开始准备学习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
#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
#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);
}
}
}
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)