串口通信
通信按照基本类型可以分为并行通信和串行通信。并行通信的各个数据位同时传送,但占用资源多,成本高;而串行通信的数据位是由低位到高位一位一位发送的。
常用的通信从传输方向上可以分为单工通信、半双工通信、全双工通信三类。
1.单工通信就是指只允许一方向另外一方传送信息,而另一方不能回传信息。比如电视遥控器、收音机广播等,都是单工通信技术。
2.半双工通信是指数据可以在双方之间相互传播,但是同一时刻只能其中一方发给另外一方,比如我们的对讲机就是典型的半双工。
3.全双工通信就发送数据的同时也能够接收数据,两者同步进行,就如同我们的电话一样,我们说话的同时也可以听到对方的声音。
二.串口通信的基本知识:
通常一个单片机有两个引脚是来做UART通信的,P3.0(RXD)、P3.1(TXD),两个单片机通信的示意图:
TXD 是串行发送引脚,RXD是串行接收引脚。两个单片机之间要通信,首先电源基准得一样,所以我们要把两个单片机的 GND 相互连接起来。
串行通信的数据发送过程:
在 UART 通信的时候,一个字节是8位,规定当没有通信信号发生时,通信线路保持高电平,当要发送数据之前,先发一位 0 表示起始位,然后发送 8 位数据位,数据位是先低后高的顺序,数据位发完后再发一位 1 表示停止
位。这样本来要发送一个字节的 8 位数据,而实际上我们一共发送了 10 位,多出来的两位其中一位起始位,一位停止位。而接收方呢,原本一直保持的高电平,一旦检测到了一位低电平,那就知道了要开始准备接收数据了,接收到 8 位数据位后,然后检测到停止位,再准备下一个数据的接收。
三、串口通信速率的约定:
串口通信的时候涉及到引脚的高低电平的持续时间,比如发送一个0和1,发送引脚先持续一段低电平,在持续一段高电平,那么这个数据就发送过去了,这个时间是如何约定的,这就需要了解通信当中的另外一个概念——波特率(baud)。
发送一位二进制的时间=1/baud,通信之前,单片机 1 和单片机 2 首先都要明确的约定好它们之间的通信波特率,必须保持一致,收发双方才能正常实现通信。
四.USB转串口通信
现在大多数的笔记本电脑上已经没有串口了,所以一般我们的电路板上会有一个USB转串口的芯片,以实现实现USB通信协议和标准UART串行通信协议的转换,一般常用的芯片有ch340和pl2303这两个转串口的芯片
五、UART模块介绍:
51单片机的 UART串口的结构由串行口控制寄存器SCON、发送和接收电路三部分构成。
SCON-串行控制寄存器的位分配(地址0x98,可位寻址)
位 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
---|---|---|---|---|---|---|---|---|
符号 | SM0 | SM1 | SM2 | REN | TB8 | RB8 | TI | RI |
复位值 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
SCON - 串行寄存器位描述
位 | 符号 | 描述 |
---|---|---|
7/6 | SM0/SM1 | 这两位共同决定了串口通信的模式 0~模式 3 共 4 种模式。 我们最常用的就是模式 1,也就是 SM0=0, SM1=1,下边我们重点就讲模式 1,其它模式从略。 |
5 | SM2 | 多机通信控制位(极少用),模式 1 直接清零。 |
4 | REN | 使能串行接收。由软件置位使能接收,软件清零则禁止接收。 |
3 | TB8 | 模式 2 和 3 中要发送的第 9 位数据(很少用)。 |
2 | RB8 | 模式 2 和 3 中接收到的第 9 位数据(很少用),模式 1 用来接收停止位。 |
1 | TI | 发送中断标志位,当发送电路发送到停止位的中间位置时, TI 由硬件置 1,必须通过软件清零。 |
0 | RI | 接收中断标志位,当接收电路接收到停止位的中间位置时, RI 由硬件置 1,必须通过软件清零。 |
可以位寻址的含义:支持对寄存器的单个位进行操作,不可位寻址的只能一次性对寄存器进行整体操作。
串口通信的波特率,只能由定时器T1或T2产生,不能由T0产生。使用定时器2,则需要配置额外的寄存器,默认使用的是定时器1。使用定时器1产生波特率需要使用定时器1的模式2,即自动重载模式:
TH1 = TL1 = 256 - 晶振值/12/2/16/波特率
波特率有关的还有一个寄存器,是一个电源管理寄存器PCON,他的最高位可以把波特率提高一倍,也就是如果写 PCON |= 0x80 以后,计算公式就成了:
TH1 = TL1 = 256 - 晶振值/12 /16 /波特率
关于SBUF寄存器:
串口通信的发送和接收电路在物理上有2个名字相同的SBUF寄存器,它们的地址也都是0x99,但是一个用来做发送缓冲,一个用来做接收缓冲。意思就是说,有2个房间,两个房间的门牌号是一样的,其中一个只出人不进人,另外一个只进人不出人,这样的话,我们就可以实现UART的全双工通信,相互之间不会产生干扰。我们每次只操作SBUF,单片机会自动根据对它执行的是“读”还是“写”操作来选择是接收 SBUF 还是发送 SBUF。
//例:发送
SBUF = 1;
//接受
P0 = SBUF;
六、串口通信的基本配置步骤:
1、配置串口为模式 1。
2、配置定时器 T1 为模式 2,即自动重装模式。
3、根据波特率计算 TH1 和 TL1 的初值,如果有需要可以使用 PCON 进行波特率加倍。
4、打开定时器控制寄存器 TR1,让定时器跑起来。
T1 做波特率发生器的时候,千万不要再使能 T1 的中断了。否则会使产生的波特率发生错误。
void UART_Init(unsigned int baud)
{
SCON = 0x50; //配置串口为模式 1
TMOD &= 0x0F; //清零 T1 的控制位
TMOD |= 0x20; //配置 T1 为模式 2
TH1 = 256 - (11059200/12/32)/baud; //计算 T1 重载值
TL1 = TH1; //初值等于重载值
ET1 = 0; //禁止 T1 中断
//ES = 1 ; //使能串口中断
TR1 = 1; //启动 T1
}
当我们使用串口中断的时候:
//首先main函数中打开总中断
main()
{
EA = 1; //使能总中断
UART_Init(9600); //将里面的串口使能中断打开
...}
//串口中断服务函数
void InterruptUART() interrupt 4
{
if (RI) //接收到字节
{
RI = 0; //手动清零接收中断标志位
SBUF = SBUF + 1; //接收的数据+1 后发回,左边是发送 SBUF,右边是接收 SBUF
}
if (TI) //字节发送完毕
{
TI = 0; //手动清零发送中断标志位
}
}
串口接收和发送数据的时候,都是一个字节一个字节的进行的,假如我们想要发送一个字符串的话,我们可以先写好一个字节的发送函数,然后再写一个发送字符串的函数,通过循环的方式一个字节一个字节的发送过去,这样我们就可以放字符串了。
七、关于ASCII码:
我们常用的字符就包含了0~9的数字、A~Z/a~z的字母、还有各种标点符号等。那么在单片机系统里面我们怎么来表示它们呢?ASCII码(AmericanStandardCodeforInformationInterchange,即美国信息互换标准代码)可以完成这个使命:我们知道,在单片机中一个字节的数据可以有 0~255 共 256个值,我们取其中的0~127共128个值赋予了它另外一层涵义,即让它们分别来代表一个常用字符,当我们用字符格式发送一个小a,其实发送的是十六进制的0x61,这样就体现了ASCII码表的用处,其具体的对应关系如表:
ASCII码字符表
ASC | 控制 | ASCII | 字符 | ASCII | 字符 | ASCII | 字符 |
---|---|---|---|---|---|---|---|
000 | NUL | 032 | (space) | 064 | @ | 096 | ‟ |
001 | SOH | 033 | ! | 065 | A | 097 | a |
002 | STX | 034 | “ | 066 | B | 098 | b |
003 | ETX | 035 | # | 067 | C | 099 | c |
004 | EOT | 036 | $ | 068 | D | 100 | d |
005 | END | 037 | % | 069 | E | 101 | e |
006 | ACK | 038 | & | 070 | F | 102 | f |
007 | BEL | 039 | ‘ | 071 | G | 103 | g |
008 | BS | 040 | ( | 072 | H | 104 | h |
009 | HT | 041 | ) | 073 | I | 105 | i |
010 | LF | 042 | * | 074 | J | 106 | j |
011 | VT | 043 | + | 075 | K | 107 | k |
012 | FF | 044 | , | 076 | L | 108 | l |
013 | CR | 045 | - | 077 | M | 109 | m |
014 | SO | 046 | . | 078 | N | 110 | n |
015 | SI | 047 | / | 079 | O | 111 | o |
016 | DLE | 048 | 0 | 080 | P | 112 | p |
017 | DC1 | 049 | 1 | 081 | Q | 113 | q |
018 | DC2 | 050 | 2 | 082 | R | 114 | r |
019 | DC3 | 051 | 3 | 083 | S | 115 | s |
020 | DC4 | 052 | 4 | 084 | T | 116 | t |
021 | NAK | 053 | 5 | 085 | U | 117 | u |
022 | SYN | 054 | 6 | 086 | V | 118 | v |
023 | ETB | 055 | 7 | 087 | W | 119 | w |
024 | CAN | 056 | 8 | 088 | X | 120 | x |
025 | EM | 057 | 9 | 089 | Y | 121 | y |
026 | SUB | 058 | : | 090 | Z | 122 | z |
027 | ESC | 059 | ; | 091 | [ | 123 | { |
028 | FS | 060 | < | 092 | \ | 124 | ¦ |
029 | GS | 061 | = | 093 | ] | 125 | } |
030 | RS | 062 | > | 094 | ^ | 126 | ~ |
031 | US | 063 | ? | 095 | _ | 127 | DEL |