通信按数据传输方式进行分类,可以分为串行通信和并行通信;按通信机制方式进行分类,可以分为同步传输和异步传输。按照数据传输方向和能力进行分类,可以分为单工,半双工和全双工。
串行通信:数据是按照单个比特一个接一个地传输的,需要在数据位之间插入控制位,以确保数据的传输正确。串行通信的优点是使用较少的导线,在长距离传输时更稳定,但传输速度相对较慢。
并行通信:数据是同时传输多个比特,需要更多的导线来实现。并行通信的优点是传输速度快,但成本高且容易产生电源噪声等干扰。
备注:图片来源于.html
同步通信:发送方和接收方使用共同的时钟信号进行数据传输和控制,这种方式的数据传输速度较快,但需要在发送和接收端维护相同的时钟,并且相对复杂。
异步通信:在数据传输过程中不需要任何时钟同步信号,而是在数据之间通过特定的协议进行数据同步。这使得异步通信更加简单易用,但传输速率相对较慢,数据传输可靠性也较差。
单工(Simplex):单工通信只能在一个方向上进行信息传输,即信息只能从一个方向的发送器传送到另一个方向的接收器,无法进行双向传输。例如,电视广播和无线电广播就是一种单向通信,只能通过广播信号发送信息,而无法接收信息反馈。
半双工(Half Duplex):半双工通信只能在同一时间内进行单向传输,即信息只能从一个方向的发送器传送到另一个方向的接收器,不能同时进行双向传输。例如,对讲机就是一个典型的半双工通信设备,同一时间内只能有一方进行发言,另一方只能听取,不能同时说话和听取。
全双工(Full Duplex):全双工通信可以在同一时间内进行双向传输,即信息可以同时从两个方向进行传输,例如电话通信、网络通信等。在全双工通信中,每个通信实体都拥有一个发送器和一个接收器,能够在不影响对方通信的情况下进行同时的双向数据传输。
备注:图片来源于
类型 | 描述 | 通信协议 | 数据传输速率 | 传输距离 | 应用 |
---|---|---|---|---|---|
同步串行通信 | 发送方与接收方在时钟方面保持同步,逐位地按照固定的时间间隔同时发送或接收数据 | SPI、I2C、Microwire等 | Mbps | 通常不超过一个设备的长度 | 短距离通信、芯片与芯片之间的通信 |
异步串行通信 | 发送方和接收方不需要保持时钟同步,每个数据字节之间有一个起始位和一个或多个停止位,实现了帧同步 | UART、RS-232等 | Kbps | 通常不超过几十米 | 数据采集、远程控制、较短距离通信 |
同步并行通信 | 发送方和接收方在时钟上保持同步,同时传输多个数据位 | ISA总线 | Mbps | 通常不超过一个设备的长度 | 高速数据传输 |
异步并行通信 | 发送方和接收方不需要时钟同步,在特定情况下可以同时传送多个数据位 | USB、PCI总线等 | Gbps | 通常不超过几米 | 高速数据传输、外部存储设备 |
类型 | 描述 | 通信协议 | 数据传输速率 | 传输距离 | 应用 |
---|---|---|---|---|---|
USB通信 | 通过USB接口连接各种外部设备,支持异步传输、同步传输和流传输等多种工作模式 | USB 1.x/2.x/3.x | Gbps | 通常不超过几米 | 外部设备连接、高速数据传输 |
CAN通信 | 用于工业自动化和汽车电子领域的数据总线标准,支持多个节点之间的数据传输 | CAN 2.0B | Mbps | 数百米至数千米 | 工业自动化、汽车电子 |
Ethernet通信 | 基于帧格式的网络协议,用于互联网和局域网通信,支持快速、可靠的数据传输 | IEEE 802.3 | Gbps | 通常不超过几百米 | 网络通信、数据中心、局域网 |
WiFi通信 | 基于无线局域网技术的通信方式,通过无线网络实现设备之间的数据传输 | IEEE 802.11 | Gbps | 通常不超过几十米 | 移动设备、家庭网络、公共场所 |
Bluetooth通信 | 短距离、低功耗的无线通信技术,主要用于移动设备之间的数据传输 | Bluetooth 4.0/5.0 | Mbps | 通常不超过几十米 | 移动设备、家庭娱乐、智能家居 |
① 串口通信是指通过串行通信接口来进行数据传输的一种通信方式。串口通信有两种基础协议:同步协议和异步协议,其中异步协议广泛应用于单片机开发中。
② 在异步协议中,通信双方的时钟并不需要进行同步,而是利用起始位和停止位来判断每一个字节的开始和结束。异步通信中最常用的协议是UART(Universal Asynchronous Receiver-Transmitter),UART只需要使用一根发送线和一根接收线即可完成单向或双向的串口通信。
③ 串口通信可以实现点对点和多点通信,实现简单,价格低廉,但数据传输速率较慢,一般采用的通信速率为115200bps以下。在单片机开发中,串口通信被广泛应用于与电脑之间的数据传输、与传感器之间的数据传输以及与其他单片机之间的数据传输等场景。(注意有时终线的是同步,没有时钟线的是异步,同步串行通信数据帧如下图所示 )
例如:MCU单片机给PC机发送一个字符 ‘A’,的通信过程大致如下:
串口通信的几个比较重要的参数包括:
波特率(Baud Rate):表示通信双方之间每秒传输的比特数,通常用bps(bits per second)来表示。波特率越高,数据传输速度越快,但同时也会增加误码率,降低传输可靠性。
数据位(Data Bits):表示每个字节中所包含的数据位数,常见的取值有5、6、7和8位。数据位的选择取决于数据所包含的信息量以及传输的精度要求。
停止位(Stop Bits):表示每个字节传输结束后,发送方在发送线上保持的电平状态,通常有1位和2位两种取值。停止位的作用是为了告诉接收方当前数据传输已经结束。
校验位(Parity):在数据传输过程中,加入一个校验位来判断数据是否正确传输。常见的校验方式有奇偶校验、偶校验、无校验等,其中奇偶校验最为常用。
以上参数需要双方进行协商确定,并在通信时保持一致,否则数据传输将会出现错误。在单片机开发中,常常使用的串口通信参数为波特率9600bps、8数据位、1停止位、无校验位。
串口线的接口标准通常有DB9和DB25两种,其中DB9有9根引脚,适用于较少信号的串口设备,而DB25有25根引脚,适用于需要传输大量信号的串口设备。在串口线的选择时,需要根据具体的设备类型和接口标准进行选择。同时,还需要注意串口线的长度和屏蔽效果,以确保数据传输的稳定性和可靠性。
DB9是一种常用的串口接口标准,也称作DE-9(D形9针),其中“D”指代连接器的外形类似于字母D。DB9接口共有9个引脚,分别为:
DB9接口广泛应用于串口设备之间的通信,如串口打印机、调制解调器、路由器、终端设备等。在使用DB9接口时,需要注意接口针脚的正确连接和通信参数的正确设置,以确保数据传输的稳定和可靠。
DB25是一种串口接口标准,也称作DE-25(D形25针),其中“D”指代连接器的外形类似于字母D。DB25接口共有25个引脚,与DB9接口相比,其拥有更多的信号引脚,能够支持更复杂的通信方式。DB25接口的引脚定义如下:
1.protective ground(保护接地)
2.TxD(Data Transmit) - 数据发送
3.RxD(Data Receive) - 数据接收
4.RTS(Request To Send) - 请求发送
5.CTS(Clear To Send) - 清除发送
6.DSR(Data Set Ready) - 数据集就绪
7.Signal ground(Signal Ground) - 信号地
8.CD(Carrier Detect) - 载波检测
9.RI(Ring Indicator) - 响铃指示
10.交替行选通
11.设备选择1
12.设备选择2
13.设备选择3
14.设备选择4
15.线路就绪
16.时钟
17.端口就绪
18.暂停
19.申请握手
20.结束握手
21.数据线就绪1
22.数据线就绪2
23.数据线就绪3
24.数据线就绪4
25.保留
DB25接口广泛应用于串口设备之间的通信,如计算机、打印机、调制解调器、路由器、终端设备等。在使用DB25接口时,需要注意接口针脚的正确连接和通信参数的正确设置,以确保数据传输的稳定和可靠。
串口的连接需要结合实际原理图来连接,看是采用的交叉线方式还是直通线方式,如果采用交叉线方式就把单片机的TXD与其他设备的RXD相连,RXD与TXD相连;如果采用的是直通线就把单片机的TXD与其他设备的TXD相连,RXD与RXD相连。
标准串口引脚2是RX,引脚3是TX,(即九针串口的2号引脚连接的是主控芯片的RXD引脚,3号引脚连接的是主控芯片的TXD引脚),如果单片机开发板的串口和电脑串口都是标准串口,则俩串口应该用交叉线连接。(单片机的TXD连接电脑的RXD;单片机的RXD连接串口的RXD)
不过现实中直通线居多,为了配合直通线的使用,在画板的时候,把主控芯片的RXD引脚连接至串口的3脚(RXD实际是TXD),主控芯片的TXD引脚连接至串口的2脚(TXD实际是RXD),这样这个开发板上的串口就不是标准串口了,即2变成TX,3变成RX,和标准串口连接时当然应该使用直连线了。(单片机的TXD(实际是RXD)和电脑的TXD相连;单片机的RXD(实际是TXD)和电脑RXD相连)
备注:参考了这篇博文:
① USB转串口是指通过USB接口将计算机与串口设备进行连接的一种方式。由于现代笔记本电脑大多已经取消了串口接口,而很多应用场合仍需要使用串口设备进行通信,因此USB转串口逐渐成为了一种常见的解决方案。
② USB转串口一般需要使用专门的转换器,这种转换器内部会集成一个串口芯片和USB芯片,可以实现USB和串口之间的信号转换和协议转换。在使用时,用户只需要将USB转串口转换器插入计算机的USB接口上,就可以通过串口通信软件来访问串口设备进行数据传输。
③ 需要注意的是,不同的USB转串口转换器支持的串口标准可能不同,如RS232、TTL等,因此在选择转换器时需要确认其支持的串口标准是否符合自己的需求。同时,在使用USB转串口转换器时也需要特别注意其驱动程序是否已经安装,以及通信参数的设置是否正确。
串口外设的架构图从下至上,我们看到串口外设主要由三个部分组成,分别是波特率的控制部分①、收发控制部分②及数据存储转移部分 ③。
波特率,即每秒传输的二进制位数,用 b/s (bps)表示,通过对时钟的控制可以改变波特率。在配置波特率时,我们向波特比率寄存器 USART_BRR 写入参数,修改了串口时钟的分频值USARTDIV 。 USART_BRR寄存器包括两部分,分别是DIV_Mantissa (USARTDIV 的整数部分)和DIVFraction (USARTDIV的小数)部分,最终,计算公式为USARTDIV=DIV_Mantissa+(DIVFraction/16)。USARTDIV 是对串口外设的时钟源进行分频的,对于USART1 ,由于它是挂载在 APB2 总线上的,所以它的时钟源为 fPCLK2 ;而 USART2、3 挂载在APB1 上,时钟源则为 fPCLK1 ,串口的时钟源经过 USARTDIV 分频后分别输出作为发送器时钟及接收器时钟 ,控制发送和接收的时序。
围绕着发送器和接收器控制部分,有多个寄存器:CR1、CR2、CR3、SR,即USART的三个控制寄存器 (Control Register)及一个 状态寄存器 (StatusRegister)。通过向寄存器写入各种控制参数 ,来控制发送和接收,如奇偶校验位,停止位等,还包括对USART中断的控制;串口的状态在任何时候都可以从状态寄存器中查询得到。
收发控制器根据我们的寄存器配置,对数据存储转移部分的移位寄存器进行控制。当我们需要发送数据时,内核或 DMA 外设(一种数据传输方式)把数据从内存(变量)写入到发送数据寄存器 TDR 后, 发送控制器 将适时地自动把数据从 TDR 加载到 发送移位寄存器 ,然后通过串口线Tx ,把数据 一位一位地发送出去,在数据从TDR 转移到移位寄存器时,会产生发送寄存器TDR 已空事件TXE ,当数据从移位寄存器全部发送出去时,会产生数据发送完成事件 TC ,这些事件可以在 状态寄存器 中查询到。而接收数据则是一个 逆过程 ,数据从串口线 Rx 一位一位地输入到接收移位寄存器 ,然后自动地转移到接收数据寄存器 RDR ,最后用内核指令或 DMA读取到内存(变量)中。
要在STM32F103C8T6上实现串口通信,可以按照以下步骤进行操作:
注意:串口在单片机中我们也常常用于调试,或输出运行的相应信息,所以我们可以通过对print/scanff函数进行重定向来实现通过printf函数输出的信息会通过串口发送到上位机设备上。
#include "uart1.h"
#include <stdbool.h>
#include "led.h"
#include "string.h"
char USART1_RX_Buffer[USART1_RX_MAX]= {0};// 接收缓存
uint8_t USART1_RX_Index= 0; // 接收下标
uint32_t led_run =0;
//加入以下代码,支持printf函数,而不需要选择use MicroLIB
#if 1
#pragma import(__use_no_semihosting)
//标准库需要的支持函数
struct __FILE
{ int handle; }; FILE __stdout;
//定义_sys_exit()以避免使用半主机模式
_sys_exit(int x)
{ x = x;
}
//重定义fputc函数
int fputc(int ch, FILE *f)
{ while((USART1->SR&0X40)==0);//循环发送,直到发送完毕 USART1->DR = (u8) ch; return ch;
}
#endif /***************** 发送一个字节 **********************/
void Usart_SendByte( USART_TypeDef * pUSARTx, uint8_t ch)
{/* 发送一个字节数据到USART */USART_SendData(pUSARTx,ch);/* 等待发送数据寄存器为空 */while (USART_GetFlagStatus(pUSARTx, USART_FLAG_TXE) == RESET);
}/****************** 发送8位的数组 ************************/
void Usart_SendArray( USART_TypeDef * pUSARTx, uint8_t *array, uint16_t num)
{uint8_t i;for(i=0; i<num; i++){/* 发送一个字节数据到USART */Usart_SendByte(pUSARTx,array[i]); }/* 等待发送完成 */while(USART_GetFlagStatus(pUSARTx,USART_FLAG_TC)==RESET);
}/***************** 发送字符串 **********************/
void Usart_SendString( USART_TypeDef * pUSARTx, char *str)
{unsigned int k=0;do {Usart_SendByte( pUSARTx, *(str + k) );k++;} while(*(str + k)!='