一、UART基础概念
UART(Universal Asynchronous Receiver/Transmitter) 通用异步收发器;
参与通信的设备称为主机;
通信的本质是信息的传达;
1.1 通信方式
1.2 串行通信与并行通信
- 并行通信:通信双方之间有两根及以上的数据线传输信息;传输速率较高,但会占用大量的芯片资源传输速率较高,但会占用大量的芯片资源.
- 串行通信:通信双方之间只有一根数据线传输信息;系统占用资源少,结构简单等优点。
USB(统一串口总线)
1.3 UART
UART(串口)是一种通信方式,全双工串行通信方式
作为常用的串行通信方式,以TTL为例,串口通信在不同主机之间的数据格式为:
空闲时数据线为高电平;
发送时发送一个低电平表示起始位;
发送的第一个比特是最低位(最右边)bit0即LBS;
校验位分为奇校验,偶校验和无校验。 奇校验是指确保数据位加上校验位中"1",1的总数为奇数; 偶校验是指确保数据位加上校验位中"1",1的总数为偶数;
为保证下一个字节发送前的起始位能够表现出来,校验位之后发送一个停止位1。(将数据分隔);
数据传输速率:
串行通信用波特率(bit per second)来描述数据传输的速率,记作bps。常见的波特率有1200、2400,4800,9600,115200等,表示每秒钟传输的比特数。
串行的异步通信与同步通信:
异步通信:指通信中两个字符(8位)之间的时间间隔是不固定的,而在一个字符内各位的时间间隔是固定的;
收发双方的波特率必须是事先约定好的;
同步通信:要求发收双方具有同频同相的同步;
用专用时钟信号线来控制时钟的节奏,以为例
- SDA(数据线)
- SCL(时钟线):用于同步双方时钟的节奏,一般由发送方决定;
主机间通信时的电器物理问题:
主机间通信无论采用并行还是串行方式,都无法避免一个物理现象:导线内阻不为零
造成的电压衰减。以之前讨论的TTL电平为例,主机之间的距离会造成高电平在接收端出现衰减现象和串扰(指不同信号之间相互干扰导致信号失真)影响。
1.TTL(Transistor-Transistor Logic)通常指的就是芯片引脚产生的电压,这个电压值跟选择的芯片有关,在51单片机系统下是5v;在2440下是3.3v等等。5vTTL通信距离通常被限制在10~20米之间,如果需要更远的距离,怎么解决呢?
2. 为解决这个问题IEEE(Institute of Electrical and Electronics Engineers)颁布了RS232标准,其中规定了:
逻辑高电平(逻辑1):在-3V到-15V之间
逻辑低电平(逻辑0):在+3V到+15V之间
收发主机间有三根线,分别是收、发和地,因此RS232是全双工的。理论上RS232能够传输20~30米。
3.同理RS485使用两根信号线(A和B)来传输数据,通过比较A和B之间的电压差来识别信息,电压范围分别为+7V到+12V和-7V到-12V。正电压表示高电平,负电压表示低电平。这种差分信号传输方式提高了抗干扰能力。RS485的传输距离可达1200米,适用于大范围的数据传输需求。由于采用的是压差,RS485在传输数据的某一时刻,两根线都要用到,所以它是半双工的。
二、串口通讯(51单片机)
Windows表示串口为COMn;
2.1 SBUF寄存器
2.2 SCON寄存器与PCON寄存器
STC89C51RC/RD+系列单片机的串行口设有两个控制寄存器:串行控制寄存器SCON和波特率选择特殊功能寄存器PCON
2.2.1 SCON寄存器
2.2.2 PCON寄存器
xdata 的作用:不将内容放在芯片内部的RAM中,放在扩展的RAM中
uart.c
#include "uart.h"
#include <reg52.h>
void init_uart(void)
{
//串口接收
SCON &= ~(3 << 6);
SCON |= (1 << 6) | (1 << 4);
//使参数生效
PCON &= ~(1 << 6);
PCON |= (1 << 7);
//设置波特率,51单片机使用定时器1
TMOD &= ~(0x0F << 4);
TMOD |= (2 << 4); //TMOD |= (1 << 5);前者更有可读性
TL1 = 230;
TH1 = 230;
//打开定时器1
TCON |= (1 << 6);
//打开中断控制位及串口控制位
IE |= (1 << 7) | (1 << 4);
}
//中断服务函数(TI RI都会导致中断)
//1.void uart_handler(void) interrupt 4
//{
// if((SCON & (1 << 0)) == 1)
// {
// P2 = SBUF;//用LED显示
// SCON &= ~(1 << 0);
// }
//}
//2.
xdata char rcv_buffer[32];
unsigned int pos = 0;
void uart_handler(void) interrupt 4
{
if((SCON & (1 << 0)) == 1)
{
if(pos < 32)
{
rcv_buffer[pos++] = SBUF;
rcv_buffer[pos] = 0;
}
SCON &= ~(1 << 0);
}
}
//发送(轮询)
void send_char(char ch)
{
SBUF = ch;
while((SCON & (1 << 1)) == 0);
SCON &= ~(1 << 1);
}
void send_buffer(const char *p, unsigned int len)
{
while(len--)
{
send_char(*p++);
}
}
void send_str(const char *p)
{
while(*p)
{
send_char(*p++);
}
}
main.c
#include "uart.h"
#include "delay.h"
#include <reg52.h>
#include <string.h>
//int main(void)
//{
// const char *s = "Hello World!";
// char buffer[] = {0xAA, 0xBB, 0x00, 0x11};
// init_uart();
// while(1)
// {
// //send_char('A');
// send_buffer(s,strlen(s));
// //send_buffer(buffer, sizeof(buffer) / sizeof(*buffer));
// delay(0xAFFF);
// }
//}
//int main(void)
//{
// init_uart();
// while(1)
// {
// if(pos != 0)
// {
// delay(0xAFFF);
// send_buffer(rcv_buffer, pos);
// pos = 0;
// }
//
// }
int main(void)
{
//xdata char buffer[16];
init_uart();
while(1)
{
if(pos != 0)
{
delay(0xAFFF);
if(strcmp(rcv_buffer, "Hello") == 0)
{
send_str("Hi");
}
else if(strcmp(rcv_buffer, "see u later") == 0)
{
send_str("bye");
}
pos = 0;
}
}
}
三、MODBUS通信协议