简介
- 设备间接线通信的一种方式
- 数据一位一位地顺序传送
- 双向通信,全双工
- 全双工:A向B发消息时,B也可以向A发消息
- 半双工:A向B发消息时,B不可以向A发消息,只有当A发完时,B才可以向A发消息
- 传送速度较慢
常用串口的电器标准协议
RS-232(标准串口,9针,20kb/s,点对点,全双工,15m)、RS-422(一对多,比232更强,10Mb/s)和RS-485(比422更强)
串口的电平
UART:异步串行,通用异步接受/发送。UART包含TTL电平的串口和RS232电平的串口
- RS-232电平:逻辑1:
-3~-15V
电压;逻辑0:3~15V
电压 - TTL电平:0V = 0, +5V=1
- 输入高电平>=2.4V,输出低电平<=0.4V;
- 输入高电平>=2.0V,输入低电平 <= 0.8V;
串口通信
串口接线方式
- RXD:数据输入引脚,数据接受;STC89系列对应P3.0口
- TXD:数据发送引脚,数据发送;STC89系列对应P3.1口
- 接线方式:交叉接线
串口编程要素
- 输入/输出数据缓冲器都叫做SBUF,都使用99H地址码,但是是两个独立的8位寄存器
- 代码体现为:接收数据:char data = SBUF,发送数据SBUF = data
- UART是异步串行接口,通信双方使用时钟不同,因为霜分硬件配置不同,但是需要约定通信速度,也就是波特率。
- 对于电脑,使用现成的软件即可,但对于单片机的波特率配置,需要自己写
串口编程
波特率初始化一
- 设置串口的工作方式
- 设置波特率是否加倍
- 设置定时器的模式
- 根据波特率,设置定时器常数TH和TL
- 启动定时器
void UartInit(void) //9600bps@11.0592MHz
{
//AUXR避免辐射
AUXR = 0x01;
//设置串行口的工作方式
SCON = 0x40;
//设置波特率不加倍
PCON = 0x10;
//设置定时器模式,8位自动重装
TMOD &= 0x0F;
TMOD |= 0x20;
//设置定时器常数
TH1 = 0xFD;
TL1 = 0xFD;
//启动定时器
TR1 = 1;
}
判断数据是否发送完毕
根据串行口控制寄存器SCON中B1下的TI
意思就是当串行发送数据结束时,TI=1,会先主机请求中断。
串口发送字符串
#include "reg52.h"
#include <intrins.h>
sfr AUXR = 0x8E;
void Delay1000ms() //@11.0592MHz
{
unsigned char i, j, k;
_nop_();
i = 8;
j = 1;
k = 243;
do
{
do
{
while (--k);
} while (--j);
} while (--i);
}
void UartInit(void) //9600bps@11.0592MHz
{
//AUXR避免辐射
AUXR = 0x01;
//设置串行口的工作方式
SCON = 0x40;
//设置波特率不加倍
PCON = 0x10;
//设置定时器模式,8位自动重装
TMOD &= 0x0F;
TMOD |= 0x20;
//设置定时器常数
TH1 = 0xFD;
TL1 = 0xFD;
//启动定时器
TR1 = 1;
}
void sendCh(char ch){
SBUF = ch;
while(!TI);//防止字符串还没有发送完毕,SBUF就发生了改变
TI = 0;
}
//发送字符串
void sendString(char* str){
while(*str != '\0'){
sendCh(*str);
str++;
}
}
void main(){
char data_mark = 'a';
//配置C51串口的通信方式
UartInit();
while(1){
Delay1000ms();
sendString("hello word\r\n");
}
}
注意上面代码中有一行while(!T1);
这一行是给程序延时的,防止串行数据还没发送完毕时,SBUF就发生了改变,这也是发送的数据
发生乱序的原因
向串口发送字符
#include "reg52.h"
#include <intrins.h>
sfr AUXR = 0x8E;
sbit led1 = P3^7;
void Delay1000ms() //@11.0592MHz
{
unsigned char i, j, k;
_nop_();
i = 8;
j = 1;
k = 243;
do
{
do
{
while (--k);
} while (--j);
} while (--i);
}
void UartInit(void) //9600bps@11.0592MHz
{
//AUXR±ÜÃâ·øÉä
AUXR = 0x01;
SCON = 0x50;
PCON = 0x10;
TMOD &= 0x0F;
TMOD |= 0x20;
TH1 = 0xFD;
TL1 = 0xFD;
TR1 = 1;
}
void main(){
char cmd;
UartInit();
while(1){
Delay1000ms();
if(RI == 1){
RI = 0;
cmd = SBUF;
if(cmd == 'o'){
led1 = 0;
}
if(cmd == 'c'){
led1 = 1;
}
}
}
}
向串口发送字符串控制开关灯,以中断的方式——简易
#include "reg52.h"
#include <intrins.h>
#include <string.h>
sfr AUXR = 0x8E;
sbit led1 = P3^7;
char arr[12];
void Delay1000ms() //@11.0592MHz
{
unsigned char i, j, k;
_nop_();
i = 8;
j = 1;
k = 243;
do
{
do
{
while (--k);
} while (--j);
} while (--i);
}
void UartInit(void) //9600bps@11.0592MHz
{
//AUXR避免辐射
AUXR = 0x01;
//设置串行口的工作方式,使能接收串口数据
SCON = 0x50;
//设置波特率不加倍
PCON = 0x10;
//设置定时器模式,8位自动重装
TMOD &= 0x0F;
TMOD |= 0x20;
//设置定时器常数
TH1 = 0xFD;
TL1 = 0xFD;
//启动定时器
TR1 = 1;
//开启全局中断开关
EA = 1;
//开启串行UART中断
ES = 1;
}
void sendCh(char ch){
SBUF = ch;
while(!TI);//防止字符串还没有发送完毕,SBUF就发生了改变
TI = 0;
}
//发送字符串
void sendString(char* str){
while(*str != '\0'){
sendCh(*str);
str++;
}
}
void main(){
//配置C51串口的通信方式
UartInit();
while(1){
Delay1000ms();
sendString("hello word\r\n");
}
}
void UART_Handle(void) interrupt 4
{
static int i;
if(RI){
RI=0;
arr[i++] = SBUF;
if(i==12){
i = 0;
}
if(strcmp(arr,"open") == 0){
led1 = 0;
i=0;
memset(arr,'\0',12);
}
if(strcmp(arr,"close") == 0){
led1 = 1;
i=0;
memset(arr,'\0',12);
}
}
}