用的是普中科技的EM3.V2.2开发板,没什么可说的,做好最小系统板后也可以自己搭建电路使用。
在一片集成电路芯片上集成微处理器、存储器、I/O接口电路,从而构成了单芯片微型计算机,就是单片机。 Intel公司推出了MCS-51系列单片机:集成8位CPU、4K字节ROM、128字节RAM、4个8位并口、1个全双工串行口、2个16位定时/计数器。寻址范围64K,并有控制功能较强的布尔处理器。
高电平:5V或者3.3V,取决单片机电源。
低电平:0V
高电平:-12V
低电平:+12V
所以当我们用单片机跟电脑通信的时候,我们要通过各种元器件将单片机的电平转换为计算机可识别的电平才能跟电脑进行通信。
基数是2,逢二进一。
基数是16,逢十六进一。
有0得0
1&1=1 ; 1&0=0 ; 0&0=0 ;
有1得1
1|1=1 ; 1|0=1 ; 0|0=0;
1的非得0,0的非得1。
~1=0; ~0=1;
必须不同,否则没有(0)
11=0;10=1;0^0=0;
P3.0:RXD串行口输入
P3.1:TXD串行口输出
P3.2:INT0外部中断0输入
P3.3:INT1外部中断1输入
P3.4:T0定时器0外部输入
P3.5:T1定时器1外部输入
P3.6:WR外部写控制
P3.7:RD外部读控制
总线(BUS)是计算机各部件之间传送信息的公共通道。微机中有内部总线和外部总线两类。内部总线是CPU内部之间的连线。外部总线是指CPU与其它部件之间的连线。
外部总线有三种:
数据总线DB(Data Bus), 地址总线 AB(Address Bus)和控制总线 CBControl Bus)。
CPU:由运算和控制逻辑组成,同时还包括中断系统和部分外部特殊功能寄存器;
RAM:用以存放可以读写的数据,如运算的中间结果、最终结果以及欲显示的数据;
ROM:用以存放程序、一些原始数据和表格;
I/O口:四个8位并行I/O口,既可用作输入,也可用作输出;
T/C:两个定时/记数器,既可以工作在定时模式,也可以工作在记数模式;
五个中断源的中断控制系统;
一个全双工UART(通用异步接收发送器)的串行I/O口,用于实现单片机之间或单片机与微机之间的串行通信;
片内振荡器和时钟产生电路,石英晶体和微调电容需要外接。最高振荡频率取决于单片机型号及性能。
机器周期和指令周期
(1)振荡周期:也称时钟周期,是指为单片机提供时钟脉冲信号的振荡源的周期,我们开发板上为12MHZ。
(2)状态周期:每个状态周期为时钟周期的2倍,是振荡周期经二分频后得到的。
(3)机器周期:一个机器周期包含6个状态周期S1~S6,也就是 12 个时钟周期。在一个机器周期内,CPU可以完成一个独立的操作。
(4)指令周期:它是指CPU完成一条操作所需的全部时间。每条指令执行时间都是有一个或几个机器周期组成。MCS - 51 系统中,有单周期指令、双周期指令和四周期指令。
上拉电阻就是将不确定的信号通过一个电阻拉到高电平,同时此电阻起到一个限流的作用,下拉就是下拉到低电平。
作用:
选取原则:
一个简单的单片机C程序要有什么
#include
void main()
{
while(1)
{
}
}
C语言中常用语句略,if,while,do…while,for,switch…case
函数略
sfr:特殊功能寄存器声明
sfr 变量名=地址值;
*特殊功能寄存器在reg51.H这个头文件里面都帮我们定义好了,所以平时我们就不要自己去定义寄存器的名字。
sbit:特殊功能位声明
sbit 变量名=地址值;
*在给某个引脚取名的时候经常会用到。
bit:位变量声明
*用来定义位数据变量
例:sfr SCON= 0X98;
sbit LED= P0^2;
1.电源电路
2.复位电路
3.时钟电路
4.下载电路
见百度,非常简单,需要破解
project–>new project–>新建一个文件夹,保存在那里面–>选择单片机—>File—>new—>文件名main.c—>右击Source Group,Add File。
#include
void main()
{
while(1)
{
}
}
点那个彩虹锤,output勾上create hex file
编译,运行
C语言知识点:
bit和sbit都是C51扩展的变量类型。
sbit用法:
sbit 变量名=地址值;
在给某个引脚取名的时候经常会用到。
#include
sbit led=P0^0;
void main()
{
while(1)
{
led=1;//给p0^0管脚一个高电平
}
}
typedef unsigned char u8;
typedef unsigned int u16;//后面要加分号
重新定义一些常用的关键词,可以增强程序的可移植性,因为在不同的编译软件上面,C语言的数据类型的关键词的位宽是不一样的。
while(i<10)
{
i=i+1;
}
while语句的语义是:计算表达式的值,当值为真(非0)时,执行循环体语句。
void delay(u16 i)//大约延时10us
{
while(i--);
}
#include
typedef unsigned char u8;
typedef unsigned int u16;
sbit led=P0^0;
void delay(u16 i)//大约延时10us
{
while(i--);
}
void main()
{
while(1)
{
led=1;//给p0^0管脚一个高电平
delay(50000);//500ms
led=0;
delay(50000);
}
}
#define A P0(注意后面不用加分号)
crol(a,b);循环左移函数,a是左移的值,b是左移的位数。包含在instrins.h库函数里面。
cror(a,b);循环右移函数,a是右移的值,b是右移的位数。包含在instrins.h库函数里面。
#include
#include
typedef unsigned char u8;
typedef unsigned int u16;
#define led P0
void delay(u16 i)//大约延时10us
{
while(i--);
}
void main()
{
u8 i;
led=0x01;//16进制 化成二进制是0000 0001
delay(50000)
while(1)
{
for(i=0;i<8;i++)
{
led=(0x01<<i);//0x01 0000 0001 0000 0010移位
delay(50000);
}
}
}
多谐振荡器由晶体管或集成电路构成,当接通电源后(1.5~15V直流工作电压),多谐振荡器起振,输出1.5~2.5kHZ的音频信号,阻抗匹配器推动压电蜂鸣片发声。
改变单片机引脚输出波形的频率,就可以调整控制蜂鸣器音调,产生各种不同音色、音调的声音。
改变输出电平的高低电平占空比,则可以控制蜂鸣器的声音大小。
#include
typedef unsigned char u8;
typedef unsigned int u16;
sbit beep=P1^5;
void delay(u16 i)//大约延时10us
{
while(i--);
}
void main()
{
while(1)
{
beep=~beep;//取反
delay(10);
}
}
#include
typedef unsigned char u8;
typedef unsigned int u16;
sbit relay=P1^4;
void main()
{
relay=0;
while(1)
{
}
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Xg1JDGqm-1628929040392)(F:\01单片机学习笔记\静态数码管模块.png)]
LED数码管根据LED的不同接法可以分为2类:共阴和共阳。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FA91VRjT-1628929040394)(F:\01单片机学习笔记\静态数码管原理.png)]
共阳码表:
0xC0 | 0xF9 | 0xA4 | 0xB0 | 0x99 | 0x92 | 0x82 | 0xF8 | 0x80 | 0x90 | 0x88 | 0x83 | 0xC6 | 0xA1 | 0x86 | 0x8E | 0xFF |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | A | B | C | D | E | F | 无显示 |
共阴码表:
0x3f | 0x06 | 0x5b | 0x4f | 0x66 | 0x6d | 0x7d | 0x07 | 0x7f | 0x6f | 0x77 | 0x7c | 0x39 | 0x79 | 0x79 | 0x71 | 0x00 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | A | B | C | D | E | F | 无显示 |
74HC245
LED显示器工作方式有两种:静态显示方式和动态显示方式。静态显示的特点是每个数码管的段选必须接一个8位数据线来保持显示的字形码。当送入一次字形码后,显示字形可一直保持,直到送入新字形码为止。这种方法的优点是占用CPU时间少,显示便于监测和控制。缺点是硬件电路比较复杂,成本较高
#include
#include
typedef unsigned char u8;
typedef unsigned int u16;
u8 code smgduan[16]={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90,0x88,0x83,0xC6,0xA1,0x86,0x8E,0xFF};//共阳
void main()
{
P0=smgduan[0];
while(1)
{
}
}
74HC138,J10接J1
74HC245与74HC138
动态显示的特点是将所有数码管的段选线并联在一起,由位选线控制是哪一位数码管有效。选亮数码管采用动态扫描显示。所谓动态扫描显示即轮流向各位数码管送出字形码和相应的位选,利用发光管的余辉和人眼视觉暂留作用,使人的感觉好像各位数码管同时都在显示。动态显示的亮度比静态显示要差一些,所以在选择限流电阻时应略小于静态显示电路中的。
#include
#include
typedef unsigned char u8;
typedef unsigned int u16;
sbit LSA=P2^2;
sbit LSB=P2^3;
sbit LSB=P2^4;
u8 code smgduan[16]={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90,0x88,0x83,0xC6,0xA1,0x86,0x8E,0xFF};//共阳
void delay(u16 i){
while(i--);
}
void DigDisplay(){
u8 i;
for(i=0;i<8;i++){
switch(i)
{
case 0:
LSA=0;LSB=0;LSC=0;break;
case 1:
LSA=1;LSB=0;LSC=0;break;
case 2:
LSA=0;LSB=1;LSC=0;break;
case 3:
LSA=1;LSB=1;LSC=0;break;
case 4:
LSA=0;LSB=0;LSC=1;break;
case 5:
LSA=1;LSB=0;LSC=1;break;
case 6:
LSA=0;LSB=1;LSC=1;break;
case 7:
LSA=1;LSB=1;LSC=1;break;
}
P0=smgduan[i];
delay(100);
P0=0x00;//P0口数据清零,如果不清零会有重影
}
}
void main()
{
P0=smgduan[0];
while(1)
{
}
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EisFFO5x-1628929040400)(F:\01单片机学习笔记\独立按键模块.png)]
/*************************************************************
实验现象:下载程序后按下K1按键可以对D1小灯状态取反
*************************************************************/
#include "reg52.h" //此文件中定义了单片机的一些特殊功能寄存器
typedef unsigned int u16; //对数据类型进行声明定义
typedef unsigned char u8;
sbit k1=P1^0; //定义P10口是k1
sbit led=P0^0; //定义P00口是led
void delay(u16 i)
{
while(i--);
}
//按键处理函数
void keypros()
{
if(k1==0) //检测按键K1是否按下
{
delay(1000); //消除抖动 一般大约10ms
if(k1==0) //再次判断按键是否按下
{
led=~led; //led状态取反
}
while(!k1); //检测按键是否松开
}
}
void main()
{
led=1;
while(1)
{
keypros(); //按键处理函数
}
}
逐行扫描:我们可以通过高四位轮流输出低电平来对矩阵键盘进行逐行扫描,当低四位接收到的数据不全为1的时候,说明有按键按下,然后通过接收到的数据是哪一位为0来判断是哪一个按键被按下。
行列扫描:我们可以通过高四位全部输出低电平,低四位输出高电平。当接收到的数据,低四位不全为高电平时,说明有按键按下,然后通过接收的数据值,判断是哪一列有按键按下,然后再反过来,高四位输出高电平,低四位输出低电平,然后根据接收到的高四位的值判断是那一行有按键按下,这样就能够确定是哪一个按键按下了。
JP3中的5678脚接GND
//矩阵按键实验 *
//实现现象:下载程序后动态数码管的第一个显示0,按下矩阵按键上的按键显示对应的数字
//注意事项:如果不想让点阵模块显示,可以将74HC595模块上的JP595短接片拔掉。
#include "reg52.h" //此文件中定义了单片机的一些特殊功能寄存器
typedef unsigned int u16; //对数据类型进行声明定义
typedef unsigned char u8;
#define GPIO_DIG P0
#define GPIO_KEY P1
sbit LSA=P2^2;
sbit LSB=P2^3;
sbit LSC=P2^4;
u8 KeyValue; //用来存放读取到的键值
u8 code smgduan[17]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07, 0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};//显示0~F的值
void delay(u16 i)
{
while(i--);
}
//函数功能: 检测有按键按下并读取键值
void KeyDown(void)
{
char a=0;
GPIO_KEY=0x0f;
if(GPIO_KEY!=0x0f)//读取按键是否按下
{
delay(1000);//延时10ms进行消抖
if(GPIO_KEY!=0x0f)//再次检测键盘是否按下
{
//测试列
GPIO_KEY=0X0F;
switch(GPIO_KEY)
{
case(0X07): KeyValue=0;break;
case(0X0b): KeyValue=1;break;
case(0X0d): KeyValue=2;break;
case(0X0e): KeyValue=3;break;
}
//测试行
GPIO_KEY=0XF0;
switch(GPIO_KEY)
{
case(0X70): KeyValue=KeyValue;break;
case(0Xb0): KeyValue=KeyValue+4;break;
case(0Xd0): KeyValue=KeyValue+8;break;
case(0Xe0): KeyValue=KeyValue+12;break;
}
while((a<50)&&(GPIO_KEY!=0xf0)) //检测按键松手检测
{
delay(1000);
a++;
}
}
}
}
void main()
{
LSA=0; //给一个数码管提供位选
LSB=0;
LSC=0;
while(1)
{
KeyDown(); //按键判断函数
GPIO_DIG=smgduan[KeyValue]; //
}
输入端的扩展
逻辑图和真值表
#include "reg52.h"
#include "intrins.h"
typedef unsigned int u16;
typedef unsigned char u8;
#define GPIO_LED P0
sbit IN_PL = P1^6;
sbit IN_Data = P1^7; //数据通过p1.7脚移入单片机进行处理
sbit SCK = P3^6;
u8 Read74HC165(void)
{
u8 i;
u8 indata;
IN_PL = 0;
_nop_(); //短暂延时,产生一定宽度的脉冲
IN_PL = 1; //将外部信号全部读入锁存器中
_nop_();
indata=0; //保存数据的变量清零
for(i=0; i<8; i++)
{
indata = indata<<1; //左移一位
SCK = 0; //时钟置零
_nop_();
indata |= IN_Data;
SCK = 1; //时钟置一
}
return(indata);
}
void main()
{
u8 h165Value;
GPIO_LED = 0xff;
while(1)
{
h165Value = Read74HC165();
if(h165Value != 0xFF)
{
GPIO_LED = h165Value;
}
}
}
输出端的扩展
逻辑图和真值表
程序
#include "reg51.h" //此文件中定义了单片机的一些特殊功能寄存器
#include "intrins.h"
typedef unsigned int u16; //对数据类型进行声明定义
typedef unsigned char u8;
sbit SRCLK=P3^6;
sbit RCLK=P3^5;
sbit SER=P3^4;
void delay(u16 i)
{
while(i--);
}
void Hc595SendByte(u8 dat)
{
u8 a;
SRCLK = 1;
RCLK = 1;
for(a=0;a<8;a++) //发送8位数
{
SER = dat >> 7; //从最高位开始发送
dat <<= 1;
SRCLK = 0; //发送时序
_nop_();
_nop_();
SRCLK = 1;
}
RCLK = 0;
_nop_();
_nop_();
RCLK = 1;
}
void main()
{
u8 ledNum;
ledNum = ~0x01;
while(1)
{
Hc595SendByte(ledNum);
ledNum = _crol_(ledNum, 1);
delay(50000);
}
}
#include "reg51.h" //此文件中定义了单片机的一些特殊功能寄存器
#include "intrins.h"
typedef unsigned int u16; //对数据类型进行声明定义
typedef unsigned char u8;
//--定义使用的IO口--//
sbit SRCLK=P3^6;
sbit RCLK=P3^5;
sbit SER=P3^4;
/**********************************************************
* 函 数 名 : Hc595SendByte(u8 dat1,u8 dat2)
* 函数功能 : 通过595发送2个字节的数据
* 输 入 : dat1:第2个595输出数值
* * dat2: 第1个595输出数值
* 输 出 : 无
**********************************************************/
void Hc595SendByte(u8 dat1,u8 dat2)
{
u8 a;
SRCLK = 1;
RCLK = 1;
for(a=0;a<8;a++) //发送8位数
{
SER = dat1 >> 7; //从最高位开始发送
dat1 <<= 1;
SRCLK = 0; //发送时序
_nop_();
_nop_();
SRCLK = 1;
}
for(a=0;a<8;a++) //发送8位数
{
SER = dat2 >> 7; //从最高位开始发送
dat2 <<= 1;
SRCLK = 0; //发送时序
_nop_();
_nop_();
SRCLK = 1;
}
RCLK = 0;
_nop_();
_nop_();
RCLK = 1;
}
void main()
{
while(1)
{
Hc595SendByte(0xfe,0x01);
}
}
#include "reg51.h" //此文件中定义了单片机的一些特殊功能寄存器
#include "intrins.h"
typedef unsigned int u16; //对数据类型进行声明定义
typedef unsigned char u8;
//--定义使用的IO口--//
sbit SRCLK=P3^6;
sbit RCLK=P3^5;
sbit SER=P3^4;
//数字0取模数据
u8 ledduan[]={0x00,0x00,0x3E,0x41,0x41,0x41,0x3E,0x00}; //类似于动态数码管的段选
//心型图像取模数据
//u8 ledduan[]={0x1C,0x3E,0x7E,0xFC,0xFC,0x7E,0x3E,0x1C}; //类似于动态数码管的段选
u8 ledwei[]={0x7f,0xbf,0xdf,0xef,0xf7,0xfb,0xfd,0xfe}; //类似于动态数码管的位选
void delay(u16 i)
{
while(i--);
}
/**********************************************************
* 函 数 名 : Hc595SendByte(u8 dat1,u8 dat2)
* 函数功能 : 通过595发送2个字节的数据
* 输 入 : dat1:第2个595输出数值
* * dat2: 第1个595输出数值
* 输 出 : 无
**********************************************************/
void Hc595SendByte(u8 dat1,u8 dat2)
{
u8 a;
SRCLK = 1;
RCLK = 1;
for(a=0;a<8;a++) //发送8位数
{
SER = dat1 >> 7; //从最高位开始发送
dat1 <<= 1;
SRCLK = 0; //发送时序
_nop_();
_nop_();
SRCLK = 1;
}
for(a=0;a<8;a++) //发送8位数
{
SER = dat2 >> 7; //从最高位开始发送
dat2 <<= 1;
SRCLK = 0; //发送时序
_nop_();
_nop_();
SRCLK = 1;
}
RCLK = 0;
_nop_();
_nop_();
RCLK = 1;
}
void main()
{
u8 i=0;
while(1)
{
for(i=0;i<8;i++)
{
Hc595SendByte(ledwei[i],ledduan[i]);
delay(10);
}
}
}
五线四相步进电机模块输出-->直流电机
5V-->直流电机两脚任意一个
O1-->直流电机两脚任意一个
**********************************************************/
#include "reg52.h" //此文件中定义了单片机的一些特殊功能寄存器
#include //因为要用到左右移函数,所以加入这个头文件
typedef unsigned int u16; //对数据类型进行声明定义
typedef unsigned char u8;
sbit moto=P1^0;
void delay(u16 i)
{
while(i--);
}
void main()
{
u8 i;
moto=0; //关闭电机
for(i=0;i<100;i++) //循环100次,也就是大约5S
{
moto=1; //开启电机
delay(5000); //大约延时50ms
}
moto=0; //关闭电机
while(1)
{
}
}
/**********************************************************
实验现象:下载程序后,步进电机旋转
接线说明:
1,单片机-->四线双极性步进电机模块
P10-->IA
P11-->IB
P12-->IC
P13-->ID
2,四线双极性步进电机模块输出-->步进电机
OA-->A+
OB-->A-
OC-->B+
OD-->B-
**********************************************************/
#include "reg52.h" //此文件中定义了单片机的一些特殊功能寄存器
#include //因为要用到左右移函数,所以加入这个头文件
typedef unsigned int u16; //对数据类型进行声明定义
typedef unsigned char u8;
sbit MOTOA = P1^0;
sbit MOTOB = P1^1;
sbit MOTOC = P1^2;
sbit MOTOD = P1^3;
#define SPEED 200 //修改此值可改变电机旋转速度,不能过大或过小
void delay(u16 i)
{
while(i--);
}
void main()
{
P1=0X00;
while(1)
{
MOTOA = 1;
MOTOB = 0;
MOTOC = 1;
MOTOD = 1;
delay(SPEED);
MOTOA = 1;
MOTOB = 1;
MOTOC = 1;
MOTOD = 0;
delay(SPEED);
MOTOA = 0;
MOTOB = 1;
MOTOC = 1;
MOTOD = 1;
delay(SPEED);
MOTOA = 1;
MOTOB = 1;
MOTOC = 0;
MOTOD = 1;
delay(SPEED);
}
}
CPU在处理某一事件A时,发生了另一事件B请求CPU迅速去处理(中断发生);
CPU暂时中断当前的工作,转去处理事件B(中断响应和中断服务);
待CPU将事件B处理完毕后,再回到原来事件A被中断的地方继续处理事件A(中断返回),这一过程称为中断 。
引起CPU中断的根源,称为中断源。中断源向CPU提出的中断请求。CPU暂时中断原来的事务A,转去处理事件B。对事件B处理完毕后,再回到原来被中断的地方(即断点),称为中断返回。实现上述中断功能的部件称为中断系统。
89C51/52的中断系统有5个中断源 ,2个优先级,可实现二级中断嵌套 。
CPU对中断系统所有中断以及某个中断源的开放和屏蔽是由中断允许寄存器IE控制的。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mY7JJSST-1628929040414)(F:\01单片机学习笔记\中断允许控制1.png)]
TCON的中断标志
IT0(TCON.0),外部中断0触发方式控制位。
当IT0=0时,为低电平触发方式。
当IT0=1时,为边沿触发方式(下降沿有效)。
IE0(TCON.1),外部中断0中断请求标志位。
IT1(TCON.2),外部中断1触发方式控制位。
IE1(TCON.3),外部中断1中断请求标志位。
TF0(TCON.5),定时/计数器T0溢出中断请求标志位。
TF1(TCON.7),定时/计数器T1溢出中断请求标志位。
同一优先级中的中断申请不止一个时,则有中断优先权排队问题。同一优先级的中断优先权排队,由中断系统硬件确定的自然优先级形成,其排列如所示:
中断源
51单片机的中断优先级有三条原则:
为了实现上述后两条原则,中断系统内部设有两个用户不能寻址的优先级状态触发器。其中一个置1,表示正在响应高优先级的中断,它将阻断后来所有的中断请求;另一个置1,表示正在响应低优先级中断,它将阻断后来所有的低优先级中断请求。
中断响应条件
以上三条同时满足时,CPU才有可能响应中断。
例子:
以外部中断0为例,
主程序中需要有以下代码:
EA=1;//打开总中断开关
EX0=1;//开外部中断0
IT0=0/1;//设置外部中断的触发方式
中断服务函数:
void int0 () interrupt 0 using 1
{
do anything that you want
}
/**************************************************************************************
实验现象:下载程序后,操作K3按键使D1状态取反
接线说明: 1、单片机-->LED&交通灯模块
P20-->D1
2、单片机-->独立按键模块
P32-->K3
***************************************************************************************/
#include "reg52.h" //此文件定义了单片机的一些特殊功能寄存器
typedef unsigned int u16; //对数据类型进行定义
typedef unsigned char u8;
sbit k3=P3^2; //定义按键K3
sbit led=P2^0; //定义P2.0口是led
/*******************************************************************************
* 函数名 : delay
* 函数功能 : 延时函数,i=1时,大约延时10us
*******************************************************************************/
void delay(u16 i)
{
while(i--);
}
/*******************************************************************************
* 函数名 : Int1Init()
* 函数功能 : 设置外部中断1
*******************************************************************************/
void Int0Init()
{
//设置INT0
IT0=1;//下降沿触发方式
EX0=1;//打开INT0的中断允许
EA=1;//打开总中断
}
/*******************************************************************************
* 函数名 : main
* 函数功能 : 主函数
*******************************************************************************/
void main()
{
Int0Init(); // 设置外部中断0
while(1);
}
/*******************************************************************************
* 函数名 : Int0() interrupt 0
* 函数功能 : 外部中断0的中断函数
*******************************************************************************/
void Int0() interrupt 0
{
delay(1000);
if(k3==0)
{
led=~led;
}
}
例如:外接晶振为12MHz时,51单片机相关周期的具体值为:振荡周期=1/12us;状态周期=1/6us;机器周期=1us;指令周期=1~4us;
定时/计数器实质上是一个加1计数器。它随着计数器的输入脉冲进行自加1,也就是每来一个脉冲,计数器就自动加1,,当加到计数器为全1时,再输入一个脉冲就使计数器回零,且计数器的溢出使相应的中断标志位置1,向CPU发出中断请求(定时/计数器中断允许时)。如果定时/计数器工作于定时模式,则表示定时时间已到;如果工作于计数模式,则表示计数值已满。
可见,由溢出时计数器的值减去计数初值才是加1计数器的计数值。
定时/计数器的实质是加1计数器(16位),由高8位和低8位两个寄存器THx和TLx组成。TMOD是定时/计数器的工作方式寄存器,确定工作方式和功能;TCON是控制寄存器,控制T0、T1的启动和停止及设置溢出标志。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Fi3UUOMb-1628929040422)(F:\01单片机学习笔记\51单片机定时器结构.png)]
51单片机定时/计数器的工作由两个特殊功能寄存器控制。TMOD用于设置其工作方式;TCON用于控制其启动和中断申请。
1、工作方式寄存器TMOD
工作方式寄存器TMOD用于设置定时/计数器的工作方式,低四位用于T0,高四位用于T1。其格式如下:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-88EU1OSG-1628929040424)(F:\01单片机学习笔记\工作方式寄存器TMOD.png)]
GATE是门控位, GATE=0时,用于控制定时器的启动是否受外部中断源信号的影响。只要用软件使TCON中的TR0或TR1为1,就可以启动定时/计数器工作;GATA=1时,要用软件使TR0或TR1为1,同时外部中断引脚INT0/1也为高电平时,才能启动定时/计数器工作。即此时定时器的启动条件,加上了INT0/1引脚为高电平这一条件。
C/T :定时/计数模式选择位。C/T =0为定时模式;C/T =1为计数模式。
M1M0:工作方式设置位。定时/计数器有四种工作方式。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yB67lZ1o-1628929040426)(F:\01单片机学习笔记\定时器计数器工作方式设置表.png)]
2、控制寄存器TCON
TCON的低4位用于控制外部中断,已在前面介绍。TCON的高4位用于控制定时/计数器的启动和中断申请。其格式如下:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qp01ErmA-1628929040428)(F:\01单片机学习笔记\控制寄存器TCON.png)]
TF1(TCON.7):T1溢出中断请求标志位。T1计数溢出时由硬件自动置TF1为1。CPU响应中断后TF1由硬件自动清0。T1工作时,CPU可随时查询TF1的状态。所以,TF1可用作查询测试的标志。TF1也可以用软件置1或清0,同硬件置1或清0的效果一样。
TR1(TCON.6):T1运行控制位。TR1置1时,T1开始工作;TR1置0时,T1停止工作。TR1由软件置1或清0。所以,用软件可控制定时/计数器的启动与停止。
TF0(TCON.5):T0溢出中断请求标志位,其功能与TF1类同。
TR0(TCON.4):T0运行控制位,其功能与TR1类同。
方式0为13位计数,由TL0的低5位(高3位未用)和TH0的8位组成。TL0的低5位溢出时向TH0进位,TH0溢出时,置位TCON中的TF0标志,向CPU发出中断请求。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KKdO9eNz-1628929040433)(F:\01单片机学习笔记\定时器工作方式0.png)]
定时器模式时有:
N = t / T c y N=t/Tcy N=t/Tcy
计数初值计算的公式为:
X = 2 13 − N X=2^{13}-N X=213−N
定时器的初值还可以采用计数个数直接取补法获得。计数模式时,计数脉冲是T0引脚上的外部脉冲。
门控位GATE具有特殊的作用。当GATE=0时,经反相后使或门输出为1,此时仅由TR0控制与门的开启,与门输出1时,控制开关接通,计数开始;当GATE=1时,由外中断引脚信号控制或门的输出,此时控制与门的开启由外中断引脚信号和TR0共同控制。当TR0=1时,外中断引脚信号引脚的高电平启动计数,外中断引脚信号引脚的低电平停止计数。这种方式常用来测量外中断引脚上正脉冲的宽度。
方式1的计数位数是16位,由TL0作为低8位,TH0作为高8位,组成了16位加1计数器 。
计数个数与计数初值的关系为:
X = 2 16 − N X=2^{16}-N X=216−N
方式2为自动重装初值的8位计数方式。
计数个数与计数初值的关系为:
X = 2 8 − N X=2^{8}-N X=28−N
工作方式2特别适合于用作较精确的脉冲信号发生器。
方式3只适用于定时/计数器T0,定时器T1处于方式3时相当于TR1=0,停止计数。
工作方式3将T0分成为两个独立的8位计数器TL0和TH0 。
例程
/**************************************************************************************
实验现象:下载程序后,D1小灯循环点亮1秒,熄灭1秒。使用单片机内部定时器可实现准确延时
接线说明: 1、单片机-->LED&交通灯模块
P20-->D1
***************************************************************************************/
#include "reg52.h" //此文件中定义了单片机的一些特殊功能寄存器
typedef unsigned int u16; //对数据类型进行声明定义
typedef unsigned char u8;
sbit led=P2^0; //定义P20口是LED
/*******************************************************************************
* 函数名 : Timer0Init
* 函数功能 : 定时器0初始化
*******************************************************************************/
void Timer0Init()
{
TMOD|=0X01;//选择为定时器0模式,工作方式1,仅用TR0打开启动
TH0=0XFC; //给定时器赋初值,定时1ms
TL0=0X18;
ET0=1;//打开定时器0中断允许
EA=1;//打开总中断
TR0=1;//打开定时器
}
/*******************************************************************************
* 函数名 :main
* 函数功能 :主函数
*******************************************************************************/
void main()
{
Timer0Init(); //定时器0初始化
while(1);
}
/*******************************************************************************
* 函数名:void Timer0() interrupt 1
* 函数功能:定时器0中断函数
*******************************************************************************/
void Timer0() interrupt 1
{
static u16 i;
TH0=0XFC; //给定时器赋初值,定时1ms
TL0=0X18;
i++;
if(i==1000)
{
i=0;
led=~led;
}
}
/**************************************************************************************
实验现象:下载程序后,呈交通灯现象
接线说明:1、单片机-->led交通灯模块
J20-->J19
P30-->J18(D9)
P31-->J18(D10)
2、单片机-->数码管模块
J22-->J6
P22-->J9(A)
P23-->J9(B)
P24-->J9(C)
***************************************************************************************/
#include "reg52.h" //此文件中定义了单片机的一些特殊功能寄存器
typedef unsigned int u16; //对数据类型进行声明定义
typedef unsigned char u8;
sbit LSA=P2^2;
sbit LSB=P2^3;
sbit LSC=P2^4;
//--定义使用的IO口--//
#define GPIO_DIG P0
#define GPIO_TRAFFIC P1
sbit RED10 = P1^0; //上人行道红灯
sbit GREEN10 = P1^1; //上人行道绿灯
sbit RED11 = P1^2;
sbit YELLOW11= P1^3;
sbit GREEN11 = P1^4;
sbit RED00 = P3^0; //右人行道红灯
sbit GREEN00 = P3^1; //右人行道绿灯
sbit RED01 = P1^5;
sbit YELLOW01= P1^6;
sbit GREEN01 = P1^7;
u8 code smgduan[17]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};//显示0~F的值
u8 DisplayData[8];
u8 Second;
/*******************************************************************************
* 函数名 : delay
* 函数功能 : 延时函数
*******************************************************************************/
void delay(u16 i)
{
while(i--);
}
/*******************************************************************************
* 函数名 : DigDisplay
* 函数功能 : 数码管动态扫描函数,循环扫描8个数码管显示
*******************************************************************************/
void DigDisplay()
{
u8 i;
for(i=0;i<8;i++)
{
switch(i) //位选,选择点亮的数码管
{
case(0):
LSA=0;LSB=0;LSC=0; break;//显示第0位
case(1):
LSA=1;LSB=0;LSC=0; break;//显示第1位
case(2):
LSA=0;LSB=1;LSC=0; break;//显示第2位
case(3):
LSA=1;LSB=1;LSC=0; break;//显示第3位
case(4):
LSA=0;LSB=0;LSC=1; break;//显示第4位
case(5):
LSA=1;LSB=0;LSC=1; break;//显示第5位
case(6):
LSA=0;LSB=1;LSC=1; break;//显示第6位
case(7):
LSA=1;LSB=1;LSC=1; break;//显示第7位
}
GPIO_DIG=DisplayData[i];//发送段码
delay(100); //间隔一段时间扫描
GPIO_DIG=0x00;//消隐
}
}
/*******************************************************************************
* 函数名 : Timer0Init
* 函数功能 : 定时器0初始化
*******************************************************************************/
void Timer0Init()
{
TMOD|=0X01;//选择为定时器0模式,工作方式1,仅用TR0打开启动
TH0=0XFC; //给定时器赋初值,定时1ms
TL0=0X18;
ET0=1;//打开定时器0中断允许
EA=1;//打开总中断
TR0=1;//打开定时器
}
/*******************************************************************************
* 函数名 : main
* 函数功能 : 主函数
*******************************************************************************/
void main()
{
Second = 1;
Timer0Init();
while(1)
{
if(Second == 70)
{
Second = 1;
}
//--宝田路通行,30秒--//
if(Second < 31)
{
DisplayData[0] = 0x00;
DisplayData[1] = 0x00;
DisplayData[2] = smgduan[(30 - Second) % 100 / 10];
DisplayData[3] = smgduan[(30 - Second) %10];
DisplayData[4] = 0x00;
DisplayData[5] = 0x00;
DisplayData[6] = DisplayData[2];
DisplayData[7] = DisplayData[3];
DigDisplay();
//--宝田路通行--//
GPIO_TRAFFIC = 0xFF; //将所有的灯熄灭
RED00 = 1;
GREEN00 = 1;
GREEN11 = 0; //宝田路绿灯亮
GREEN10 = 0; //宝田路人行道绿灯亮
RED01 = 0; //宝田路红灯亮
RED00 = 0; //宝田路人行道红灯亮
}
//--黄灯等待切换状态,5秒--//
else if(Second < 36)
{
DisplayData[0] = 0x00;
DisplayData[1] = 0x00;
DisplayData[2] = smgduan[(35 - Second) % 100 / 10];
DisplayData[3] = smgduan[(35 - Second) %10];
DisplayData[4] = 0x00;
DisplayData[5] = 0x00;
DisplayData[6] = DisplayData[2];
DisplayData[7] = DisplayData[3];
DigDisplay();
//--黄灯阶段--//
GPIO_TRAFFIC = 0xFF; //将所有的灯熄灭
RED00 = 1;
GREEN00 = 1;
YELLOW11 = 0; //宝田路黄灯亮
RED10 = 0; //宝田路人行道红灯亮
YELLOW01 = 0; //前进路黄灯亮
RED00 = 0; //前进路人行道红灯亮
}
//--前进路通行--//
else if(Second < 66)
{
DisplayData[0] = 0x00;
DisplayData[1] = 0x00;
DisplayData[2] = smgduan[(65 - Second) % 100 / 10];
DisplayData[3] = smgduan[(65 - Second) %10];
DisplayData[4] = 0x00;
DisplayData[5] = 0x00;
DisplayData[6] = DisplayData[2];
DisplayData[7] = DisplayData[3];
DigDisplay();
//--黄灯阶段--//
GPIO_TRAFFIC = 0xFF; //将所有的灯熄灭
RED00 = 1;
GREEN00 = 1;
RED11 = 0; //宝田路红灯亮
RED10 = 0; //宝田路人行道红灯亮
GREEN01 = 0; //前进路绿灯亮
GREEN00 = 0; //前进路人行道绿灯亮
}
//--黄灯等待切换状态,5秒--//
else
{
DisplayData[0] = 0x00;
DisplayData[1] = 0x00;
DisplayData[2] = smgduan[(70 - Second) % 100 / 10];
DisplayData[3] = smgduan[(70 - Second) %10];
DisplayData[4] = 0x00;
DisplayData[5] = 0x00;
DisplayData[6] = DisplayData[2];
DisplayData[7] = DisplayData[3];
DigDisplay();
//--黄灯阶段--//
GPIO_TRAFFIC = 0xFF; //将所有的灯熄灭
RED00 = 1;
GREEN00 = 1;
YELLOW11 = 0; //宝田路黄灯亮
RED10 = 0; //宝田路人行道红灯亮
YELLOW01 = 0; //前进路红灯亮
RED00 = 0; //前进路人行道红灯亮
}
}
}
/*******************************************************************************
* 函数名 : void Timer0() interrupt 1
* 函数功能 : 定时器0中断函数
*******************************************************************************/
void Timer0() interrupt 1
{
static u16 i;
TH0=0XFC; //给定时器赋初值,定时1ms
TL0=0X18;
i++;
if(i==1000)
{
i=0;
Second ++;
}
}
/**************************************************************************************
* NE555脉冲发生器实验 *
实验现象:下载程序后,数码管接2-2、2-3、2-4,NE555接法如图
注意事项:将NE555的短接片J11短接起来
***************************************************************************************/
#include "reg52.h" //此文件中定义了单片机的一些特殊功能寄存器
typedef unsigned int u16; //对数据类型进行定义
typedef unsigned char u8;
//--定义使用的IO--//
#define GPIO_DIG P0
sbit LSA=P2^2;
sbit LSB=P2^3;
sbit LSC=P2^4;
u8 code smgduan[17]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};//ÏÔʾ0~FµÄÖµ
u8 DisplayData[8];
//--定义全局变量--//
unsigned long Freq; //用来存放要显示的频率值
unsigned long TimeCount; //用于计算1s钟的
/*******************************************************************************
* 函数名 : delay
* 函数功能 : 延时函数
*******************************************************************************/
void delay(u16 i)
{
while(i--);
}
/*******************************************************************************
* 函数名 : DigDisplay
* 函数功能 : 数码管动态扫描函数,循环扫描8个数码管显示
*******************************************************************************/
void DigDisplay()
{
u8 i;
for(i=0;i<8;i++)
{
switch(i) //位选,选择点亮的数码管
{
case(0):
LSA=0;LSB=0;LSC=0; break;//显示第0位
case(1):
LSA=1;LSB=0;LSC=0; break;//显示第1位
case(2):
LSA=0;LSB=1;LSC=0; break;//显示第2位
case(3):
LSA=1;LSB=1;LSC=0; break;//显示第3位
case(4):
LSA=0;LSB=0;LSC=1; break;//显示第4位
case(5):
LSA=1;LSB=0;LSC=1; break;//显示第5位
case(6):
LSA=0;LSB=1;LSC=1; break;//显示第6位
case(7):
LSA=1;LSB=1;LSC=1; break;//显示第7位
}
GPIO_DIG=DisplayData[i];//发送段码
delay(100); //间隔一段时间扫描
GPIO_DIG=0x00;//消隐
}
}
/*******************************************
*函数名 :TIMER_Configuration
*功能 :配置定时/计数器T0和T1
*******************************************/
void Timer_Config()
{
//--定时器T1做计数器,工作方式1(16位定时器),只由TRx打开计数器--//
//--定时器T0做计数器,工作方式1(16位定时器),只由TRx打开计数器--//
TMOD=0x51;
//--设置定时器晶振为12MHZ时定时50ms--//
TH0=0x3C;
TL0=0xB0;
//--打开中断-//
ET0=1;
ET1=1;
EA=1;
//--打开定时器*/
TR0=1;
TR1=1;
}
/*******************************************************************************
* 函数名 : main
* 函数功能 : 主函数
*******************************************************************************/
void main()
{
Timer_Config();
while(1)
{
if(TR1 == 0) //当计数器停下的时候,表示计数完毕
{
Freq = Freq + TL1; //读取TL的值
Freq = Freq + (TH1 * 256); //读取TH的值
//--求频率的个十百千万十万位--//
DisplayData[0] = smgduan[Freq%1000000/100000];
DisplayData[1] = smgduan[Freq%100000/10000];
DisplayData[2] = smgduan[Freq%10000/1000];
DisplayData[3] = smgduan[Freq%1000/100];
DisplayData[4] = smgduan[Freq%100/10];
DisplayData[5] = smgduan[Freq%10];
//--显示完,重新计算下一次频率--//
Freq = 0;//将计算的频率清零
TH1 = 0; //将计数器的值清零
TL1 = 0;
TR0 = 1; //开启定时器
TR1 = 1; //开启计数器
}
//--显示求得的数值--//
DigDisplay();
}
}
/*******************************************
*函数名 :Timer0
*功能 :定时器0的中断函数
*******************************************/
void Timer0() interrupt 1
{
//--12MHZ设置定时50ms的初值--//
TH0=0x3C;
TL0=0xB0;
TimeCount++;
if(TimeCount==20)//计时到1S
{
TR0=0;
TR1=0;
TimeCount=0;
}
}
/*******************************************
*函数名 :Timer1
*功能 :定时器1的中断函数
*******************************************/
void Timer1() interrupt 3
{
//--进入一次中断,表明计数到了65536--//
Freq=Freq+65536;
}
1、异步通信
异步通信是指通信的发送与接收设备使用各自的时钟控制数据的发送和接收过程。为使双方的收发协调,要求发送和接收设备的时钟尽可能一致。异步通信是以字符(构成的帧)为单位进行传输,字符与字符之间的间隙(时间间隔)是任意的,但每个字符中的各位是以固定的时间传送的,即字符之间不一定有“位间隔”的整数倍的关系,但同一字符内的各位之间的距离均为“位间隔”的整数倍。
异步通信的特点:不要求收发双方时钟的严格一致,实现容易,设备开销较小,但每个字符要附加2~3位用于起止位,各帧之间还有间隔,因此传输效率不高。
2、同步通信
同步通信时要建立发送方时钟对接收方时钟的直接控制,使双方达到完全同步。此时,传输数据的位之间的距离均为“位间隔”的整数倍,同时传送的字符间不留间隙,即保持位同步关系,也保持字符同步关系。发送方对接收方的同步可以通过两种方法实现。
单工是指数据传输仅能沿一个方向,不能实现反向传输。
半双工是指数据传输可以沿两个方向,但需要分时进行。
全双工是指数据可以同时进行双向传输。
1、奇偶校验
在发送数据时,数据位尾随的1位为奇偶校验位(1或0)。奇校验时,数据中“1”的个数与校验位“1”的个数之和应为奇数;偶校验时,数据中“1”的个数与校验位“1”的个数之和应为偶数。接收字符时,对“1”的个数进行校验,若发现不一致,则说明传输数据过程中出现了差错。
2、代码和校验
代码和校验是发送方将所发数据块求和(或各字节异或),产生一个字节的校验字符(校验和)附加到数据块末尾。接收方接收数据同时对数据块(除校验字节外)求和(或各字节异或),将所得的结果与发送方的“校验和”进行比较,相符则无差错,否则即认为传送过程中出现了差错。
3、循环冗余校验
这种校验是通过某种数学运算实现有效信息与校验位之间的循环校验,常用于对磁盘信息的传输、存储区的完整性校验等。这种校验方法纠错能力强,广泛应用于同步通信中。
比特率是每秒钟传输二进制代码的位数,单位是:位/秒(bps)。如每秒钟传送240个字符,而每个字符格式包含10位(1个起始位、1个停止位、8个数据位),这时的比特率为:10位×240个/秒 =2400 bps
串行接口或终端直接传送串行信息位流的最大距离与传输速率及传输线的电气特性有关。当传输线使用每0.3m(约1英尺)有50PF电容的非平衡屏蔽双绞线时,传输距离随传输速率的增加而减小。当比特率超过1000bps 时,最大传输距离迅速下降,如9600bps 时最大距离下降到只有76m(约250英尺)。
RS-232C是EIA(美国电子工业协会)1969年修订RS-232C标准。RS-232C定义了数据终端设备(DTE)与数据通信设备(DCE)之间的物理接口标准。
1、机械特性
RS-232C接口规定使用25针连接器,连接器的尺寸及每个插针的排 列位置都有明确的定义。(阳头)
2、功能特性
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-v0BChDD7-1628929040451)(F:\01单片机学习笔记\RS232C功能特性.png)]
3、过程特性
过程特性规定了信号之间的时序关系,以便正确地接收和发送数据 。
1、传输距离短,传输速率低
RS-232C总线标准受电容允许值的约束,使用时传输距离一般不要超过15米(线路条件好时也不超过几十米)。最高传送速率为20Kbps。
2、有电平偏移
RS-232C总线标准要求收发双方共地。通信距离较大时,收发双方的地电位差别较大,在信号地上将有比较大的地电流并产生压降。
3、抗干扰能力差
RS-232C在电平转换时采用单端输入输出,在传输过程中当干扰和噪声混在正常的信号中。为了提高信噪比,RS-232C总线标准不得不采用比较大的电压摆幅。
RS-422A输出驱动器为双端平衡驱动器。如果其中一条线为逻辑“1”状态,另一条线就为逻辑“0”,比采用单端不平衡驱动对电压的放大倍数大一倍。差分电路能从地线干扰中拾取有效信号,差分接收器可以分辨200mV以上电位差。若传输过程中混入了干扰和噪声,由于差分放大器的作用,可使干扰和噪声相互抵消。因此可以避免或大大减弱地线干扰和电磁干扰的影响。RS-422A传输速率(90Kbps)时,传输距离可达1200米。
RS-485是RS-422A的变型:RS-422A用于全双工,而RS-485则用于半双工。RS-485是一种多发送器标准,在通信线路上最多可以使用32 对差分驱动器/接收器。如果在一个网络中连接的设备超过32个,还可以使用中继器。
RS-485的信号传输采用两线间的电压来表示逻辑1和逻辑0。由于发送方需要两根传输线,接收方也需要两根传输线。传输线采用差动信道,所以它的干扰抑制性极好,又因为它的阻抗低,无接地问题,所以传输距离可达1200米,传输速率可达1Mbps。
RS-485是一点对多点的通信接口,一般采用双绞线的结构。普通的PC机一般不带RS485接口,因此要使用RS-232C/RS-485转换器。对于单片机可以通过芯片MAX485来完成TTL/RS-485的电平转换。在计算机和单片机组成的RS-485通信系统中,下位机由单片机系统组成,上位机为普通的PC机,负责监视下位机的运行状态,并对其状态信息进行集中处理,以图文方式显示下位机的工作状态以及工业现场被控设备的工作状况。系统中各节点(包括上位机)的识别是通过设置不同的站地址来实现的。
/**************************************************************************************
实验现象:下载程序后打开串口调试助手,将波特率设置为4800,选择发送的数据就可以显示
接线说明: 需要USB转TTL模块。UTXD接P30R,URXD接P30T
注意事项:
***************************************************************************************/
#include "reg52.h" //此文件中定义了单片机的一些特殊功能寄存器
typedef unsigned int u16; //对数据类型进行声明定义
typedef unsigned char u8;
/*******************************************************************************
* 函数名 :UsartInit()
* 函数功能 :设置串口
* 输入 : 无
* 输出 : 无
*******************************************************************************/
void UsartInit()
{
SCON=0X50; //设置为工作方式1
TMOD=0X20; //设置计数器工作方式2
PCON=0X80; //波特率加倍
TH1=0XF3; //计数器初始值设置,注意波特率是4800的
TL1=0XF3;
ES=1; //打开接收中断
EA=1; //打开总中断
TR1=1; //打开计数器
}
/*******************************************************************************
* 函 数 名 : main
* 函数功能 : 主函数
* 输 入 : 无
* 输 出 : 无
*******************************************************************************/
void main()
{
UsartInit(); // 串口初始化
while(1);
}
/*******************************************************************************
* 函数名 : Usart() interrupt 4
* 函数功能 : 串口通信中断函数
* 输入 : 无
* 输出 : 无
*******************************************************************************/
void Usart() interrupt 4
{
u8 receiveData;
receiveData=SBUF;//出去接收到的数据
RI = 0;//清除接收中断标志位
SBUF=receiveData;//将接收到的数据放入到发送寄存器
while(!TI); //等待发送数据完成
TI=0; //清除发送完成标志位
}