外部:
单片机:在一片集成电路芯片上集成微处理器(CPU)、存储器(ROM和RAM)、I/O接口电路,从而构成了单芯片微型计算机,即单片机(single chip Microcomputer)也叫微控制器(MCU)
CPU( Central Processing Unit ):由运算和控制逻辑组成,同时还包括中断系统和部分外部特殊功能寄存器;
RAM( Random-Access Memory ):用以存放可以读写的数据,如运算的中间结果、最终结果以及欲显示的数据;
ROM (Read-Only Memory):用以存放程序、一些原始数据和表格;
I/O(input/output)口:四个8位并行I/O口,既可用作输入,也可用作输出;
T/C (timer/counter):两个定时/记数器,既可以工作在定时模式,也可以工作在记数模式;
不同公司产不同名字的芯片。但规范是一样的。
Intel公司1980年推出了MCS-51系列单片机:集成 8位CPU、4K字节ROM、128字节RAM、4个8位并口、1个全双工串行口、2个16位定时/计数器。寻址范围64K
Intel:80C31、80C51、80C32、80C52、87C52
ATMEL:AT89C51、AT89C52、AT89C2051等;
STC:89C51、89C52、90C51、STC15w
下面是芯片的样子,不同样子即不同封装格式
电平特性
数字电路中只有两种电平:高和低
单片机为TTL电平: 高 +5V 低 0V
RS232电平:计算机的串口 高 -12V 低+12V
所以计算机与单片机之间通讯时需要加电平转换芯片max232等其他芯片
一般使用USB-TTL烧录器,或者自己焊接MAX232,如下图
常用双列直插式,可以看到它是有一个半圆缺口,这是你分辨引脚的标记,面对半圆缺口,从左到右分别是1-40个引脚,
引脚有什么功能呢,其实就只能输入输出,即I/O。你可以输出5V或者0V,也可以读取电平5V或者0V。
注意代码中
5V->1 高电平
0V->0 低电平
如果你要较真,用电表测,它可能都不是整整的5V或者0V,是一定范围内,算是高电平,好像是3-5V吧。
1-8引脚是P1,9是RST。
10-17是P3,但它们还有第二功能。就说他们可以输入输出高电平低电平外,还有别的作用。如下图。编写代码时能体现。
20是GND即接地,40是VCC,5V,其它自行了解。
烧写(下载)代码到单片机,其实也是PC和单片机的通信,可以通过上面的USB-TTL,进行串口通信,连接单片机,VCC->VCC GND->GND TXD->RXD RXD->TXD(注意串口两个引脚是交叉接。)
它们也可以进行正常的串口通信。
51单片机最小系统
单独一块51芯片是工作不了的,他需要两部分驱动电路,复位电路和时钟电路
时钟电路
心脏起搏器。
51 单片机上的时钟管脚:
XTAL1(19 脚) :芯片内部振荡电路输入端。
XTAL2(18 脚) :芯片内部振荡电路输出端。
一般来说晶振可以在1.2 ~ 12MHz 之间任选,常用11.9562MHz
电容可以在20 ~ 40pF 之间选择
复位电路
在单片机系统中,复位电路是非常关键的,当程序跑飞(运行不正常)或死机(停止运行)时,就需要进行复位。
复位引脚RST( 第9 管脚) 出现2个机器周期以上的高电平时,单片机就执行复位操作。如果RST 持续为高电平,单片机就处于循环复位状态。
上电瞬间,电容两端电压不能突变,此时电容的负极和RESET 相连,电压全部加在了电阻上,RESET 的输入为高,芯片被复位。随之+5V电源给电容充电,电阻上的电压逐渐减小,最后约等于0,芯片正常工作。并联在电容的两端为复位按键,当复位按键没有被按下的时候电路实现上电复位,在芯片正常工作后,通过按下按键使RST管脚出现高电平达到手动复位的效果。一般来说,只要RST 管脚上保持10ms 以上的高电平,就能使单片机有效的复位。
EA/VPP(31 脚)
EA接到VCC,高电平是因为,51 单片机的EA/VPP(31 脚) 是内部和外部程序存储器的选择管脚。当EA 保持高电平时,单片机访问内部程序存储器;当EA 保持低电平时,则不管是否有内部程序存储器,只访问外部存储器。
内部
这就很抽象了啊。好多内部的东西,都是定义规范。你用多了就懂它的意思的。
我们最终的目的就说控制这些引脚按规范,你自己的代码,或者一些协议,来输出高电平1,或者低电平0
那怎么控制呢?我的理解哈,如果有大神,也不会来看我的。
通过寄存器,就是下面这些东西,什么B、PSW啊,我也不会讲全部,因为有的不熟。
寄存器,你就当它一个黑盒吧,你输入代码控制它,它按你的要求输出。
其实它更像一堆开关,二进制嘛。每个开关对应一个功能,都是八位寄存器,那它们都是8个开关,也许有的开关没有功能,但很少。这些开关,有的你可以一个一个开,有的你要一起,不能单独。怎么知道是那些呢,看它们的字节地址,尾号是0或8的,都能一个开关一个开关的操作。其他的则不能。就是书上说的,按字节寻址和按位寻址。
举个例子。
PSW寄存器(程序状态字寄存器)一个8位寄存器,说明有八个开关, 字节地址 D0H
地址尾号是0,能单独操作它的每一个开关。
它有哪八个开关,有哪些功能呢?
程序状态字各位的含义
PWS位地址 D7 D6 D5 D4 D3 D2 D1 D0
含义 CY AC F0 RS1 RS0 OV --- P
下面分别对各位简单总结:
1. D1H,---没有定义,这个开关没有定义东西
2.进位标志位(CY)
CY的全称是Carry,有的资料就简写为一个C字母。
在使用加减乘除、左移或右移之类等操作时,这个标志位会受到影响。
因为51单片机一般是对8位数据的操作,当数据的最高位(D7)进行例如加法操作产生进位时,CY就会置1。否则CY等于0;当进行8为减法时,若运算结果有借位,则CY=1,否则C=0。
我把CY这个标志位理解为8位运算中的第九个数据位。
3.辅助进位标志位(AC)
AC的全称是Assistant Carry。
首先说明一下什么是低半字节和高半字节:一个字节有8位,低半字节就是第0位到第3位,高半字节就是第4位到第7位
还是进行8位加法运算,如果低半字节的最高位(D3)有进位,则AC=1,否则AC=0;当进行8位减法运算时,如果D3有借位,则AC=1,否则AC=0、
这个可以和CY标志位进行类比理解。
4.软件标志(F0)
这是用户定义的一个状态标志。可以通过软件对它置位或清零。
5.工作寄存器组选择位RS1和RS0
可以在编程的时候置位或清零,以选择4个工作寄存器组中的一个进行工作。
一个寄存器组有8字节,有四组寄存器,一共32字节。在片内数据存储区中的00H~1FH。
6.溢出标志(OV)
OV的全称是Overflow。
当进行有符号(signed)数加减法运算时,由硬件自动置位或清零。
当OV=1时,表示一个数字已经超出了累加器以补码形式表示一个有符号数的范围,即超出了-128~+127的范围。
在8位补码中,D7一般用来表示符号位,D6~D0用来表示二进制数字。
所以,在加法时,如果最高位(D7)和次高位(D6)中有一个进位,或在减法时两个中有一个借位,OV将被置位。
执行乘法指令(MUL AB)也会影响OV标志位,当乘积大于255时,OV=1,否则OV=0。
执行除法指令时也会影响OV标志位。
6.1与AC标志位对比
要注意,溢出和进位是两个不同的概念,进位是指无符号数运算时ACC中D7向更高位的进位。溢出是指带符号数补码运算时,运算结果超出8位二进制补码的表示范围。
另外,OV的状态可以由ACC的D7和D6相异或得出。
7.奇偶标志位P
每执行一条汇编指令,单片机都能根据A中1的个数的奇偶自动令P置位或清零,奇为1,偶为0。
此标志位对串行通信的数据传输非常有用,通过就校验可以检验传输的可靠性。
其它寄存器,可以自己研究有什么作用。
现在,学习怎么使用。就是怎么操作开关。
那就是编程了。
现在假设你已经学过C语言了。
51单片机C语言还需要补充几点。
1.bit和sbit都是C51扩展的变量类型。 bit和int char之类的差不多,只不过char=8位, bit=1位而已。都是变量,编译器在编译过程中分配地址。除非你指定,否则这个地址是随机的。这个地址是整个可寻址空间,RAM+FLASH+扩展空间。bit只有0和1两种值,意义有点像Windows下VC中的BOOL。 sbit是对应可位寻址空间的一个位,可位寻址区:20H~2FH。一旦用了sbi xxx = REGE^6这样的定义,这个sbit量就确定地址了。sbit大部分是用在寄存器中的,方便对寄存器的某位进行操作的。
2.bit位标量 bit位标量是C51编译器的一种扩充数据类型,利用它可定义一个位标量,但不能定义位指针,也不能定义位数组。它的值是一个二进制位,不是0就是1,类似一些高级语言中的Boolean类型中的True和False。
3.sfr特殊功能寄存器 sfr也是一种扩充数据类型,点用一个内存单元,值域为0~255。利用它可以访问51单片机内部的所有特殊功能寄存器。如用sfr P1 = 0x90这一句定P1为P1端口在片内的寄存器,在后面的语句中我们用以用P1 = 255(对P1端口的所有引脚置高电平)之类的语句来操作特殊功能寄存器。 sfr P1 = 0x90; //定义P1 I/O 口,其地址90H sfr 关键定后面是一个要定义的名字,可任意选取,但要符合标识符的命名规则,名字最好有一定的含义如P1 口可以用P1 为名,这样程序会变的好读好多.等号后面必须是常数,不允许有带运算符的表达式,而且该常数必须在特殊功能寄存器的地址范围之内(80H-FFH),具体可查看附录中的相关表. sfr 是定义8 位的特殊功能寄存器而sfr16 则是用来定义16 位特殊功能寄存器, 如8052 的T2 定时器,可以定义为: sfr16 T2 = 0xCC; //这里定义8052 定时器2,地址为T2L=CCH,T2H=CDH
然后可以像写C语言一样写一个控制单片机的程序了。
IDE是 Keil uVison4 软件安装自行百度吧。
开始从点亮一个LED开始吧
新建工程,选择Atmel的AT89C51
选择是。
建好后,可以把右边展开,有一个启动文件
新建一个.c文件,添加到工程里
开始写代码了。
和C语言一样,添加头文件。主函数。
#include<reg51.h>
void main()
{
}
然后怎么点亮灯呢?
一个人led怎么亮?它需要两端有5V电压,电流不能太大,不然会被烧了,所以需要串联一个电阻。
所以电路是这样的。
现在来给两端5V电压,那么我们就需要P1.0引脚输出5V即高电平,代码中的逻辑1。
直接在主函数中写P1.0=1;看看
#include<reg51.h>
void main()
{
P1.0=1;
}
然而却报错,因为不知P1.0是什么啊 ,我们需要定义
我们知道P1.0是P1的一个引脚,然后我们还知道,P1寄存器地址是90H,也是P1.0引脚的地址,它是八位寄存器,有八个开关。P1地址以0结尾,那么我们可以单独使用其中任意一个开关,也就是按位寻址。如P1.0或者P1.1等等,那它们的地址依次是
P1.0 -》90H
P1.1 -》91H
P1.2 -》92H
P1.3 -》93H
P1.4 -》94H
P1.5 -》95H
P1.7 -》97H
在C语言里,如果直接写P1.0,C编译器并不能识别,而且P1.0也不是一个合法的C语言变量名,所以得给它另起一个名字,这里起的名为led,可是led是不是就是P1.0呢?你这么认为,C编译器可不这么认为,所以必须给它们建立联系,这里使用了Keil C的关键字sbit来定义,sbit的用法有三种:
第一种方法:sbit 位变量名=地址值
第二种方法:sbit 位变量名=SFR名称^变量位地址值
第三种方法:sbit 位变量名=SFR地址值^变量位地址值
如定义P1中的P1.0可以用以下三种方法:
sbit P1.0=0x90 (1)说明:0x90 是P1.0的位地址值
sbit P1.0=P1^0 (2)说明:其中PSW必须先用sfr定义好
sbit P1.0=0x90^2 (3)说明:0xD0就是PSW的地址值
因此这里用sbit led=P1^0;就是定义用符号led来表示P1.0引脚,如果你愿意也可以起P10一类的名字,只要下面程序中也随之更改就行了。
我们来实验一下,用三种方式定义小灯,给它亮。
代码:
#include<reg51.h>
sbit P10=0x90; //代码中小数点有特殊含义或功能,不能用来命名。所以改为P10
sbit P11=0x90^1;
sbit P12=P1^2;
void main()
{
P10=1;
P11=1;
P12=1;
}
烧写进单片机,仿真
我们可以看看reg51.h是什么样子,其实也就是把寄存器地址,起了一个名字方便你使用,如果你记得住地址,你也可以直接用地址来操作。
/*--------------------------------------------------------------------------
REG51.H
Header file for generic 80C51 and 80C31 microcontroller.
Copyright (c) 1988-2002 Keil Elektronik GmbH and Keil Software, Inc.
All rights reserved.
--------------------------------------------------------------------------*/
#ifndef __REG51_H__
#define __REG51_H__
/* BYTE Register */
sfr P0 = 0x80;
sfr P1 = 0x90;
sfr P2 = 0xA0;
sfr P3 = 0xB0;
sfr PSW = 0xD0;
sfr ACC = 0xE0;
sfr B = 0xF0;
sfr SP = 0x81;
sfr DPL = 0x82;
sfr DPH = 0x83;
sfr PCON = 0x87;
sfr TCON = 0x88;
sfr TMOD = 0x89;
sfr TL0 = 0x8A;
sfr TL1 = 0x8B;
sfr TH0 = 0x8C;
sfr TH1 = 0x8D;
sfr IE = 0xA8;
sfr IP = 0xB8;
sfr SCON = 0x98;
sfr SBUF = 0x99;
/* BIT Register */
/* PSW */
sbit CY = 0xD7;
sbit AC = 0xD6;
sbit F0 = 0xD5;
sbit RS1 = 0xD4;
sbit RS0 = 0xD3;
sbit OV = 0xD2;
sbit P = 0xD0;
/* TCON */
sbit TF1 = 0x8F;
sbit TR1 = 0x8E;
sbit TF0 = 0x8D;
sbit TR0 = 0x8C;
sbit IE1 = 0x8B;
sbit IT1 = 0x8A;
sbit IE0 = 0x89;
sbit IT0 = 0x88;
/* IE */
sbit EA = 0xAF;
sbit ES = 0xAC;
sbit ET1 = 0xAB;
sbit EX1 = 0xAA;
sbit ET0 = 0xA9;
sbit EX0 = 0xA8;
/* IP */
sbit PS = 0xBC;
sbit PT1 = 0xBB;
sbit PX1 = 0xBA;
sbit PT0 = 0xB9;
sbit PX0 = 0xB8;
/* P3 */
sbit RD = 0xB7;
sbit WR = 0xB6;
sbit T1 = 0xB5;
sbit T0 = 0xB4;
sbit INT1 = 0xB3;
sbit INT0 = 0xB2;
sbit TXD = 0xB1;
sbit RXD = 0xB0;
/* SCON */
sbit SM0 = 0x9F;
sbit SM1 = 0x9E;
sbit SM2 = 0x9D;
sbit REN = 0x9C;
sbit TB8 = 0x9B;
sbit RB8 = 0x9A;
sbit TI = 0x99;
sbit RI = 0x98;
#endif