电平标准是数据1和数据0的表达方式,是传输线缆中人为规定的电压与数据的对应关系,串口常用的电平标准有如下三种:
· 电平标准是数据1和数据O的表达方式,是传输线缆中人为规定的电
压与数据的对应关系,串口常用的电平标准有如下三种:
· TTL电平:+5V表示1,0V表示0
· RS232电平 :- 3 ~- 15V表示1,+3~+15V表示0
· RS485电平:两线压差+2~+6V表示1,-2 ~- 6V表示0(差分信号)
·全双工:通信双方可以在同一时刻互相传输数据
·半双工:通信双方可以互相传输数据,但必须分时复用一根数据线(在同一时刻只能单向传输)
·单工:通信只能有一方发送到另一方,不能反向传输
·异步:通信双方各自约定通信速率(没有时钟线)
·同步:通信双方靠一根时钟线来约定通信速率
·总线:连接各个设备的数据传输线路(类似于一条马路,把路边各住户连接起来,使住户可以相互交流)
· 波特率:串口通信的速率(发送和接收各数据位的间隔时间)
· 检验位:用于数据验证
· 停止位:用于数据帧间隔
SBUF: 串口数据缓存寄存器,物理上是两个独立的寄存器,但占用相同的地址。写操作时,写入的是发送寄存器,读操作时,读出的是接收寄存器
当要发送数据时,数据从总线传输到SBUF,通过控制门传输到TXD,将数据发送出去,控制门是一些控制逻辑电路,不用关心,发送数据由发送控制器来进行控制。接收数据时,数据从RXD接收到,通过接收控制器将数据送到移位寄存器,再送到SBUF。接收数据是由中断来进行的,数据传输速率由中间的逻辑电路(定时器1)来控制(波特率)
(1)SCON
该单片机使用模式一,8位UART
SMO/FE用于帧错误检测,8为UART不需要,所以SMO/FE=0
SM0=0,SM1=1
因为只有方式1,所以SM2不用管,配为0
REN:允许/禁止串行接收控制位。由软件置位REN,即REN=1为允许串行接收状态,可启动串行接收器RxD,开始接收信息。软件复位REN,即REN=0,则禁止接收。此时不需要,先给0
TB8:在方式2或方式3,它为要发送的第9位数据,按需要由软件置位或清0。
RB8:在方式2或方式3,是接收到的第9位数据。
方式1不需要,所以TB8=0,RB8=0
TI:发送中断请求标志位。在方式0,当串行发送数据第8位结束时,由内部硬件自动置位,即TI=1,向主机请求中断,响应中断后必须用软件复位,即TI=0。在其他方式中,则在停止位开始发送时由内部硬件置位,必须用软件复位。
RI:接收中断请求标志位。在方式0,当串行接收到第8位结束时由内部硬件自动置位RI=1,向主机请求中断,响应中断后必须用软件复位,即RI=0。在其他方式中,串行接收到停止位的中间时刻由内部硬件置位,即RI=1(例外情况见SM2说明),必须由软件复位,即RI=0。
初始化配置TI=0,RI=0
综上SCON=0x40;
(2)SBUF
SBUF为接收发送寄存器,初始化不需要配置
(3)PCON
(4)IE,IPH,IP,SADEN,SADDR都不需要配置
定时器初值与波特率有关,可以用STC-ISP软件生成波特率,完成串口的配置
本单片机是11.0592MHz的频率,没有误差,所以在直接就用9600波特率,不需要波特率倍速来减小误差
SCON先改为0x40
STC89C52没有AUXR这个寄存器,直接将那两行删除就行
定时器1只用作波特率发生器,不需要其产生中断,故与中断相关的配置就不需要了
main.c
#include
#include "Delay.h"
#include "UART.h"
unsigned char Sec;
void main()
{
UART_Init(); //串口初始化
while(1)
{
UART_SendByte(Sec); //串口发送一个字节
Sec++; //Sec自增
Delay(1000); //延时1秒
}
}
UART.c
#include
/**
* @brief 串口初始化,[email protected]
* @param 无
* @retval 无
*/
void UART_Init()
{
SCON=0x40;
PCON &=0x7F;
TMOD &= 0x0F; //设置定时器模式
TMOD |= 0x20; //设置定时器模式
TL1 = 0xFD; //设定定时初值
TH1 = 0xFD; //设定定时器重装值
ET1 = 0; //禁止定时器1中断
TR1 = 1; //启动定时器1
}
/**
* @brief 串口发送一个字节数据
* @param Byte 要发送的一个字节数据
* @retval 无
*/
void UART_SendByte(unsigned char Byte)
{
SBUF=Byte;
while(TI==0);
TI=0;
}
UART.h
#ifndef __UART_H__
#define __UART_H__
void UART_Init();
void UART_SendByte(unsigned char Byte);
#endif
该实验需要接收数据,故SCON的REN位为1,SCON改为0x50
接收数据需要中断才能进行,所以需要中断使能(这个中断是串口中断,不是定时器1中断)
UART.c
#include
/**
* @brief 串口初始化,[email protected]
* @param 无
* @retval 无
*/
void UART_Init()
{
SCON=0x50;
PCON |= 0x7F;
TMOD &= 0x0F; //设置定时器模式
TMOD |= 0x20; //设置定时器模式
TL1 = 0xFD; //设定定时初值
TH1 = 0xFD; //设定定时器重装值
ET1 = 0; //禁止定时器1中断
TR1 = 1; //启动定时器1
EA=1;
ES=1;
}
/**
* @brief 串口发送一个字节数据
* @param Byte 要发送的一个字节数据
* @retval 无
*/
void UART_SendByte(unsigned char Byte)
{
SBUF=Byte;
while(TI==0);
TI=0;
}
/*串口中断函数模板
void UART_Routine() interrupt 4
{
if(RI==1)
{
RI=0;
}
}
*/
main.c
#include
#include "Delay.h"
#include "UART.h"
void main()
{
UART_Init(); //串口初始化
while(1)
{
}
}
void UART_Routine() interrupt 4
{
if(RI==1) //如果接收标志位为1,接收到了数据
{
P2=~SBUF; //读取数据,取反后输出到LED
UART_SendByte(SBUF); //将受到的数据发回串口
RI=0; //接收标志位清0
}
}
补充:数据显示模式
·HEX模式/十六进制模式/二进制模式:以原始数据的形式显示
·文本模式/字符模式:以原始数据编码(ASCII码)后的形式显示
例如,发送数据为HEX模式,接收数据为文本模式,发送数据30则接收到0,因为数字0对应的ASCII码为0x30
发送数据为文本模式,接收数据为HEX模式,发送数据A则接收到41,因为A对应的ASCII码为0x41