
绪论
我是机械学院大一学生,这学期是通过该课程才开始了解单片机,基础知识是通过自己
查阅资料了解的,由于水平较低,会有些错误或者不合理的地方,希望老师指正。
单片机种类繁多,从基本的51单片机到高级的AVR单片机,凌阳SPMC65单片机,他们
拥有着其他计算机无法取代的作用,如今单片机已经成为一个独立学科。它的出现是近代计
算机技术发展史上的一个重要里程碑,因为它体积小,所以一般都被放在机械的里面,无法
看见。它在这个装置中,起着有很重要的作用,控制着整个机械的运作。它具有以下特点:
体积小、功能强、应用面广、质量轻、价格便宜,既适合人们使用又适合人们去学习它,这
些优点为学习、应用和开发提供了便利条件。如今单片机的使用范围也十分的广:彩电、冰
箱、空调、录像机、VCD、遥控器、游戏机、电饭煲、鼠标、计算器、汽车等等很多地方都
用到了单片机,生活中到处可以看到它的使用之处。
经过了一段时间的学习,我决定向大家简介最简单的51系列单片机,从原理、结构,
常用单片机芯片结构,常用的功能——IO口、定时器、UART口等,这些方面介绍它,并且
在文章的最后我会给出几个例子进行分析,
我的理解:
之所以选择51单片机首先是因为它具有以下的优点:1.开发工具自制容易;2.入门简
单;3.在很长一段时间内,51还是主流,至今为止,51单片机应用最广,并且没有被高级
单片机取代;4.上学期学习了C语言,对单片机的编程开发有少许作用。
原理:
单片机又称单片微控制器,它不是一个完成某一个已经预定好的逻辑功能的芯片,而
是把一个计算机系统集成到一个芯片上。概括的讲,一块芯片就成了一台计算机。我们可以
对它进行编程,用它做些它力所能及的事,而不仅仅是一件已经预定好的事。
我眼里的单片机:
对于微型计算机,一般都是由都是由微型处理器,、储存器、I/O接口、三大功能通
过总线相互交流,工作。单片机也是微型计算机的一种,对于单片机,单片机由运算器、控
制器、存储器、输入输出设备构成。单片机完成其任务的过程,其实也就是单片机执行程
序的过程,即一条条执行的指令的过程,所谓指令就是把要求单片机执行的各种操作用的命
令的形式写(利用汇编语言,C语言等等各种编辑语言)下来,这是我们在对它进行设计时
要做的一个步骤,就是我们希望它做什么,怎么做,通过命令的形式告诉机器,一般而言一
条指令对应着一个基本动作;单片机所能执行的全部指令,就是该单片机的指令系统,对于
不同种类的单片机(AVR,51,凌阳等等不同单片机),其指令系统也是不一样的不同。为
使单片机能自动完成某一特定任务,必须把要解决的问题编成一系列指令(这些指令必须是
选定单片机能识别和执行的指令,因为不同单片机的指令可能会有所不同),这一系列指令
的集合就成为程序,程序需要预先存放在具有存储功能的部件——存储器中。存储器由许多
存储单元(最小的存储单位)组成,就像大楼房有许多房间组成一样,指令就存放在这些单
元里,单元里的指令取出并执行就像大楼房的每个房间的被分配到了唯一一个房间号一样,
每一个存储单元也必须被分配到唯一的地址号,该地址号称为存储单元的地址,这样只要知
道了存储单元的地址,就可以找到这个存储单元,其中存储的指令就可以被取出,然后再被
执行。程序通常是顺序执行的,所以程序中的指令也是一条条顺序存放的,单片机在执行程
序时要能把这些指令一条条取出并加以执行,必须有一个部件能追踪指令所在的地址,这一
部件就是程序计数器PC(包含在CPU中),在开始执行程序时,给PC赋以程序中第一条指
令所在的地址,然后取得每一条要执行的命令,PC在中的内容就会自动增加,增加量由本
条指令长度决定,可能是1、2或3,以指向下一条指令的起始地址,保证指令顺序执行。
结构
1.内部结构:
微处理器:
单片机叫MCU就是微处理器也可以叫微型逻辑控制单元,一般情况下,单片机包含
CPU,但运算能力没有单纯的CPU强大,因为单片机的用途所限,它无需象计算机Cpu那
样强大的运算能力,但单片机一个集成电路中包含了数据存储器相当于电脑的内存
RAM和程序存储器相当于电脑的硬盘和ROM,并且单片机内部一般集成有各种
应用接口,例如串口I2CADDA等模块接口。
存储器:
单片机有三种存储器:
数据存储器:
它是用来存储命令的,即编程人员的程序代码,也是整个机器运作的大脑,这里面存储的内
容将控制整个机器的运作,决定这个机器可以做什么,能够做什么。内部数据RAM用来存
放运算过程的中间值,并用作堆栈区。
数据存储器又可以分为三个区:1.工作寄存器区在MCS-51系列单片机的片内RAM
中,有四个工作寄存器区,分别称为工作寄存器区0~工作寄存器区,每区有八个字节,除
了可以用字节地址号码操作之外,还可以用R0、R1…R7为名称对其操作。用名称进行操
作,称为寄存器寻址,指令代码较为简短。其中R0、R1可以作为间接寻址寄存器,以其
中内容作为地址,能够对片内RAM(或片外RAM的256字节)进行间接寻址。在任何时
刻,只能使用一个工作寄存器区。当前使用那个区,可以通过指令设置PSW中的RS1和
RS0来决定。PSW称为程序状态字,是下面要介绍的特殊功能寄存器。通过设置RS1和
RS0,可以快速切换当前工作寄存器区,适合在不同的程序段中进行保护现场。当前没有使
用的工作寄存器区,不能使用R0、R1…R7等名称,但可以按字节地址对其随意读写。复
位时RS1和RS0皆初始化为0,故此复位后将自动使用工作寄存器区0。
2.位寻址区
位寻址区共有16字节,字节地址为20H~2FH,每个字节中的8个“位”,都有一个“位地址”。
共有128个位,“位地址”的范围为00H~7FH。前面问题所提到的“位地址4EH”,是在“字节
地址29H”中,是第6位。对位寻址区可以按照“位地址”来对某一个位单独进行操作,也可
以按照“字节地址”进行操作,即同时对八个位地址的内容进行操作。MCS-51系列单片机具
有一套专用的“位操作”指令(又称为布尔指令),可对这些位地址进行“与”、“或”、“非”等操
作。这是该系列单片机的特色之一。
3.通用数据区
通用数据区有80字节,只能按“字节地址”(直接或间接寻址)进行操作。在片内80H~FFH
地址范围内,离散的分布着21个特殊功能寄存器(SFR)。8052系列单片机,在80H~FFH
范围内,还有128字节的片内通用RAM,对其操作时,则必须采用“间址”寻址方式。而对
这片地址范围内的特殊功能寄存器只能采用“直接”寻址方式进行操作。特殊功能寄存器中有
11个还可以进行“位寻址”,中也列出了可以位寻址的寄存器以及位地址号码。如果位地址为
空白,则说明该寄存器不能进行“位寻址”。可以看出规律:当字节地址可以被8整除时,该
字节即可以按位寻址。其最低位的“位地址”与“字节地址”相同,其他位的位地址向高位依次
加1。
特殊功能寄存器:
单片机共用21个字节的特殊功能寄存器,这些特殊功能是已经既定好的功能,使用时加以
调用即可,他们连续不断的分布在128个字节的特殊功能存储空间中。21个寄存器的功能
及名称如下:
BF0H
B寄存器
ACCE0H
累加器
PSWD0H
程序状态字
TH2*CDH
定时器/计数器2(高8位)
TL2*CCH
定时器/计数器2(低8位)
RLDH*CBH
外部输入(P1.1)计数器/自动再装入模式时初值
寄存器高八位
RLDL*CAH
外部输入(P1.1)计数器/自动再装入模式时初值
寄存器低八位
T2CON*C8H
T2定时器/计数器控制寄存器
IP
B8H
中断优先级控制寄存器
P3
B0H
P3口锁存器
IE
A8H
中断允许控制寄存器
P2
A0H
P2口锁存器
SBUF99H
串行口锁存器
SCON
98H
串行口控制寄存器
P190H
P1口锁存器
TH18DH
定时器/计数器1(高8位)
TH08CH
定时器/计数器0(高8位)
TL18BH
定时器/计数器1(低8位)
TL08AH
定时器/计数器0(低8位)
TMOD89H
T0、T1定时器/计数器方式控制寄存器
TMOC
88H
T0、T1定时器/计数器控制寄存器
DPH83H
数据地址指针(高8位)
DPL82H
数据地址指针(低8位)
SP81H
堆栈指针
P080H
P0口锁存器
PCON87H
电源控制寄存器
对于SFR的操作也用两种:位操作,字节操作。
程序存储器:
当我们将要使用单片机操作一个机器的时候,我们往往要对其操作进行编程,我们将已经编
程好的程序输入至单片机里,这些程序储存在哪呢?就是程序储存器里了,一般一个单片机
的程序储存器可以存储很多程序,当然啦,执行的时候只能执行一个程序的命令。
输入输出接口
如何使得编程人员与单片机进行交流,即如何把程序员的程序放到单片机中,如何从单片机
中行获取程序,我们必须要用到一种工具完成这个操作,输入输出端口就是为了完成这个目
的而被创造的。一下我用例子给大家介绍一下输入输出端口的结构及其功用。
1.并行端口:
(1)P0:可作为通用I/O端口还可以作为地址/数据线使用。例:设单片机P0.X引脚直接
驱动一个三极管的be结,当单片机先向P0.X输出“1”,其后某一个时刻再用软件
重新读入该引脚却得到的是低电平。这种错误的产生不在于单片机,而在于P0.X错
误的被拉成低电平的缘故。
(2)P1:单功能通用I/O端口,准双向静态口。输出的信息有锁存,输入的有读引脚度
锁存器之分。
(3)P2:输入方面和P0P1一样,输出方面有不同之处
(4)P3:双功能静态I/O端口。
2.串行端口
定时器/计数器
一般他们有两个模式:定时器模式和计数器模式,每个模式有四个工作方式:工作方式0、
工作方式1、工作方式2、工作方式3、他们主要是产生各种时间间隔、记录外部事件发生
的次数等。
例子分析:
设有一个频率小雨500hz的低频脉冲信号由T0引脚进入8031,要该信号每发生一次负跳变,
P1.1引脚就输出一个500μs是同步负脉冲,同时P1.2输出一个1ms的正脉冲。时钟振荡频
率为6MHz.
BEGIN:MOVTMOD,#06H;设置T0为计数器模式下的工作方式2
MOVTH0#OFFH;计数器计数1次就溢出
MOVTL0#0FFH
CLRP1.2;P1.2初始为低电平
SETBTR0;启动计数器
DEL1:JBCTF0RESP1;检测外部信号是否出现负跳变
AJMPDEL1
RESP1:CLRTR0;停止计数
MOVTMOC#O2H;重设T0为定时器模式下工作方式2
MOVTH0#06H;定时500μs
MOVTH0#06H
SETBP1.2;P1.2输出高电平
CLRP1.1;P1.1输出低电平
SETBTR0;启动定时器
DEL2:JBCTF0,RESP2;检测第一次定时500μs到否
AJMPDEL2
RESP2:SETBP1.1;P1.1的输出恢复到高电平
DEL3:JBCTF0,RESP3
AJMPDEL3
RESP3:CLRP1.2
CLRTR0;停止定时
AJMPBEGIN
中断控制系统
中断指的是某事件发生时,为了对该事件进行处理,CPU终止现行程序的执行,转去执行处
理该事件的程序,待处理完毕后,在返回执行原来程序。比如:数控车床的停止按钮,按下
该按钮后,车床停止进给运动,只做旋转运动,按下继续按钮后,机床继续运动,这就是中
断控制系统在车床上的一个应用.一下向大家介绍一个例子:
例子:
SETEA;开全局中断
SETEX0;允许外部中断
SETPX0;外部中断
SETBIT0;中断申请边沿触发
MOVR2,#59;R2为打印计数器
MOVR0,#30H;R0为地址指针
MOVR1,#07H;R1为打印机地址
MOVA,@R0;
MOVX@R1,A;输出第一个数据
SJMP$;
ORG0003H;中断服务程序
LJMPROUT;
ROUT:PUSHPSW;保护现场
PUSHACC;
INCR0;修改指针
MOVA,@R0;
MOVX@R1,A;输出数据
DECR2;修改计时器
MOVA,R2;转存至A
JNZNEXT;
数据输出完毕后关中断,否则继续打
印
CLREX0;关中断
NEXT:POPACC;恢复现场
POPPSW;
RETI;中断返回
时钟振荡电路
之前已经为大家,介绍了大致的单片机开发程序,这里为大家献上一个比较复杂的数字钟的
程序,由于本人只是业余学了一点点程序,所以分析的地方不是很透彻,只是对大致的框架
进行了分析,希望老师指正。
数字钟例子及分析:
#include
#include
//#define
#defineTM_condXBYTE[0x8000]
#defineAM_condXBYTE[0x8001]
#defineTM_minuteXBYTE[0x8002]
#defineAM_minuteXBYTE[0x8003]
#defineTM_hourXBYTE[0x8004]
#defineAM_hourXBYTE[0x8005]
#defineTM_weekXBYTE[0x8006]
#defineTM_dayXBYTE[0x8007]
#defineTM_monthXBYTE[0x8008]
#defineTM_yearXBYTE[0x8009]
#defineREG_AXBYTE[0x800a]
#defineREG_BXBYTE[0x800b]
#defineREG_CXBYTE[0x800c]
#defineREG_DXBYTE[0x800d]
#defineRAM_114XBYTE[0x800e]
#defineucharunsignedchar
#defineuintunsignedint
sbitDIN=P1^0;
sbitLOAD=P1^1;
sbitCLK=P1^2;
sbitMANU=P1^3;
sbitSAY=P1^4;
sbitDATE=P1^5;
sbitrestchip=P1^6;
sbitPLAY=P1^7;
ucharxdatai=0,j=0,count=0;
uintxdatadat;
//ucharxdata
uintxdatatime_buf[17];
uintxdatat_buf[17];
ucharcodetable[]=
{0x3f,0x06,0x5b,0x4f,0x66,
0x6d,0x7d,0x07,0x7f,0x6f};
ucharcodespeak_buf[]=
{0x00,0x01,0x02,0x03,0x04,0x05,
0x06,0x07,0x08,0x09,0x0a,0x0b,
0x0c,0x0d,0x0e,0x0f,0x10,0x11};
ucharxdataspea[15];
/*延时程序*/
voiddelay(uchart)
{
ucharm,n,s;
for(m=t;m>0;m--)
{for(n=20;n>0;n--)
for(s=248;s>0;s--);}
}
/设置时钟/
voidttime()
{
REG_B=0XFA;
TM_cond=time_buf[5];
TM_minute=time_buf[4];
TM_hour=time_buf[3];
TM_day=time_buf[2];
//TM_week=time_buf[4];
TM_month=time_buf[1];
TM_year=time_buf[0];
REG_B=0X7A;}
/*读时钟芯片中的数据*/
read_time()
{ucharxdataa;
do{a=REG_A;}
while((a&0x80)==0x80);
time_buf[11]=AM_cond;
time_buf[10]=AM_minute;
time_buf[9]=AM_hour;
time_buf[8]=TM_day;
time_buf[7]=TM_month;
time_buf[6]=TM_year;
time_buf[5]=TM_cond;
time_buf[4]=TM_minute;
time_buf[3]=TM_hour;
time_buf[2]=TM_day;
time_buf[1]=TM_month;
time_buf[0]=TM_year;
}
/*此子程序输入的是两八位的数据
前面的是命令后面的是数据*/
voidnd_led(ucharcom,uchardat)
{
ucharADS,n,m;
LOAD=0;
n=0;
while(n<16)
{
if(n<8)
ADS=com;
el
ADS=dat;
for(m=8;m>=1;m--)
{
DIN=ADS&0x80;
ADS<<=1;
CLK=1;
CLK=0;
}
n=n+8;
}
LOAD=1;
}
/*发送时钟数据到数码管驱动芯片*/
nd_time(uchara,ucharb)
{ucharn,m=0;
for(n=a;n<=b;n++)
{m=m|0x01;
nd_led(m,table[speak_buf[n]]);
}
}
/*打开时钟芯片*/
voidstart_time()
{
restchip=0;
restchip=1;
REG_A=0x2f;
REG_B=0xfa;
}
/*报À时子程序*/
speak(uchara)
{
PLAY=0;
P3=P3|a;
delay(20);
PLAY=1;
P3=P3|0xff;
}
/*time_buf转程序*/
chan(uinta)
{
while(a/10)
{spea[j]=a%10;
a=a/10;
j++;
if(j==14)
{j=0;}}
spea[j]=a;
}
/*---------------*/
ti_sp()
{ucharn;
for(n=0;n<6;n++)
{chan(time_buf[n]);}
}
/*-------------*/
t_sp()
{ucharn;
for(n=0;n<6;n++)
{chan(t_buf[n]);}
}
/*报时缓冲子程序*/
speak_huan()
{ucharn;
for(n=0;n<14;n++)
{ti_sp();
nd_time(8,13);
switch(n)
{ca3:speak(speak_buf[n]),speak(0x0b);break;
ca5:speak(speak_buf[n]),speak(0x0c);break;
ca7:speak(speak_buf[n]),speak(0x0d);break;
ca9:speak(speak_buf[n]),speak(0x0e);break;
ca11:speak(speak_buf[n]),speak(0x0f);break;
ca13:speak(speak_buf[n]),speak(0x10);break;
default:if(n<3)speak(speak_buf[n]);break;}
if((n==4)||(n==6)||(n==8)||(n==10)||(n==12))
{if(spea[n]==0)
continue;
elif(spea[n]==1)
{speak(0x0a);}
el
{speak(speak_buf[n]);
speak(0x0a);
}
}
}}
/*显示日历子程序*/
reli()
{ucharn,m;
for(n=7,m=12;n>=0;n--,m--)
{read_time();
nd_time(n,m);
speak(0x11);
delay(20);
}}
/*数据缓冲和数据上限设定*/
can(uinta,uintb)
{if(dat==b)
{dat=a;}
if(count==1)
{time_buf[i]=dat;
ti_sp();
if(i<=4)
nd_time(8,13);
el
nd_time(0,7);
}
elif(count==2)
{t_buf[i]=dat;
t_sp();
if(i<=4)
nd_time(8,13);
el
nd_time(0,7);
}
}
/*按键识别子程序*/
kk()
{if(DATE==0)
{delay(2);
if(DATE==0)
i++;
if(i==8)
{i=0;}}
if(SAY==0)
{delay(2);
if(SAY==0)
{if(count==1)
dat=time_buf[i];
el
dat=time_buf[i+6];
dat++;
switch(i)
{ca0:can(0,60);break;
ca1:can(0,60);break;
ca2:can(0,24);break;
//ca3:can(0,7);break;
ca3:can(0,30);break;
ca4:can(0,12);break;
ca5:can(2004,2009);break;
}
}}}
/*--------------------------*/
voidkey(void)
{while(1)
{if(MANU==0)
{delay(2);
if(MANU==0)
{count++;
if(count==3)
count=0;
if(count==1)
kk();
if(count==2)
kk();
if(count==0)
{read_time();
ti_sp();
nd_time(8,13);}
}
}
if(SAY==0)
{delay(2);
if(SAY==0)
{ti_sp();
speak_huan();}}
if(DATE==0)
{delay(2);
if(DATE==0)
{ti_sp();
reli();}}}}
/*主函数*/
main(void)
{
start_time();
nd_led(0x0c,0x01);//停机方式
nd_led(0x09,0x00);//译码模式不译码
nd_led(0x0a,0x08);//亮度中
nd_led(0x0b,0x07);//扫描界限全部扫描
while(1)
{read_time();
ti_sp();
nd_time(8,13);
if((MANU==0)||(SAY==0)||(DATE==0))
{delay(2);
if((MANU==0)||(SAY==0)||(DATE==0))
key();
}
}
以上由于能力有限只对大致的思路了解,所以分析的地方不是很多,而且很多具体的不是很
认识,希望老师指正,下学期会更加认真的学习的。
总结
因为是机械学院的大一学生,所以对单片机基本处于空白状态,这学期的电子实训课程把我
第一次领进了单片机的世界,通过这次课程我了解到了,单片机与我们机械一族有着密不可
分的联系,从海上的轮船到天上的飞机,无一缺少单片机的控制,首先单片机就引起了我的
兴趣。
其次,我发现单片机既是一个单独的学科,又与各个学科紧密联系,独立,是因为单片机的
发展已经从计算机中独立出来,成为了一个专业的方向,需要更加专业的知识去学习它,但
是单片机的发展,需要其他方面的辅助,研制出更好的单片机必须要与物理数学等学科的辅
助,同时编出一套好的单片机的程序又需要一个很好的计算机编程能力,所以,需要我对其
他的学科也要好好的学习。
本文发布于:2023-03-04 20:53:51,感谢您对本站的认可!
本文链接:https://www.wtabcd.cn/zhishi/a/167793443111123.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文word下载地址:单片机的工作原理.doc
本文 PDF 下载地址:单片机的工作原理.pdf
| 留言与评论(共有 0 条评论) |