电子说
示意图
微控制器通信 - 什么是UART?
微控制器经常发现自己处于具有特定功能的专用电路中,例如测量,监控和控制。但是,有些情况下将微控制器连接到计算机可能非常有益甚至是必要的(例如,设备配置)。有几种方法可以实现PC-Microcontroller通信
通过Wi-Fi(如ESP8266模块)
以太网
USB
虽然这些形式的通信可能允许高数据传输速率,但它们很难使用,大多数微控制器都有另外一种类型的通信,称为UART,它代表通用异步接收器/发送器。
这是一个简单的串行连接,可以是用于以低速发送少量数据,并且使用和实现极其简单。使UART更加便捷的是,有USB转串口转换器可用于允许微控制器通过USB使用虚拟COM端口与PC通信。
串行概述
使用微控制器和计算机的串行通信可包括许多不同的设置,包括奇偶校验和停止位。但是,在本教程中,我们将介绍最简单的串行通信形式,这也是最常见的形式之一。所以我们首先要看的是如何发送串行数据。首先,我们来看看硬件!
微控制器上最简单形式的串行外设是一个美化的移位寄存器,它使用两个独立的I/O引脚来发送数据(TxDn)和接收数据(RxDn)
当需要从设备发送数据时,它会将数据发送到其发送移位寄存器中,然后逐位计时数据,直到所有数据都已发送完毕。当需要读取数据时,接收器首先需要检测是否正在接收某些数据。
一旦满足此条件,接收器就会将数据移入移位寄存器。完成后,可以从接收移位寄存器中读取器件,并以其认为合适的任何方式处理数据。
UART模块的简单框图
UART模块中使用的协议本身(有时称为RS-232)包含有助于数据传输/接收的选项和附加功能。下图显示了典型的UART传输,包括起始位,数据本身,奇偶校验位和停止位。
从ATmega168数据表中获取的图像
IDLE - 如果没有发生传输,则传输线必须保留逻辑1(5V,3.3V等)
起始位 - UART线上的下降沿表示传输即将开始
数据位 - 这些是我们的实际数据位发送,并且位首先发送到最低位(位0,位1 。..位7)
奇偶校验位 - 此可选位可用作错误检查的基本形式具有等于所有位组合的异或(XOR)的值
停止位 - 这是停止传输所必需的并且是逻辑1.有时,可以使用两个停止位,但通常只使用一个
ATmega上的UART
ATmega168上的UART模块非常复杂,因为它允许不同的操作模式(包括同步传输),但我们将配置UART以使用适用于99%基于UART的项目的最常见设置。
时钟源
我们需要配置的第一件事是UART模块的时钟源(这也配置了UART运行的模式) 。由于我们将使用异步传输(时钟不传输,只有数据),我们将使用“正常异步”。为此,我们在UCSRnC寄存器中将UMSEL位设置为0.
奇偶校验位和停止位
由于大多数传输不需要奇偶校验,我们将禁用该位。为此,我们需要将两个UPM位都设置为0,这可以在UCSR寄存器中找到。
对于停止位,我们只会使用一个停止位,通过清除UCSRnB寄存器中的USBS位来完成。
数据大小
UART模块能够以不同的位宽发送数据,但对于大多数项目,我们将使用8位数据大小,因为我们的微控制器是一个8位器件。为此,我们将寄存器UCSRnB和UCSRnC中的UCSZ位的值设置为011。
波特率
在谈到串行通信时,波特率通常是指每秒传输的数据位数,可以认为是连接速度。串行通信的典型波特率包括9600,115200和10417.
对于我们的串行设置,我们将使用9600的波特率(非常常见的波特率)。波特率可以使用下面的公式计算,但是,使用第163-165页上的表格更容易。
由于我们的ATmega168连接到8MHz振荡器,我们可以查看下表,看看我们将UBRR寄存器设置为什么值。
对于9600波特,我们将使用值51.请注意,您的CLKDIV8位可能已设置,如果是这种情况,那么您的波特率可能比您预期的慢8倍。如果是这种情况,请尝试使用UBRR值12而将U2X0设置为开,或使用更高的时钟速度。
启用接收/传输
我们需要设置几个启用位,其他启用位是可选的。我们需要使能的前两位是RXEN和TXEN,它们使能接收器和发送器。
我们可以设置两个中断使能位,这意味着当我们的UART模块完成发送或接收数据时,中断将触发(对实时应用程序有用)。
读/写UART
有趣的是,AVR UART外设对接收和发送寄存器使用相同的I/O地址。当写入UART数据寄存器(UDRn)时,数据被发送到UART发送器移位寄存器,当从UART数据寄存器读取时,返回来自UART接收器的数据。
一些有用的控制信号
一个寄存器UCSR0A可以帮助确定UART的状态模块,因为它有几个状态位。
RXC0,第7位,如果接收缓冲区中有需要读取的数据,则为1
TXC0,第6位,一旦传输将为1已完成
如果发送缓冲区为空,UDRE0,位5将为1
FE0,位4,发出帧错误警告
DOR0,第3位,发出数据溢出警告(当收到的数据太多且接收缓冲区已满时)
当奇偶校验时,UPE0,位2将为1在接收到的字节上检测到错误
一个简单的UART示例
此示例将介绍如何创建一个echo设备,该设备将等待连接的PC向UART线路发送一个字节。一旦检测到,AVR将立即发回相同的字节以回显消息。
/*
* AVR UART.c
*
* Created: 09/01/2018
* Author : RobinLaptop
*/
// These are really useful macros that help to get rid of unreadable bit masking code
#define setBit(reg, bit) (reg = reg | (1 《《 bit))
#define clearBit(reg, bit) (reg = reg & ~(1 《《 bit))
#define toggleBit(reg, bit) (reg = reg ^ (1 《《 bit))
#define clearFlag(reg, bit) (reg = reg | (1 《《 bit))
#include
int main(void)
{
// Initialize Registers
// Configure register UCSRA
setBit(UCSR0A, U2X0); // Double the BRG speed (since I am using a 8MHz crystal which is divided by 8)
clearBit(UCSR0A, MPCM0); // Normal UART communication
// Configure register UCSRB
clearBit(UCSR0B, RXCIE0); // We will not enable the receiver interrupt
clearBit(UCSR0B, TXCIE0); // We will not enable the transmitter interrupt
clearBit(UCSR0B, UDRIE0); // We will not enable the data register empty interrupt
setBit(UCSR0B, RXEN0); // Enable reception
setBit(UCSR0B, TXEN0); // Enable transmission
clearBit(UCSR0B, UCSZ02); // 8 bit character size
// Configure register UCSRC
clearBit(UCSR0C, UMSEL00); // Normal Asynchronous Mode
clearBit(UCSR0C, UMSEL01);
clearBit(UCSR0C, UPM00); // No Parity Bits
clearBit(UCSR0C, UPM01); // No Parity Bits
clearBit(UCSR0C, USBS0); // Use 1 stop bit
setBit(UCSR0C, UCSZ01); // 8 bit character size
setBit(UCSR0C, UCSZ00);
// Configure the baud rate register (this is a combination of both UBRR0L and UBRR0H)
// Despite using an 8MHz crystal my Fosc is 1MHz since the CLK8DIV fuse bit is dividing the clock
// by 8. When I try to change this fuse the AVR locks me out!
UBRR0 = 12;
while (1)
{
// Wait until data has been received
while(!(UCSR0A & (1 《《 RXC0)));
// Now send the same byte back
UDR0 = UDR0;
// Wait until the Data Transmit Register is empty
while(!(UCSR0A & (1 《《 TXC0)));
}
}
全部0条评论
快来发表一下你的评论吧 !