串口通信
并行通信方式
并行通信通常是将数据字节的各位用多条数据线同时进行传送,每一位数据都需要一根传输线这种通信方式仅仅是适合于短距离的数据传输,,并行通信控制简单,相对传送的速度相对较快,但是由于传输线比较多,长距离传送时成本高收发的各位同时接收存在困难
串行通信方式:
串行通信是将数据字节分成一位一位在一条传输线上进行传送,此时只需要一条数据线,外加一条公共信号地线和若干条控制线,因为一次传递一位,所以一个字节的数据要分成8位才能传送完毕,因此发送时必须要把并行数据转换成串行数据,接收之后再把串行数据转换成并行数据,供计算机使用
串行通信分为两种方式:异步通信和同步通信
异步通信是指通信的发送与接收设备使用各自的时钟控制数据的发送和接收过程,为了使双方的收发协调,要求发送和接收设备的时钟尽可能的一致
基本上是一个机器周期发送一个~~
异步通信一帧的字符信息,字符与字符之间的间隙是任意的,但是字符中的位与位之间的间隙是固定的
异步通信的数据格式:起始位,表示下一位是数据位,一低电平开始
数据位,数据位的最低有效位开始发送
校验位:根据校验位验证是否发错
停止位:以高电平结束,一个位宽的高电平
同步通信,同步通信要求建立收发的时钟对接收时钟的直接控制,使双方达到完全同步,维持传输数据之间的距离必须是位间隔的整数倍,同时传送的之间不留间隙,既保持位同步关系,也保持字符同步关系,一般通过外同步和内同步实现;同步通信用的非常少
串行通信的传输方向
单工:是指数据传输只能沿一个方向,不能反向传输
半双工:半双工是指数据传输可以沿着两个方向,但需要分时的进行
全双工:全双工是指数据可以同时进行双向传输;
调制解调器:利用调制器可以吧数字信号转换成模拟信号,然后通过传送到通信的新路上去,再由解调器把通信线路上收到的模拟信号转换成数字信号,由于通信是双向的,因此,调制器和解调器合并在一个装置中,这就是调制解调器
串行通信的错误校验:
奇偶校验:奇校验:数据中的1的个数应该与校验位1的个数之和为奇数,
偶校验的时候,数据中的1的个数应该与校验位的1 的个数之和为偶数
代码和校验:代码和校验是指发送方将数据块求和(或者是各个字节异或),接收方收到数据也将数据块进行求和(或者各个字节异或)两者进行比较
循环冗余校验:这种校验是通过某种数学校验实现有效信息与校验位之间得到循环校验,常常用于对磁盘信息的传输,存储区的完整性校验,这种校验的纠错能力较强,广泛应用于同步通信中
传输速率:比特率:每秒传输二进制代码的位数,单位是位每秒
RS-232c接口,九个接口,由于总线的标准受到电容允许值的约束,使用时传输距离一般不要超过十五米,最高的传输速率为20kbps
max232电平转换(还有max485)max485比较厉害
80c51控制串行口的控制寄存器:SCON
串行口用的最多的是方式1,很少用方式2和3的
这里我们先学会方式1
REN为允许串行接收位,TI发送中断标志位,在方式一中,串行发送停止位开始时,由内部硬件使TI置1,向cpu发中断请求,在中断服务程序中,必须使用软件将其清0,取消此中断申请
RI接收中断标志位:这两位只能够又硬件将其置1
PCON中只有一位SMOD与串行工作有关:SMOD,波特率倍增位,在串行口方式1,2,3,时,波特率与SMOD有关,当SMOD等于1时,波特率提高一倍,复位时,SMOD = 0;
方式1
方式1是10位数据的异步通信,TXD为数据发送引脚,XD为数据接收引脚,每一帧的数据格式是1位起始位,8位数据位,1位停止位
波特率的计算:
在串行通信中,收发双方对发送或接收数据的速率要有约定,通过软件可对单片机串行口编程为四种工作方式,其中,方式0和方式2的波特率是固定的,而方式1和方式3的波特率是可变的,由T1的溢出率来决定
串行口的四种工作方式对应三种波特率,由于输入的因为时钟的来源不同,所以,各种方式的波特率计算公式也不同
方式0的波特率=fosc/12;
方式2的波特率=(2^SMOD)/64)*fosc
方式1的波特率=(2^SMOD)/32)*(T1的溢出率)
方式3的波特率=(2^SMOD)/32)*(T1的溢出率)
T1的溢出率:当T1为波特率发生器时,最典型的用法是使T1工作在自动重装的8位定时器方式(即方式2,且TCON的TR1= 1,以启动定时器)这是溢出率取决于TH1的计数值
T1的溢出率= fosc/{12*[256-(TH1)]}
串行口工作之前,应对其进行初始化,主要是设置产生波特率的定时器1,串行口控制和中断控制,具体步骤如下:
1确定T1的工作方式,(编程TMOD寄存器)
2计算T1的初值,转载TH1,TL1
3启动T1(编程TCON中的TR1位)
4确定串行口控制(编程SCON寄存器)
串行口在中断方式工作时,要进行中断设置(编程IE,IP寄存器)
#include<reg52.h> #define uchar unsigned char #define uint unsigned int uchar flag,a,i; uchar code table[]="I get"; void init() { TMOD = 0x20;//设定定时器T1为工作方式2 TH1 = 0xfd;//T1装入初值 TL1 = 0xfd;//T1装入初值 TR1 = 1;//启动定时器 REN = 1;//允许串口接收 SM0 = 1;//设定串口工作方式为1 SM1 = 1;//设定串口工作方式为1 EA = 1;//开总中断 ES = 1;//开串口中断 //这里我们没有看到开定时器1 的中断 ,因为定时器1工作在方式2的时候为 //八位自动重装方式,我们进入定时器中断后无事可做,因此无需打开定时器1中断 } void main() { init(); while(1) { if(flag==1)//始终检测标志位flag是否为1 { ES = 0;//关闭串口中断,原因是接下来要发送数据,若不关闭串口中断 //当发送数据后,单片机同样会申请串口中断,便再次进入了中断服务程序,flag又被置位为1 //此时主程序又会再次发送数据,如此重复下去,程序变成了死循环 for(i=0;i<6;i++)//发送六位数据 { SBUF = table[i]; while(!TI);//等待是否发送完毕,因为发送完毕的时候,TI才会由硬件置1 TI = 0;//手动将TI置0 } SBUF = a;//程序执行到这条语句的时候,便自动开始将寄存器中的数据一位一位的从 //串口发送出去 while(!TI); TI = 0; ES = 1; flag = 0; } } } void ser()interrupt 4 { RI = 0;//RI清0,因为程序既然产生了串口中断,那么肯定是收到或者是发送了数据,在开始时候 //没有发送任何数据,那必然是收到了数据,此时RI会被硬件置1,进入串口中断服务程序 //必须由软件清零,才能产生下一次的中断, a = SBUF;//将sbuf中的数据读走这才是进入中断的目的 flag = 1;//标志位置1,方便主程序中查询判断是否已经收到数据 }
版权所有转载请注明链接地址:http://www.cnblogs.com/fengdashen/p/3333940.html