概念
UART是一种通用串行数据总线,用于异步通信。该总线双向通信,可以实现全双工传输和接收。在嵌入式设计中,UART用于主机与辅助设备通信,如汽车音响与外接AP之间的通信,与PC机通信包括与监控调试器和其它器件,如EEPROM通信。
通信基础
并行通信
串行通信
单工通信
数据传输方向是单向。
双工通信
半双工
通信不可同时进行
全双工
波特率
波特率是衡量资料传送速率的指标。表示每秒钟传送的符号数(symbol)。一个符号代表的信息量(比特数)与符号的阶数有关。例如传输使用256阶符号,每8bit代表一个符号,资料传送速率为120字符/秒,则波特率就是120baud,比特率是120*8=960bit/s。
UART帧格式
硬件连接
控制器
一般情况下处理器都会集成UART控制器,我们使用YART进行通信时只需要对其内部相关控制器进行设置即可。
AVR单片机USART相关寄存器
I/O数据寄存器 UDR
控制和状态寄存器 UCSRA
- 位7—RXC:USART接收结束(中断标志位)
- 位6—TXC:USART发送结束
- 位5—UDRE:数据寄存器空
- 位4—FE:帧错误
- 位3—DOR:数据溢出
- 位2—PE:奇偶校验错误
- 位1—U2X:倍速发送
- 位0—MPCM:多处理器通信模式
控制和状态寄存器UCSRB
- 位7—RXCIE:接受结束中断使能,为1产生中断
- 位6—TXCIE:发送结束中断使能
- 位5—UDRIE:USART数据寄存器空 中断使能
- 位4—RXEN:接受使能,置为后将启动USART接收器
- 位3—TXEN:发送使能,置为后将启动USART发送器
- 位2—UCSZ2:字符长度
- 位1—RXB8:对于9位串行帧进行操作时,RXB8是第9个数据位。
- 位0—TXB8:对于9位串行帧进行操作时,TXB8是第9个数据位。
控制和状态寄存器UCSRC
- 位7—URSEL:寄存器选择,通过该位访问UCSRC寄存器或UBRRH寄存器。当读UCSRC时,该位为1;当写UCSRC时,该位必须写1
- 位6—UMSEL:USART模式选择,通过这一位来选择同步或异步工作模式,0为异步,1为同步
- 位5—位4 UPM:奇偶校验模式设置,00禁止,01保留,10偶校验,11奇校验
- 位3—USBS:停止位选择。0-停止位位数1;1-停止位位数2
- 位2—位1 UCSZ:字符长度设置
- 位0—UCPOL:时钟极性,仅用于同步工作模式
波特率寄存器UBRRL和UBRRH
- 位15—URSEL:寄存器选择,当读时为0,当写时为1
- 位11—0 UBRR比特率寄存器:UBRRH包含了比特率的高四位,UBRRL包含了低8位
在操作时设置最高位URSEL来区分。
- 写操作:当写入数据时,最高位为0,数据写入UBRRH;数据的最高位为1时,数据写入UCSRC 读操作
- 读操作:第一次读取的值为寄存器UBBRH的数值,如果在连续的两个时钟周期里都执行读操作,那么第二次读到的就是UCSEC的值
波特率计算公式 例子 误差计算公式
USART的使用方法
- 初始化。工作模式,帧结构等(UCSRC)
- 波特率设置(UBBRL,UBBRH)
- 中断的相关设置(UCSRB)
- 选择中断号,编写中断服务函数
初始化
#define uchar unsigned char
#define uint unsigned int
#define fosc 7372800
uchar rdata;
uchar flag;
void uart_init(uint baud)
{
uint a;
UCSRC=0x86;
a=fosc/16-baud-1;
UBRRL=a%256;
UBRRH=a/256;
UCSRB=0x98;
SREG|=BIT(7);
}
发送函数
void uart_send(uchar data)
{
while(!(UCSRA&BIT(UDRE)));
UDR=data;
while(!(UCSRA&BIT(TXC));
UCSRA|=BIT(TXC);
}
接受函数
#pragma interrupt_handler uartrece_isr:12
void uartrece_isr(void)
{
UCSRB&=~BIT(7);
rdata=UDR;
flag=1;
UCSRB|=BIT(7);
}
主函数
void main(void)
{
uchar i ='h';
uart_init(9600);
while(1)
{
if(flag)
{
flag=0;
uart_send(rdata);
}
}
}
实例
#define F_CPU 8000000UL
#define myUBRR 8
#define myU2X 1
#include <avr/io.h>
#include <avr/interrupt.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
void USART_Init( unsigned int speed)
{
UBRRH = (unsigned char)(speed>>8);
UBRRL = (unsigned char)speed;
UCSRB=(1<<RXEN)|( 1<<TXEN);
#if (myU2X==1)
UCSRA |= (1<<U2X);
#endif
UCSRC = (1<<URSEL)|(1<<USBS)|(1<<UCSZ1)|(1<<UCSZ0);
}
void USART_Transmit( unsigned char data )
{
while ( !(UCSRA & (1<<UDRE)) );
UDR = data;
UCSRA |= (1<<TXC);
}
int main (void)
{
char ch='O';
int i;
DDRC=0xFF;
USART_Init(myUBRR);
while (true) {
i=0;
do {
PORTC=i;
if (UCSRA & (1<<RXC)){
ch=UDR;
if (UCSRA & ((1<<FE)|(1<<DOR))){
ch='.';
PORTC=0xFF;
}
PORTC=ch;
USART_Transmit(ch);
i++;
}
}
while (i<10);
while ( !(UCSRA & (1<<TXC)) );
UCSRB &= ~((1<<RXEN)|( 1<<TXEN));
PORTC=0;
for (i=0;i<(3*myUBRR);i++);
UCSRB|=((1<<RXEN)|( 1<<TXEN));
PORTC=1;
}
}
|