51单片机入门零基础2.5串口发数

合集下载

51单片机汇编语言入门教程

51单片机汇编语言入门教程

51单片机汇编语言入门教程什么是51单片机
51单片机指的是英特尔公司推出的一种单片机芯片种类,其名字为“AT89S52”。

后来,这种芯片因其使用广泛,被人们简称为“51单片机”。

为什么要研究汇编语言
研究汇编语言能够让我们更好地理解机器是如何执行指令的,
从而更好地优化程序,提高程序运行效率。

汇编语言基础知识
数据类型
- 字节:一个字节是8位二进制数,可以表示0~255之间的数。

- 字:一个字是16位二进制数,可以表示0~之间的数。

- 双字:一个双字是32位二进制数,可以表示0~之间的数。

指令集
51单片机有大约100条汇编指令,这些指令可以完成各种操作,如运算、数据传输、中断处理等。

寄存器
51单片机有4个8位的通用寄存器(寄存器0~3)和2个16
位的通用寄存器(DPTR和PC)。

程序结构
51单片机只有一种程序结构——线性结构。

程序从0地址开始执行,一条一条地执行,直到程序结束。

编写第一个汇编程序
以下是一个简单的汇编程序示例:
ORG 0H ;设置程序起始地址为0H
MOV P1, #55H ;将55H赋值给P1口
END ;程序结束指令
这个程序的作用是将55H赋值给P1口。

总结
通过学习本教程,我们了解了基本的汇编语言知识,包括数据
类型、指令集、寄存器、程序结构以及编写程序的基本步骤。

希望
这份教程可以帮助初学者顺利掌握51单片机汇编语言编程的基础。

51单片机串口通信

51单片机串口通信

一、串口通信原理串口通讯对单片机而言意义重大,不但可以实现将单片机的数据传输到计算机端,而且也能实现计算机对单片机的控制。

由于其所需电缆线少,接线简单,所以在较远距离传输中,得到了广泛的运用。

串口通信的工作原理请同学们参看教科书。

以下对串口通信中一些需要同学们注意的地方作一点说明:1、波特率选择波特率(Boud Rate)就是在串口通信中每秒能够发送的位数(bits/second)。

MSC-51串行端口在四种工作模式下有不同的波特率计算方法。

其中,模式0和模式2波特率计算很简单,请同学们参看教科书;模式1和模式3的波特率选择相同,故在此仅以工作模式1为例来说明串口通信波特率的选择。

在串行端口工作于模式1,其波特率将由计时/计数器1来产生,通常设置定时器工作于模式2(自动再加模式)。

在此模式下波特率计算公式为:波特率=(1+SMOD)*晶振频率/(384*(256-TH1))其中,SMOD——寄存器PCON的第7位,称为波特率倍增位;TH1——定时器的重载值。

在选择波特率的时候需要考虑两点:首先,系统需要的通信速率。

这要根据系统的运作特点,确定通信的频率范围。

然后考虑通信时钟误差。

使用同一晶振频率在选择不同的通信速率时通信时钟误差会有很大差别。

为了通信的稳定,我们应该尽量选择时钟误差最小的频率进行通信。

下面举例说明波特率选择过程:假设系统要求的通信频率在20000bit/s以下,晶振频率为12MHz,设置SMOD=1(即波特率倍增)。

则TH1=256-62500/波特率根据波特率取值表,我们知道可以选取的波特率有:1200,2400,4800,9600,19200。

列计数器重载值,通信误差如下表:因此,在通信中,最好选用波特率为1200,2400,4800中的一个。

2、通信协议的使用通信协议是通信设备在通信前的约定。

单片机、计算机有了协议这种约定,通信双方才能明白对方的意图,以进行下一步动作。

假定我们需要在PC机与单片机之间进行通信,在双方程式设计过程中,有如下约定:0xA1:单片机读取P0端口数据,并将读取数据返回PC机;0xA2:单片机从PC机接收一段控制数据;0xA3:单片机操作成功信息。

c51单片机串口初值计算

c51单片机串口初值计算

c51单片机串口初值计算
单片机串口的初值计算是为了设置串口通信的波特率(Baud Rate),波特率是指串口每秒传输的位数。

在51单片机中,串口模块由SBUF(串口数据寄存器)、SCON(串口
控制寄存器)和PCON(功耗控制寄存器)组成。

串口通信的波特率设置
是通过控制SCON和PCON寄存器的相关位实现的。

以下是一种计算波特率初值的方法:
1.确定所需的波特率,例如1200。

2.计算定时器T1的初值:
其中,CPU时钟频率是指单片机的工作频率,如12MHz。

3.将T1的高8位和低8位分别存储到TH1寄存器和TL1寄存器中:
TH1=T1高8位
TL1=T1低8位
4.设置串口模式和波特率控制位:
SCON=SCON,0x50;//设置串口工作在模式1(8位数据,可变波特率)PCON=PCON,0x80;//设置波特率控制位,使能T1控制波特率
5.启动定时器T1:
TR1=1;//启动定时器T1
通过以上步骤,就可以计算并设置51单片机串口的波特率初值。

需要注意的是,由于计算初值时取整会导致一定的误差,因此实际波特率可能会略有偏差。

51单片机串口通信连续发送接收字节

51单片机串口通信连续发送接收字节

51单片机串口通信连续发送接收字节51单片机串口通信连续发送接收字节当使用单片机串口通信,连续发送字节时,如何处理呢?使用串口中断接收发送字节,中断内的程序尽可能简单,因为考虑到占用时间。

本文以连续发送4个字节为例,给出例程如下所示:本例程使用的单片机型号为:IAP15W4K58S//工作频率为11.0592MHz#include "reg51.h"#include "intrins.h"typedef unsigned char BYTE;typedef unsigned int WORD;#define FOSC 11059200L //系统频率//#define BAUD 115200 //#define BAUD 9600 //定义串口波特率#define Num_byte 4 //接收数据4个字节BYTE Data_temp[Num_byte]={0,0,0,0};sfr P0M1 = 0x93;sfr P0M0 = 0x94;sfr P1M1 = 0x91;sfr P1M0 = 0x92;sfr P2M1 = 0x95;sfr P2M0 = 0x96;sfr P3M1 = 0xb1;sfr P3M0 = 0xb2;sfr P4M1 = 0xb3;sfr P4M0 = 0xb4;sfr P5M1 = 0xC9;sfr P5M0 = 0xCA;sfr P6M1 = 0xCB;sfr P6M0 = 0xCC;sfr P7M0 = 0xE2;sfr AUXR = 0x8e; //辅助寄存器sfr T2H = 0xd6; //定时器2高8位sfr T2L = 0xd7; //定时器2低8位sfr P_SW1 = 0xA2; //外设功能切换寄存器1sbit LED1=P1^1;sbit LED2=P1^2;bit busy=0; //定义是否接收完4个字节BYTE num=0; //记录4个字节的数据void SendData(BYTE dat);void SendString(char *s);BYTE read_Byte();void delay();void main(){P0M0 = 0x00;P0M1 = 0x00;P1M0 = 0x00;P1M1 = 0x00;P2M0 = 0x00;P2M1 = 0x00;P3M0 = 0x00;P3M1 = 0x00;P4M0 = 0x00;P4M1 = 0x00;P5M0 = 0x00;P5M1 = 0x00;P6M0 = 0x00;P7M0 = 0x00;P7M1 = 0x00;P_SW1 &= 0x3F; //(P3.0/RxD, P3.1/TxD)SCON = 0x50; //8位可变波特率,允许接收T2L = (65536 - (FOSC/4/BAUD)); //设置波特率重装值T2H = (65536 - (FOSC/4/BAUD))>>8;AUXR = 0x15; //T2为1T模式, 并启动定时器2,选择定时器2为串口1的波特率发生器ES = 1; //使能串口1中断EA = 1;//SendString("STC15F2K60S2\r\nUart Test !\r\n");while(1){if(busy){ES=0;for(num=0;num<num_byte;num++)< p="">{SBUF= Data_temp[num]+0x05;while(!TI);TI=0;}num=0;ES=1;busy=0;}//SendData(3);//delay();//delay();;}/*----------------------------UART 中断服务程序-----------------------------*/void Uart() interrupt 4 using 1{ES=0;RI = 0; //清除RI位Data_temp[num++]= SBUF;if(num==Num_byte)busy=1;ES=1;}/*----------------------------发送串口数据----------------------------*/void SendData(BYTE dat){while (busy); //等待前面的数据发送完成SBUF = dat; //写数据到SBUF寄存器busy = 1;}/*----------------------------发送字符串----------------------------*/void SendString(char *s){while (*s) //检测字符串结束标志{SendData(*s); //发送当前字符s++;}//接收1个字节BYTE read_Byte(){ BYTE character; character = SBUF; return character;}void delay(){ BYTE i,j;for(i=220;i--;i>0)for(j=220;j--;j>0); }</num_byte;num++)<>。

51单片机串行口的工作方式

51单片机串行口的工作方式
☞再比如要显示“3” 须令a b c d g 为“0” 电平,e f h为“1”电平。
hgfedcba
a
fg b
e
c
dh
共阳极
累加器 A hgfedcba
0C0H = “0”
0B0H = “3”
例:利用串行口工作方式0扩展出8位并行I/O 口,驱动共阳LED数码管显示0—9。
VCC TxD RxD
☞方式2的波特率 = fosc 2SMOD/64 即: fosc 1/32 或 fosc 1/64 两种
☞奇偶校验是检验串行通信双方传输的数据正确与 否的一个措施,并不能保证通信数据的传输一定正 确。
换言之:如果奇偶校验发生错误,表明数据传输 一定出错了;如果奇偶校验没有出错,绝不等于数 据传输完全正确。
☞ REN:串行口接收允许位。 REN=1 允许接收
☞ TB8,RB8,TI,RI等位由运行中间的情况 决定,可先写成 “0”
三、工作方式2: 9位UART(1+8+1+1位)两种波特率
☞由于波特率固定,常用于单片机间通讯。 数据由8+1位组成,通常附加的一位 (TB8/RB8)用于“奇偶校验”。
☞ 溢出率:T1溢出的频繁程度 即:T1溢出一次所需时间的倒数。
☞ 波特率 =
2SMOD fosc 32 12(2n - X)
其中:X 是定时器初值
☞ 初值 X = 2n -
2SMOD fosc 32 波特率 12
常用波特率和T1初值查表
☞表格有多种, 晶振也不止一种
串口波特率 (方式1,3)
74LS164
hgfedcba
A B
CLK
CLR
74LS164

51单片机模拟串口通讯

51单片机模拟串口通讯

论坛新老朋友们。

祝大家新年快乐。

在新的一年开始的时候,给大家一点小小的玩意。

工程师经常碰到需要多个串口通信的时候,而低端单片机大多只有一个串行口,甚至没有串口。

这时候无论是选择高端芯片,还是更改系统设计都是比较麻烦的事。

我把以前搞的用普通I/O口模拟串行口通讯的程序拿出来,供大家参考,希望各位兄弟轻点拍砖。

基本原理:我们模拟的是串行口方式1.就是最普通的方式。

一个起始位、8个数据位、一个停止位。

模拟串行口最关键的就是要计算出每个位的时间。

以波特率9600为例,每秒发9 600个位,每个位就是1/9600秒,约104个微秒。

我们需要做一个精确的延时,延时时间+对IO口置位的时间=104微秒。

起始位是低状态,再延时一个位的时间。

停止位是高状态,也是一个位的时间。

数据位是8个位,发送时低位先发出去,接收时先接低位。

了解这些以后,做个IO模拟串口的程序,就是很容易的事。

我们开始。

先上简单原理图:就一个MAX232芯片,没什么好说的,一看就明白。

使用单片机普通I/ O口,232数据输入端使用51单片机P3.2口(外部中断1口,接到普通口上也可以,模拟中断方式的串行口会有用。

呵呵)。

数据输出为P0.4(随便哪个口都行)。

下面这个程序,您只需吧P0.4 和P3.2 当成串口直接使用即可,经过测试完全没有问题.2、底层函数代码如下:sbit TXD1 = P0^4; //定义模拟输出脚sbit RXD1 = P3^2; //定义模拟输入脚bdata unsigned char SBUF1; //定义一个位操作变量sbit SBUF1_bit0 = SBUF1^0;sbit SBUF1_bit1 = SBUF1^1;sbit SBUF1_bit2 = SBUF1^2;sbit SBUF1_bit3 = SBUF1^3;sbit SBUF1_bit4 = SBUF1^4;sbit SBUF1_bit5 = SBUF1^5;sbit SBUF1_bit6 = SBUF1^6;sbit SBUF1_bit7 = SBUF1^7;void delay_bps() {unsigned char i; for (i = 0; i < 29; i++); _nop_(); _nop_();} //波特率9600 模拟一个9600波特率unsigned char getchar2() //模拟接收一个字节数据{while (RXD1);_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_(); delay_bps();SBUF1_bit0 = RXD1; //0delay_bps();SBUF1_bit1 = RXD1; //1delay_bps();SBUF1_bit2 = RXD1; //2delay_bps();SBUF1_bit3 = RXD1; //3delay_bps();SBUF1_bit4 = RXD1; //4delay_bps();SBUF1_bit5 = RXD1; //5delay_bps();SBUF1_bit6 = RXD1; //6delay_bps();SBUF1_bit7 = RXD1; //7delay_bps();return(SBUF1) ; //返回读取的数据}void putchar2(unsigned char input) //模拟发送一个字节数据{SBUF1 = input;TXD1 = 0; //起始位delay_bps();TXD1 = SBUF1_bit0; //0delay_bps();TXD1 = SBUF1_bit1; //1delay_bps();TXD1 = SBUF1_bit2; //2delay_bps();TXD1 = SBUF1_bit3; //3delay_bps();TXD1 = SBUF1_bit4; //4delay_bps();TXD1 = SBUF1_bit5; //5delay_bps();TXD1 = SBUF1_bit6; //6delay_bps();TXD1 = SBUF1_bit7; //7delay_bps();TXD1 = 1; //停止位delay_bps();}3、实现串行通讯。

MCS-51单片机的串行口及控制寄存器

MCS-51单片机的串行口及控制寄存器

位序
B7
B6
B5
B4
B3
B2
B1
B0
位符
smod
/
/
/
GF1
Hale Waihona Puke GF0PDIDL

PD和IDL:是CHMOS单片机用于进入低功耗方式的控制位,在第 2章中已介绍过这两位的应用。
GF1和GF0:用户使用的一般标志位。
smod:串行口波特率倍增位,当smod=1时,串行口波特率增加 1倍。系统复位时,smod=0。
位地 址
位符 号
0AFH 0AEH 0ADH 0ACH 0ABH 0AAH 0A9H 0A8 H
EA
/
/
ES
ET1
EX1
ET1 EX0
其中与串行口有关的是ES位。当ES=0时,禁止串行口的中断; 当ES=1时,表示允许串行口中断。EX0、ET0、EX1、ET1分别表示 对外中断0、定时器/计数器0、外中断1、定时器/计数器1个中断 源的中断允许控制,EA是中断总允许控制位,详见本书第5章介绍。
PCON寄存器的B6、B5、B4位未定义。
3. 中断允许寄存器IE
中断允许寄存器IE,是MCS-51单片机中实现是否开放某 中断源中断的控制寄存器,在第5章中已做过介绍。IE寄存 器 是 可 寻 址 的 寄 存 器 , 其 字 节 地 址 为 0 A8H, 位 地 址 由 0A8H~0AFH,IE寄存器各位定义如下:
0BBH PT1
0BAH PX1
0B9H PT0
0B8H
PX0
其中与串行口有关的是PS位,当PS=0时,表示串行口中断处于 低优先级别;当PS=1时,表示串行口中断处于高优先级别。PX0、 PT0、PX1、PT1分别控制外中断0、定时器/计数器0、外中断1、定 时器/计数器1中断源的中断优先级别,详见本书第5章介绍。

51单片机串口波特率计算

51单片机串口波特率计算

51单片机串口波特率计算
在51单片机中,串口通信可以通过设置波特率来控制数据传输速度。

波特率是指每秒钟传输的数据位数。

要计算51单片机串口的波特率,需要了解以下几个参数:
1.时钟频率:51单片机的时钟频率通常为12MHz或者11.0592MHz。

这是由外部晶振或者内部时钟发生器提供的。

2.波特率发生器(UART)的参数:波特率发生器的输入时钟频率为时
钟频率的12分频。

串口通信的常用波特率有1200、2400、4800、9600等。

接下来我们
以计算1200波特率为例进行说明。

首先,计算波特率发生器的输入时钟频率:
输入时钟频率=时钟频率/12
假设时钟频率为11.0592MHz,则输入时钟频率为:
输入时钟频率=11.0592MHz/12≈921.6kHz
然后,根据波特率公式计算波特率发生器的计数器初值:
计数器初值=输入时钟频率/(16*波特率)
对于1200波特率,计数器初值为:
计数器初值=921.6kHz/(16*1200)≈48
最后,将计数器初值设置到波特率发生器,即可达到1200波特率的
串口通信。

需要注意的是,以上计算是基于8位数据位、无校验位和1位停止位
的情况。

如果需要使用其他参数,则需要根据具体情况进行计算。

综上,通过以上计算可以得到51单片机串口的波特率。

根据不同的
时钟频率和波特率要求,可以使用相应的计数器初值来设置波特率发生器,实现串口通信。

51单片机的串口

51单片机的串口

发送
门电路
T线
发送控制器

同 步 串行口中断

≥1
TI RI

接收控制器
控 制 寄 存 器
(98H)
接收 SBUF
输入移位寄存器
RXD(P3.0)
(99H)
51单片机串行口结构框图
1. 51单片机串口结构
➢ 有两个物理上独立的接收、发送缓冲器SBUF(属于特殊功能 寄存器),可同时发送、接收数据。
2. 51单片机串口相关寄存器
① SM0 SM1 —— 串行口工作方式选择位
SM0 SM1 工作方式
00
0
01
1
10
2
11
3
功能说明 同步移位寄存器输入/输出,波特率固定为fosc/12 8位UART;波特率可变(TI溢出率/n,n=32或16) 9位UART,波特率固定为fosc/n,(n=64或32) 9位UART,波特率可变(T1溢出率/n,n=32或16)
2. 51单片机串口相关寄存器
(2)串行控制寄存器SCON
SCON 位名称 位地址
功能
D7 SM0 9FH
D6 SM1 9EH
工作方式选择
D5 SM2 9DH
D4
D3
D2
D1
D0
REN
TB8
RB8
TI
RI
9CH
9BH
9AH
99H
98H
多机通信控制 接收允许 发送第9位 接收第9位 发送中断 接收中断
2. 51单片机串口相关寄存器
③ REN —— 允许接收控制位。 REN位用于对串行数据的接收进行控制:REN=0,禁止接收;REN=1,允许接收。该位由软件置位 或复位。

51单片机串口通信相关寄存器及设置指引

51单片机串口通信相关寄存器及设置指引

51单片机串口通信相关寄存器及设置指引关键字SBUF:串口数据缓存寄存器SCON:串口通信状态控制寄存器Fosc:晶振的震荡频率PSW:程序状态字寄存器1、SBUF数据缓存寄存器SBUF可直接寻址专用寄存器,是个8位寄存器,不可进行位操作。

字节地址99H。

物理上它是两个寄存器,一个发送寄存器,一个接收寄存器。

写数据到SBUF中时(SBUF = 0x52;),单片机自己会判断是写到发送寄存器。

读取SBUF中数据时(rReg = SBUF;),单片机自己会判断是读取接收寄存器。

接收寄存器是双缓冲的,以避免在接收下一帧数据之前,单片机还来不及响应接收中断,没有把上一帧的数据读取走,而产生两次帧数据重叠问题。

发送寄存器,没有缓冲,发送时单片机直接主动发出数据,不会产生重叠问题。

(扩展知识:为了保持最大的传输速率,一般不需要发送寄存器建立双缓冲功能。

双缓冲功能有别于发送数据队列缓存区。

)2、SCON串口通讯状态控制寄存器SCON可直接寻址专用寄存器,是个8位寄存器,可以进行位操作。

SCON用于控制串行通信的模式选择、接收和发送,标识串口的状态。

SCON即可以字节寻址也可以位寻址,字节地址98H,地址位为98H~9FH。

系统复位时,SCON的所有位都被清除。

SCON串口通讯状态控制寄存器的格式及各位的功能定义如下:●SM0、SM1SM0和SM1是串口模式选择位。

SM0和SM1编码对应串口4种模式,如下表:●SM2SM2在模式2和模式3中是多机通信的使能位。

在模式0中,SM2必须为0。

在模式1中,若SM2=1且没有接收到有效的停止位,则接收中断标志位RI不会被激活。

在模式2和模式3中若SM2=1且接收到的第9位数据(RB8)为0,则接收中断标志RB8不会被激活,若接收到的第9位数据(RB8)为1,则RI置位。

此功能可用于多处理机通信。

●RENREN为允许串行接收位,由软件置位或清除。

置位时允许串行接收,清除时禁止串行接收。

51单片机的2个串口分别通信的方法

51单片机的2个串口分别通信的方法

51单片机的2个串口资源分别通信的方法当使用51单片机的2个串口资源进行通信时,比如用一个串口与PLC的串口使用RS485协议通信,一个串口通过蓝牙模块和另一个单片机无线通信时,该如何处理呢?传统的51单片机只有1个串口资源,只能采用分时复用的方法。

STC的15系列增强版51单片机具有多个串口资源,本文将描述如何使用IAP15W4K58S单片机用一个串口资源与PLC的RS485有线通信,另一个串口资源与Arduino单片机通过蓝牙模块无线通信,该通讯连接过程中PLC作为主机,IAP15W4K58S作为中间机,Arduino单片机作为最低层级。

工作过程是按下启动按键,PLC发信息给IAP15W4K58S单片机发高速脉冲控制步进电机驱动的机械臂运动取走货物,当货物取走后,IAP15W4K58S单片机通过蓝牙模块通知Arduino单片机控制的小车将新货物运送过来。

连接结构示意图如下图所示。

本例程使用的单片机型号为:IAP15W4K58S,该单片机有4个采用UART 工作方式的全双工异步串行通信接口(分别为串口1、串口2、串口3和串口4),每个串行口由2个数据缓冲器、1个移位寄存器、1个串行控制寄存器和1个波特率发生器等组成。

本项目使用串行口1和串行口2。

串行口1的两个缓冲器共用寄存器SBUF (99H),串行口2的两个缓冲器共用寄存器S2BUF(9BH)。

10位(1起始位,8位数据位,1停止位)可变波特率(9600)。

串口1对应的硬件部分是TxD和RxD,串行口2对应硬件部分是TxD2和RxD2。

串口1选择引脚P3.0(RxD)和P3.1(TxD),串口2选择引脚P1.0(RxD)和P1.1(TxD)。

串口1既可以选择T1作为波特率发生器,也可以选择T2作为波特率发生器。

本文串口1提供2个选择(T1和T2),串口2只能选择T2作波特率发生器。

但是当串口1和串口2的波特率相同时,可以共用T2作为波特率发器,当T2工作在1T模式时,串行口1的波特率=SYSclk/(65536-[RL_TH2,RL_TL2])/4,SYSclk表示系统时钟频率,[RL_TH2,RL_TL2]表示T2H,T2L的定时初值设置值。

c 51单片机串口初值计算

c 51单片机串口初值计算

c 51单片机串口初值计算
在C51单片机中,串口通信是一种常用的通信方式。

为了实现串口通信,我们需要对串口的波特率、停止位、数据位、校验位等进行配置。

其中,波特率是串口通信中最重要的参数之一,它决定了数据传输的速度。

在C51单片机中,我们通常使用定时器来产生串口的波特率。

具体来说,我们可以通过配置定时器的溢出值和分频系数来计算波特率。

假设我们要配置的波特率为9600,单片机的晶振频率为12MHz,那么我们可以使用定时器T1来产生波特率。

首先,我们需要将定时器T1设置为工作方式2,即自动重装载模式。

然后,我们可以根据下面的公式计算波特率的初值:
波特率= (2^SMOD / (32 * (65536 - TH1))) * 12
其中,SMOD是波特率倍增位,TH1是定时器T1的初值。

根据上面的公式,我们可以计算出TH1的值为:
TH1 = 65536 - (2^SMOD * 12 / (32 * 波特率))
假设SMOD=0,那么我们可以将上面的公式代入计算出TH1的值为:
TH1 = 65536 - (2^0 * 12 / (32 * 9600)) = 0x4B88
因此,我们可以将TH1的值写入单片机的寄存器中,以配置串口的波特率。

除了配置波特率外,我们还需要配置串口的其他参数,例如停止位、数据位、校验位等。

这些参数可以通过对串口控制寄存器的相应位进行设置来配置。

具体配置方法可以参考单片机的数据手册或参考手册。

单片机串口通信的发送与接收

单片机串口通信的发送与接收

51单片机的串口,是个全双工的串口,发送数据的同时,还可以接收数据。

当串行发送完毕后,将在标志位TI 置1,同样,当收到了数据后,也会在RI 置1。

无论RI 或TI 出现了1,只要串口中断处于开放状态,单片机都会进入串口中断处理程序。

在中断程序中,要区分出来究竟是发送引起的中断,还是接收引起的中断,然后分别进行处理。

看到过一些书籍和文章,在串口收、发数据的处理方法上,很多人都有不妥之处。

接收数据时,基本上都是使用“中断方式”,这是正确合理的。

即:每当收到一个新数据,就在中断函数中,把RI 清零,并用一个变量,通知主函数,收到了新数据。

发送数据时,很多的程序都是使用的“查询方式”,就是执行while(TI ==0); 这样的语句来等待发送完毕。

这时,处理不好的话,就可能带来问题。

看了一些网友编写的程序,发现有如下几条容易出错:1.有人在发送数据之前,先关闭了串口中断!等待发送完毕后,再打开串口中断。

这样,在发送数据的等待期间内,如果收到了数据,将不能进入中断函数,也就不会保存的这个新收到的数据。

这种处理方法,就会遗漏收到的数据。

2.有人在发送数据之前,并没有关闭串口中断,当TI = 1 时,是可以进入中断程序的。

但是,却在中断函数中,将TI 清零!这样,在主函数中的while(TI ==0);,将永远等不到发送结束的标志。

3.还有人在中断程序中,并没有区分中断的来源,反而让发送引起的中断,执行了接收中断的程序。

对此,做而论道发表自己常用的方法:接收数据时,使用“中断方式”,清除RI 后,用一个变量通知主函数,收到新数据。

发送数据时,也用“中断方式”,清除TI 后,用另一个变量通知主函数,数据发送完毕。

这样一来,收、发两者基本一致,编写程序也很规范、易懂。

更重要的是,主函数中,不用在那儿死等发送完毕,可以有更多的时间查看其它的标志。

实例:求一个PC与单片机串口通信的程序,要求如下:1、如果在电脑上发送以$开始的字符串,则将整个字符串原样返回(字符串长度不是固定的)。

MCS-51单片机的串行口及串行通信技术

MCS-51单片机的串行口及串行通信技术

MCS-51单⽚机的串⾏⼝及串⾏通信技术数据通信的基本概念串⾏通信有单⼯通信、半双⼯通信和全双⼯通信3种⽅式。

单⼯通信:数据只能单⽅向地从⼀端向另⼀端传送。

例如,⽬前的有线电视节⽬,只能单⽅向传送。

半双⼯通信:数据可以双向传送,但任⼀时刻只能向⼀个⽅向传送。

也就是说,半双⼯通信可以分时双向传送数据。

例如,⽬前的某些对讲机,任⼀时刻只能⼀⽅讲,另⼀⽅听。

全双⼯通信:数据可同时向两个⽅向传送。

全双⼯通信效率最⾼,适⽤于计算机之间的通信。

此外,通信双⽅要正确地进⾏数据传输,需要解决何时开始传输,何时结束传输,以及数据传输速率等问题,即解决数据同步问题。

实现数据同步,通常有两种⽅式,⼀种是异步通信,另⼀种是同步通信。

异步通信在异步通信中,数据⼀帧⼀帧地传送。

每⼀帧由⼀个字符代码组成,⼀个字符代码由起始位、数据位、奇偶校验位和停⽌位4部分组成。

每⼀帧的数据格式如图7-1所⽰。

⼀个串⾏帧的开始是⼀个起始位“0”,然后是5〜8位数据(规定低位数据在前,⾼位数据在后),接着是奇偶校验位(此位可省略),最后是停⽌位“1”。

起始位起始位"0”占⽤⼀位,⽤来通知接收设备,开始接收字符。

通信线在不传送字符时,⼀直保持为“1”。

接收端不断检测线路状态,当测到⼀个“0”电平时,就知道发来⼀个新字符,马上进⾏接收。

起始位还被⽤作同步接收端的时钟,以保证以后的接收能正确进⾏。

数据位数据位是要传送的数据,可以是5位、6位或更多。

当数据位是5位时,数据位为D0〜D4;当数据位是6位时,数据位为D0〜D5;当数据位是8位时,数据位为D0〜D7。

奇偶校验位奇偶校验位只占⼀位,其数据位为D8。

当传送数据不进⾏奇偶校验时,可以省略此位。

此位也可⽤于确定该帧字符所代表的信息类型,“1"表明传送的是地址帧,“0”表明传送的是数据帧。

停⽌位停⽌位⽤来表⽰字符的结束,停⽌位可以是1位、1.5位或2位。

停⽌位必须是⾼电平。

接收端接收到停⽌位后,就知道此字符传送完毕。

51单片机与PC机通信

51单片机与PC机通信

51单片机与PC机通信随着嵌入式系统和物联网技术的发展,51单片机在许多应用中扮演着重要的角色。

这些单片机具有低功耗、高性能和易于编程等优点,使其在各种嵌入式设备中得到广泛应用。

在这些应用中,与PC机的通信是一个关键的需求。

本文将探讨51单片机与PC机通信的方法和协议。

串口通信是51单片机与PC机进行通信的最常用方式之一。

串口通信使用一个或多个串行数据线来传输数据,通常使用RS232或TTL电平标准。

在硬件连接方面,需要将51单片机的串口与PC机的串口进行连接。

通常使用DB9或USB转TTL电路来实现这一连接。

在软件编程方面,需要使用51单片机的UART控制器来进行数据的发送和接收。

具体实现可以使用Keil C51或IAR Embedded Workbench 等集成开发环境进行编程。

USB通信是一种比较新的通信方式,它具有传输速度快、支持热插拔等优点。

在51单片机中,可以使用USB接口芯片来实现与PC机的通信。

在硬件连接方面,需要将51单片机的USB接口芯片与PC机的USB接口进行连接。

通常使用CH340G或FT232等USB转串口芯片来实现这一连接。

在软件编程方面,需要使用51单片机的USB接口芯片来进行数据的发送和接收。

具体实现可以使用相应的USB库来进行编程。

网络通信是一种更加灵活和高效的通信方式。

在51单片机中,可以使用以太网控制器来实现与PC机的网络通信。

在硬件连接方面,需要将51单片机的以太网控制器与PC机的网络接口进行连接。

通常使用ENC28J60等以太网控制器来实现这一连接。

在软件编程方面,需要使用51单片机的以太网控制器来进行数据的发送和接收。

具体实现可以使用相应的网络库来进行编程。

需要注意的是,网络编程涉及到更多的协议和数据格式,需要有一定的网络基础知识。

本文介绍了51单片机与PC机通信的三种常用方式:串口通信、USB 通信和网络通信。

每种方式都有其各自的优缺点和适用场景。

51单片机串口校验设置

51单片机串口校验设置

51单片机串行通信奇偶校验的设置方法通常,串行通信的一帧的格式是8-n-1,即8位数据、无校验、1个停止位。

有时为了提高准确度,需要增加一个“奇”校验位或者“偶”校验位。

对于高级语言的做法是很简单的,只要把格式命令“8-n-1”,改为“8-P-1”或“8-O-1”即可。

串行口在带有校验位的通信方式中,是先发送8位数据,然后再发送校验位。

51单片机也可以按照带有校验位的方式进行串行通信,这在51单片机中称为9位数据方式。

51单片机中有两个位,分别称为TB8和RB8,它们在“无校验”的时候,并没有用处。

当51单片机用9位数据方式进行串行通信的时候,TB8和RB8的作用如下:51单片机在发送的时候,先发送8位数据,然后发送TB8中的内容;51单片机在接收的时候,先接收8位数据,然后接收校验位,存到RB8中。

编写51单片机程序的时候,应该在发送数据之前,在TB8中,写好待发送的校验位。

8位数据的校验位,可以利用单片机中奇偶标志位P来自动生成,程序如下。

MOV A, #待发数据;数据进了A,即刻生成奇偶标志位PMOV C, PMOV TB8, C ;校验位送到TB8MOV SBUF, A ;发送数据,以及P由于P = 1则说明A中有奇数个1,所以上述程序是“偶”校验的形式。

如果要求的是“奇”校验,则需要增加一条取反指令,如下:MOV C, PCPL CMOV TB8, C ;校验位送到TB8接收方会把收到的8位数送到SBUF,第9位数,送到RB8,然后自动设立RI = 1。

之后,就可以用RB8中的内容,对刚才收到的8位数进行正确性检验。

另一个问题:51单片机如何初始化成8-n-1(8数据位,无奇偶校验位,1停止位)波特率,是用串口的模式几?本来想用串口的模式1,可是仔细一看,模式1是10异步通信方式,1起始位,8数据位,1停止位?悬赏分:20 - 解决时间:2009-12-1 13:26问题补充:首先感谢一楼的回答。

51单片机串口通信及波特率设置

51单片机串口通信及波特率设置

51单片机串口通信及波特率设置MCS-51单片机具有一个全双工的串行通信接口,能同时进行发送和接收。

它可以作为UART(通用异步接收和发送器)使用,也可以作为同步的移位寄存器使用。

1. 数据缓冲寄存器SBUFSBUF是可以直接寻址的专用寄存器。

物理上,它对应着两个寄存器,即一个发送寄存器一个接收寄存器,CPU写SBUF就是修改发送寄存器;读SBUF就是读接收寄存器。

接收器是双缓冲的,以避免在接收下一帧数据之前,CPU未能及时的响应接收器的中断,没有把上一帧的数据读走而产生两帧数据重叠的问题。

对于发送器,为了保持最大的传输速率,一般不需要双缓冲,因为发送时CPU是主动的,不会产生重叠问题。

2. 状态控制寄存器SCONSCON是一个逐位定义的8位寄存器,用于控制串行通信的方式选择、接收和发送,指示串口的状态,SCON即可以字节寻址也可以位寻址,字节地址98H,地址位为98H~9FH。

它的各个位定义如下:MSB LSBSM0 SM1 SM2 REN TB8 RB8 TI RI SM0和SM1是串口的工作方式选择位,2个选择位对应4种工作方式,如下表,其中Fosc是振荡器的频率。

SM0 SM1 工作方式功能波特率0 0 0 8位同步移位寄存器Fosc/120 1 1 10位UART 可变1 02 11位UART Fosc/64或Fosc/321 1 3 11位UART 可变SM2在工作方式2和3中是多机通信的使能位。

在工作方式0中,SM2必须为0。

在工作方式1中,若SM2=1且没有接收到有效的停止位,则接收中断标志位RI不会被激活。

在工作方式2和3中若SM2=1且接收到的第9位数据(RB8)为0,则接收中断标志RB8不会被激活,若接收到的第9位数据(RB8)为1,则RI置位。

此功能可用于多处理机通信。

REN为允许串行接收位,由软件置位或清除。

置位时允许串行接收,清除时禁止串行接收。

TB8是工作方式2和3要发送的第9位数据。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

1.1 串口发数1.1.1串口发数的原理在模拟外部晶振为11.0592 MHz、波特率为9 600 bps的情况下,设置常量BAUD为0xFE80,并将该常量赋值到TL0、TH0两个寄存器中,实现定时。

每到相应时间触发定时中断程序,将外部引脚的状态读入并存入预先设定的数组中,完成模拟串口读入字节的任务。

常用的波特率配置如图 1.1-1所示。

由于STC15L104E没有串口,因而必须利用定时器模拟串口。

其方法是,定义一个常量,根据所需要的波特率对该常量赋值,并将该常量值赋到定时所用的寄存器中。

图1.1-1 常用波特率配置对于BAUD的具体算法是BAUD=65536-SYSclk/3/BAUDRATE/M(1T:M=1;12T:M=12)。

65536是定时器T0的溢出值,因为T0定时器为16位定时器,所以溢出值为2^16,SYSclk为系统时钟频率11.0592MHZ,BAUDRATE为波特率9600bps,而我们使用的是单周期M=1,所以我们要像定时器里存入0xfe80。

对于BAUD的算法,上一节讲到定时器中断的原理,定时器计时65536位的时候就会溢出,然后进入中断。

而我们要模拟的串口波特率为9600bps,我们想要每一位执行的时间T1就是1/9600s,而系统晶振震荡一次读一位的时间T2为1/11.0592us(单周期),那么我们要读的位数就为T1/T2。

那算法公式中的3是什么呢,这是因为我们每读一位要抽样三次来检查读取的数据。

我们要计数SYSclk/3/BAUDRATE/M位的时候产生中断,就要用65536-SYSclk/3/BAUDRATE/M,赋值给定时器,定时器定期检查串口,实现串口模拟。

本实验中我们用到的寄存器有AUXR、TMOD、TCON、IE、IP,前两节都已经详细介绍,本节不做深入讲解。

1.1.2硬件连接模拟串口的硬件连接须将单片机两个引脚分别定义为收数据发数据,在这里我们定义P3.1为发送数据,P3.0为接收数据。

原理图如图 1.1-2所示。

图1.1-2 模拟串口的硬件连接1.1.3原工程详解打开串口发数的程序,分析一下程序。

a.首先是头文件,宏定义BAUD为0xfe80(算法1.1.1中已介绍,在这里不详细说明)。

宏定义#define是给原内容起个新名字,方便后面直接写新名字,用法是#define 新名字原内容,注意没有分号。

#define BAUD 0xFE80的意义就是用BAUD代替0xfe80。

定义AUXR寄存器,定义接收串口(P3^0)和发送串口(P3^1)。

声明类型typedef,typedef是只将已有的类型换个别的名字,typedef bit BOOL;的意思就是将bit换成BOOL的名字,下面两句同样道理。

定义模拟串口的标志,其中TBUF/RBUF为存放数据的缓存区,TDAT/RDAT 为要传送的数据,TCNT/RCNT为抽样计数器,TBIT/RBIT为字节的位数,TING/RING为起始标志位,TEND/REND为结束标志位。

接着声明了4个子函数,分别是串口初始化函数、延时函数、发送字节函数和发送字符串子函数。

声明子函数的写法在前面的章节都介绍过,此处不介绍。

/*声明*/#include "reg51.h"#define BAUD 0xFE80sfr AUXR = 0x8E;sbit RXB = P3^0; //定义UART TX/RXsbit TXB = P3^1;typedef bit BOOL;typedef unsigned char BYTE;typedef unsigned int WORD;BYTE TBUF,RBUF; //模拟串口的状态标志BYTE TDAT,RDAT;BYTE TCNT,RCNT;BYTE TBIT,RBIT;BOOL TING,RING; //起始标志位BOOL TEND,REND; //结束标志位void UART_INIT();void Delay_mS(unsigned int time);void UART_SendByte(unsigned char date);void UART_SendString(unsigned char* Data,unsigned int len);注意*Data是一个指针,也是一个数组,数组就是指针,也可写成Data[]。

b.接下来分析四个子函数。

void Delay_mS(unsigned int time) //延时time mS的延时程序,最大可以延时65535毫秒{unsigned int i; //定义一个名字是“i”的无符号int型变量while(time) //等到毫秒数减到0{for(i=0;i<142;i++);//延时1mStime --; // 等效于time=time-1;}}延时子函数,这个子函数无返回值,参数是无符号整形的time。

进入子函数声明变量i,进入while循环执行for循环直到time为0,for循环内的延时时间相当于1ms。

For循环就是for(条件1; 条件2; 条件3),条件1为起始,看条件1是否符合条件2,符合执行for{}中的语句,执行结束后执行条件3,再看执行条件3后的条件是否符合条件2,符合继续执行语句,以此类推直到不符合条件2跳出循环。

所以这个子函数每进入while一次就执行for循环一次(跑142个数),这个for语句没有{},说明它起的是一个延时作用,延时1ms后time 就减1一次,直到time减到0跳出while循环,最后我们延时的数是142*time 次,完成了延时。

/*发送字符子函数*/void UART_SendByte(unsigned char date) //发送字符{if (TEND) // 等待数据的传送{TEND = 0;TBUF =date;TING = 1;}Delay_mS(100);}发送字节子函数,等待数据的传送if (TEND),TEND=1执行内部语句,将TEND重新赋值0,把要发送的数据date(参数)给TBUF,后面的中断模拟串口可知发数是通过TBUF发出去的,所以要将data给TBUF。

将发送起始位TING赋值1,跳出if语句。

调用延时子函数延时100ms。

我们赋的初值TEND=1,所以在主函数中调用此函数时,这个函数里的语句都直接执行。

这个发送字节函数的作用是每执行一次就发送一个字节(8位)。

/*发送字符串*/void UART_SendString(unsigned char* Data,unsigned int len) //发送句子{unsigned int i=0;for(;i<len;i++)UART_SendByte(Data[i]);Delay_mS(50);}发送字符串子函数,这个子函数和上面的不同是因为它有两个参数,用“,”隔开。

进入子函数声明i并赋初值0,然后执行for循环,for循环里的条件1没有就是默认i=0,for循环里套着发送字节子函数,直到发送完len的长度的字节跳出for循环,其中len的长度为字符串的总长度(在主函数内实现),每发送一个字节都要延时50ms。

这个子函数的作用是发送一个字符串的。

/*模拟串口初始化*/void UART_INIT(){TMOD = 0x00;AUXR = 0x80; //timer0 工作在1T 模式(185) 不分频TL0 = BAUD;TH0 = BAUD>>8; //timer0 预装载值TR0 = 1; //tiemr0 开启ET0 = 1; //开启timer0 中断PT0 = 1; //提升timer0 中断优先级EA = 1; //开总中断TING = 0; //状态标志位赋初值RING = 0;TEND = 1;REND = 0;TCNT = 0;RCNT = 0;}模拟串口初始化子函数。

将TMOD赋值0x00,说明T0工作在16位自动重装模式。

AUXR寄存器赋值0x80,说明T0为单周期不分频(1T模式)。

给定时器0赋初值,将BAUD的高8位赋给TH0(BAUD>>8将BAUD右移8位,BAUD就由0xfe80变成0x80),低8位赋给TL0(直接赋值),说明定时器定时BAUD个位时就产生中断。

ET0=1开启定时器0中断,PT0提升T0的中断优先级,EA开启总中断。

将模拟串口状态标志位中的TEND发送结束位赋值1,其他赋值0。

这些都并不陌生了,不细讲解。

c.接着我们分析中断程序,它是模拟串口的中心程序。

void tm0() interrupt 1 using 1 //time0中断查询来模拟串口{if (RING) //开始接收{if (--RCNT == 0){RCNT = 3; // 重置发送波特率计数器if (--RBIT == 0){RBUF = RDAT; //数据保存到RBUFRING = 0; //停止接收REND = 1; //设置接收完成标志}else{RDAT >>= 1;if (RXB)RDAT |= 0x80; //shift RX data to RX buffer}}}else if (!RXB){RING = 1; //启动标志位RCNT = 4; // 初始接收波特率计数器RBIT = 9; //初始接收比特数(8位加一位停止位)}先看中断中的接收程序,RING初始为0,所以直接进入else if (!RXB)。

由串口协议知当串口有数据接收时起始位为低电平,接收结束后结束为为高电平。

所以如果有数据接收(RXB=0)进入else if语句中,RING=1启动标志位,RCNT=4初始化波特率计数器,RBIT=9初始比特数。

这是第一次对接收数据抽样,此时是对数据第一位之前的一位起始位进行抽样(起始位为低电平)。

第二次进入中断时RING==1进入if (RING),--RCNT==3不执行下面语句,此时是对起始位第二次抽样。

第三次进入中断--RCNT==2,不执行下面语句,此时是对起始位第三次抽样,此时抽样的位置为一个周期(即一个波特率的周期频率),这也是为什么我们在计算溢出时要除以的那个“3”的原因。

第4次进入中断--RCNT==1,不执行下面语句,此时是数据位第一位的1/3处抽样。

第5次进入中断--RCNT==0(在数据位第一位的2/3处抽样),将RCNT重新赋值3,执行else语句(--RBIT==8不为0),RDAT初始为0,右移一位还为0(RDAT >>= 1;),读取接收位,若接收位为0,则RDAT数据为不变为0,若接收位为1,那么将RDAT最高位置1。

相关文档
最新文档