STC单片机串口收发学习总结

STC单片机串口收发学习总结

  • 1字符串输出到串口
  • 2LED闪烁
  • 3LED流水灯
  • 4定时器
  • 5中断
  • 6定时与中断应用示例
  • 7数码管
  • 8串口
  • 9RS232接口

1字符串输出到串口

////////////////////////////////////////////////////////
//单片机串口发送字符
////////////////////////////////////////////////////////
#include<reg51.h>		//51单片机头文件(单片机寄存器解释文件)
#include<stdio.h>		//输入输出函数头文件
void main(void)			//主函数
{	TI=1;				//串口发送标志
	while(1)			//主循环
	{
		printf("HELLO C!\r\n");//字符串输出到串口
	}
}

2LED闪烁

#include<reg51.h>
sbit LED=P3^7;				//定义特殊功能寄存器P3^7为LED
void main(void)
{
	unsigned int i;			//定义无符号16位数i
	while(1)
	{
	for(i=0;i<52000;i++)	//for循环,用于延时
		LED=~LED;			//LED取反操作
	}
}

3LED流水灯

#include<reg51.h>
void delay()//延时函数
{
	unsigned int i;
	for(i=0;i<52000;i++);	
}

void main()
{
	unsigned char i;			
	while(1)
	{
		for(i=0;i<8;i++)
		{
			P0=0x01<<i;//从右往左
			P0=0x80>>i;//从左往右
			delay();//调用延时函数
		}
	}
}

4定时器

#include<reg51.h>
sbit POUT=P1^0;
void main(void)
{
	TMOD=0x01;		//设置工作方式
	TH0=0xfc;		//装初值
	TL0=0x18;
	TR0=1;			//开定时器0
	while(1)
	{
		if(TF0==1)	//判断是否溢出
		{
			TF0=0;	//清除溢出标志
			TH0=0xfc;//重新装入初值
			TL0=0x18;
			POUT=!POUT;
		}
	}
}
  • 1.定时器/计数器原理框图
    STC单片机串口收发学习总结_第1张图片
  • 51单片机通常有两个16位寄存器/计数器(T0&T1)。
  • 每来一个脉冲,计数器+1。16位计数器技术范围为0000-FFFF。
  • 当输入脉冲通过单片机引脚输入,实现计数器功能。 当外部输入脉冲间隔确定时,计数器便可当定时器使用。
  • 加满后会产生溢出,并且清零。
  • 16位计数器是由THx和TLx两个八位寄存器组成的加1计数器。
  • C/T ̅=1时为技术功能,被计数脉冲由Tx引脚输入。
  • C/T ̅=0时为定时功能,输入脉冲由振荡器(晶振)的12分频提供。
  • 如:12M晶振,提供1MHz脉冲,周期1us。
  • 脉冲和定时器间有控制端()。“1”启动,计数器运行;“0”停止,计数器停止。
  • 单片机通过读取定时器溢出标志(TFx),判断定时器工作状态。
  • 工作步骤:1、设置工作模式(定时器/计数器);2、计算并装入初值;3、启动运行;4、等待溢出。
    2. 定时器相关寄存器
    STC单片机串口收发学习总结_第2张图片
  • 单片机中所有的控制和标志都是通过对特定寄存器的读写来实现的。(开关操作:写;TFx状态:读)
  • 定时器工作方式寄存器TMOD(低四位T0/高四位T1):
    (1)GATE:门控位
    0:以TRx来启动定时器/计数器运行。(一般置零
    1:以外部中断和TRx来启动定时器/计数器运行。
    (2)C/T ̅:计数器模式/定时器模式选择位
    0:定时器模式。
    1:计数器模式。
    (3)M1&M0:工作方式选择位
    M1M0=00(方式0):13位定时器/计数器。
    M1M0=01(方式1):16位定时器/计数器。(计数范围大,常用。)
    M1M0=10(方式2):8位常数自动重新装载。(自动重装:溢出清零后自动写入初值,用于串口的波特率发生器。)
    M1M0=11(方式3):T0分为两个8位计数器,T1停止计数。(少用)
  • 控制寄存器TCON(高四位):
    (1)TF1/TF0:计数溢出标志位。
    定时器T0或T1计数溢出时,由硬件自动将此位置置“1”;
    TFx可以由程序查询,也是定时中断的请求源。
    (2)TR1/TR0:计数运行控制位。
    TRx=1:启动定时器/计数器。
    TRx=0:停止定时器/计数器。
    3. 定时器/计数器原理框图
    • 要求:采用定时器0,方式1,实现1ms定时,每隔1ms,P10取反一次,晶振为12MHz(12×〖10〗(-6))。
    • 编程:
      1、确定工作方式,TMOD设置为0001H。
      2、计算初值:(216-x)×(12×〖10〗(-6)÷12)=1×〖10〗^(-3) s,初值x,计数范围2^16。
      可求得:x=65536-1000=64536,化为16进制为FC18,即:TH0=FCH,TL0=18H。
      3、根据需要设置中断。
      4、TR0置位,启动定时/技术器。
      5、反复查询TF0是否为1,判断是否完成定时。
      6、如果定时完成,清除TF0标志,重新装入初值,进行下一轮定时。

5中断

STC单片机串口收发学习总结_第3张图片
(查询方式执行)在定时器程序中,当TR0=1时,定时器打开,定时器开始工作,计数器开始+1,但CPU并不知道什么时候定时器溢出。CPU通过不断反复查询TF0状态,判断是否溢出。
响应时间与查询次数之间存在矛盾:响应时间短——查询次数多。
解决办法:中断系统。
STC单片机串口收发学习总结_第4张图片

  • 中断的产生:使用哪个中断就打开相应中断开关和总开关。
    中断源:定时中断2个(定时器溢出TF0/TF1)、外部中断2个(TCON低四位:IE0/IE1)、串行中断1个(串口通信部分)。
    中断允许开关:EA—中断总开关;ES—串行中断允许开关;ET1—定时1中断允许开关;EX1—外部1中断允许开关。
  • 中断的响应:
    (中断的方式执行)①设定工作模式、设初值、打开定时器(与查询方式相同);②打开中断总开关、开定时0中断;③不需要反复查询,CPU可以做自己想做的(没事干就while(1));④发生溢出时(产生中断源),程序会自动跳入中断服务子程序void time a () interrupt b:其中,a—0定时器0,a—1定时器1;b—1定时器0,b—0外部中断0,b—2外部中断1, b—3定时器1, b—4串行中断。
  • 好处:避免响应时间与查询次数之间的矛盾,提升程序工作效率;中断方式TF0不需要软件置零,硬件产生完中断后会自动将其置零。
    STC单片机串口收发学习总结_第5张图片
#include<reg51.h>
sbit POUT=P1^0;
void main(void)
{
	TMOD=0x01;		//设置工作方式
	TH0=0xfc;		//装初值
	TL0=0x18;
	TR0=1;			//开定时器0
	EA=1;			//开中断总开关
	ET0=1;			//开定时0中断
	while(1);
}
void time0() interrupt 1	//定时器1的中断服务函数
{
	TH0=0xfc;//重新装入初值
	TL0=0x18;
	POUT=!POUT;		
}

6定时与中断应用示例

/***********************************************************
*程序功能:查询方式,定时器工作于方式1,每隔一秒发光二极管闪烁一次。(晶振11.0592M)
***********************************************************/
#include<reg51.h>
#define uint unsigned int
uint pp;
sbit POUT=P1^0;
void main(void)
{
	TMOD=0x01;		//设置工作方式,定时器0,工作模式1(M1=0,M0=1)
	TH0=0xff;		//装初值,定时设置为100us,定时10000次。
	TL0=0xa4;		//对于晶振为11.0592M晶振的单片机最大定时时长只有几十毫秒
	TR0=1;			//开定时器0
	while(1)
	{
		if(TF0==1)	//单片机反复查询定时器0的溢出标志位TF0
		{
		TF0=0;
		pp++;		//每定时一次PP+1
		TH0=0xff;//重新装入初值
		TL0=0xa4;
		}
		if(pp==10000)
		{
		POUT=~POUT;
		pp=0;
		}		
	}
}
/***********************************************************
*程序功能:中断方式,定时器工作于方式1,每隔一秒发光二极管闪烁一次。(晶振11.0592M)
***********************************************************/
#include<reg51.h>
#define uint unsigned int
uint pp;
sbit POUT=P1^0;
void main(void)
{
	TMOD=0x01;		//设置工作方式,定时器0,工作模式1(M1=0,M0=1)
	TH0=0xff;		//装初值,定时设置为100us,定时10000次。
	TL0=0xa4;		//对于晶振为11.0592M晶振的单片机最大定时时长只有几十毫秒
	TR0=1;			//开定时器0
	EA=1;			//开总中断
	ET0=1;			//开定时器0中断
	while(1)
	{
		if(pp==10000)
		{
		POUT=~POUT;
		pp=0;
		}		
	}
}
void time0() interrupt 1
{
	pp++;		//每定时一次PP+1
	TH0=0xff;//重新装入初值
	TL0=0xa4;
}	
/***********************************************************
*程序功能:外部中断方式,定时器工作于方式1,每隔一秒发光二极管闪烁一次。(晶振11.0592M)
***********************************************************/
#include<reg51.h>
sbit	LED1=P0^0;
sbit	LED2=P0^1;
void ISR0(void) interrupt 0 //外部中断0服务函数
{
	LED1=~LED1;
}
void ISR1(void) interrupt 2 //外部中断1服务函数
{
	LED2=~LED2;
}
void main(void)
{
	IP=0x05;	//外部中断0和外部中断1设置为高优先级
	IT0=1;		//外部中断0为下降沿触发(中断引脚P3.2输入下降沿信号时引发中断)
	IT1=1;		//外部中断1为下降沿触发(中断引脚P3.3输入下降沿信号时引发中断)
	EX0=1;		//开外部中断0
	EX1=1;		//开外部中断1
	EA=1;		//开中断总开关
	while(1);
}

7数码管

  • 静态数码管
    STC单片机串口收发学习总结_第6张图片
    共阴&共阳两种数码管,公共端分别接地/VCC,A-H引脚分别接单片机I/O口。
    STC单片机串口收发学习总结_第7张图片
    共阴数码管数组定义0-F显示码:a
    unsigned char code LED7code[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,
    0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e};
    STC单片机串口收发学习总结_第8张图片
  • 动态数码管
    位控端:控制哪个数码管亮;段控端:控制单个数码管显示。
    位控端使几个数码管轮流显示,由视觉暂停效应使得视觉上多个数码管是同时点亮的。
    STC单片机串口收发学习总结_第9张图片
    由于单片机I/O口输出电流是有限的,位控端连接七个LED需要三极管放大。
    STC单片机串口收发学习总结_第10张图片
/*************************************************************
*程序功能:静态数码管,数码管轮流显示0-F
*************************************************************/
#include<reg51.h>
unsigned char code LED7code[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,
0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e};//数组,定义0-F显示码
void delay(void)
{
	unsigned int i;
	for(i=0;i<65000;i++);
}
void main(void)
{
	unsigned char i;
	P2=0xfe;			//
	while(1)
	{
		for(i=0;i<16;i++)//16个内容循环显示
		{
		P0=LED7code[i];//P0口连接数码管A-H
		delay();
		}
	}
}
/*************************************************************
*程序功能:数码管动态显示
*************************************************************/
#include<reg51.h>
unsigned char code wei[]={~0x08,~0x04,~0x02,~0x01};//数码管各位码表
unsigned char code duan[]={0xc0,0xf9,0xa4,0xb0};//0-3码表
void delay(unsigned int i)
{
	unsigned int m,n;
	for(m=i;m>0;m--);
		for(n=90;n>0;n--);
}
void main(void)
{
	unsigned char num;			
	while(1)
	{
		for(num=0;num<4;num++)
		{
		P2=	wei[num];
		P0=duan[num];
		delay(20);
		}
	}
}

8串口

计算机与外设/计算机与计算机之间的通信:并行通信、串行通信。
STC单片机串口收发学习总结_第11张图片

  • 并行通信:把所有的数据端连在一起一次处理,如8位计算机一次处理8个位的数据,需要询问(WR) ̅、应答(RD) ̅、8根数据线A0-8地址端/D0-8数据端。(优缺点)速度快;但是硬件连接复杂。
    STC单片机串口收发学习总结_第12张图片
  • 串行通信:数据分时通过同一通道传输。(优缺点)传输速度慢;硬件简单,最多只需要2根线RXD接收端/TXD发送端。
    STC单片机串口收发学习总结_第13张图片
  • 串行通信的三种方式:单工(A->B)、半双工(A->B|B->A)、全双工(A->B&B->A)。单片机是全双工异步通信方式。
    STC单片机串口收发学习总结_第14张图片
  • 异步串口通信帧格式:起始位(由1—0,下降沿)一个数据是10/11位(区别在于奇偶校验位)串口方式1(10位一帧)无校验位,低位在前(读数时从后往前读D7-0)。
    STC单片机串口收发学习总结_第15张图片
    波特率:设置正确的波特率才能收到正确的数据。
    STC单片机串口收发学习总结_第16张图片
  • 串口的相关寄存器:
    1、串行数据缓冲器SBUF:
    在这里插入图片描述
    2、串行控制寄存器SCON:
    在这里插入图片描述
    RI—接收中断标志位;TI—发送中断标志位;
    RB8/TB8—接收及发送数据第9位(奇偶校验位);
    REN—接收控制(0:禁止;1:允许);
    SM2—多机通信(0:双机;1:多机);
    SM1/SM0—串行口工作方式选择:
    方式0,同步移位寄存器输入/输出,波特率固定为fosc/12;
    方式1,10位异步收发,波特率可变(T1溢出率/n,n=32/16);
    方式2,11位异步收发,波特率固定为fosc/n,n=32/16;
    方式3,11位异步收发,波特率可变(T1溢出率/n,n=32/16)。
/*************************************************************
*程序功能:串口发送Hello
*************************************************************/
#include<reg51.h>
#include<stdio.h>	//输入输出函数头文件
void main(void)
{
	SCON=0X50;	//串口方式1允许接收
	TMOD=0X20;	//定时器1定时方式2
	TH1=0XF4;	//11.0592M	2400波特率
	TL1=0xF4;
	TI=1;		//串口发送标志
	TR1=1;		//启动定时器
	
	while(1)
	{
		printf("Hello world!\r\n");//字符串输出到串口
	}
}
/**************************************************
*串口通信实验:发送
**************************************************/
#include<reg51.h>
#include<stdio.h>	//输入输出函数头文件
unsigned char code MESSAGE[]="My first serial data!\n";
unsigned char a;
void delay(unsigned int i)
{
	unsigned char j;
	for(i;i>0;i++)
		for(j=200;j>0;j--);
}
void main(void)
{
	SCON=0X50;	//REN=1允许接收状态 串口方式1
	TMOD|=0X20;	//定时器1定时方式2
	TH1=0XF4;	//11.0592M	2400波特率 数据位8 停止位1
	TL1=0xF4;
	TI=1;		//串口发送标志
	TR1=1;		//启动定时器
	
	while(1)
	{
		a=0;
		while(MESSAGE[a]!='\0')	//数组最后一个位为'\0'
		{
			SBUF=MESSAGE[a];	//SBUF接收/发送缓冲器(串行通信特殊功能寄存器)
			while(!TI);			//等待数据传送(TI发送中断标志) TI=1时说明数据发送完成
			TI=0;				//清除数据传输标志
			a++;				//下一个字符
		}
		delay(1000);
	}
}
/**************************************************
*串口通信实验:收发(数据转发功能:单片机收到了电脑发送的数据后又转发回给电脑)
**************************************************/
#include<reg51.h>
#define uchar unsigned char
uchar a,flag;				//设置全局变量
void main()
{
	SCON=0X50;	//REN=1允许接收状态 串口方式1
	TMOD=0X20;	//定时器1定时方式2
	TH1=0XF4;	//11.0592M	2400波特率 数据位8 停止位1
	TL1=0xF4;
	TI=1;		//串口发送标志
	TR1=1;		//启动定时器
	EA=1;		//开总中断
	ES=1;		//开串中断
	while(1)
	{
		if(flag==1)		//如果有数据则进入这个语句
		{
			ES=0;		//进入发送数据时先关闭串行中断
			flag=0;
			SBUF=a;		//将数据原样发回
			while(!TI);	//等待数据发完
			TI=0;
			ES=1;		//退出再开串行中断
		}
	}
}
void serial() interrupt 4//串行中断函数
{
	a=SBUF;				//将收取的数据存到a
	flag=1;				//标志置位——表示单片机收到数据
	RI=0;				//接收标志清零
}

9RS232接口

  • RS232接口标准:
    STC单片机串口收发学习总结_第17张图片
    RS232最常用的就是2-RXD、3-TXD、5-GND。
    注意:在传输距离近的情况下(距离<1m),单片机和电脑可以直接通过TTL的线连接进行通信;连接线过长时,由于(单片机输出都是TTL信号)TTL电压比较低衰减比较厉害,可以转换(MAX232/220/202芯片)为232的方式进行传输(15m以内传输没问题,速率较低时采用双绞线传输距离还可以更长30-35m)
    在这里插入图片描述
    STC单片机串口收发学习总结_第18张图片
    RS232的连接:连接线有直通线&交叉线
    STC单片机串口收发学习总结_第19张图片
    易损坏,不支持热拔插,带电不要拔插。

你可能感兴趣的:(单片机学习笔记)