一、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单片机)
-
硬件部分(USB下载电路)
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单片机使用定时器1TMOD &= ~(0x0F << 4);TMOD |= (2 << 4); //TMOD |= (1 << 5);前者更有可读性TL1 = 230;TH1 = 230;//打开定时器1TCON |= (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通信协议