UART嵌入式通信协议(以AVR单片机为例)

概念

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的使用方法

  1. 初始化。工作模式,帧结构等(UCSRC)
  2. 波特率设置(UBBRL,UBBRH)
  3. 中断的相关设置(UCSRB)
  4. 选择中断号,编写中断服务函数

初始化

//以atmega32为例

#define uchar unsigned char
#define uint unsigned int
#define fosc 7372800 //时钟频率

uchar rdata;
uchar flag;

void uart_init(uint baud)//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))); //第五位是否为1,从而满足条件退出循环发送数据
UDR=data;
while(!(UCSRA&BIT(TXC));
UCSRA|=BIT(TXC); //写1进行清除操作
}

接受函数

#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);
//uart_send(i);
while(1)
	{
	if(flag)
		{
		flag=0;
		uart_send(rdata);	
		}
	}
}

实例

// ATMEGA32
#define F_CPU 8000000UL
#define myUBRR 8 // 115200 b/s
#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)//使用 UBRR 寄存器的给定值初始化 USART,该值应根据波特率 BoudRate 计算
/*  当 U2X=0 
		UBRR=Fosc/(16*BaudRate)-1  
		BaudRate=Fosc/16(UBRR+1) 
	当 U2X=1
		UBRR=Fosc/(8*BaudRate)-1 
		BaudRate=Fosc/8(UBRR+1)
*/
{
	UBRRH = (unsigned char)(speed>>8);
	UBRRL = (unsigned char)speed;

	UCSRB=(1<<RXEN)|( 1<<TXEN); //允许接收和发送USART
	#if (myU2X==1) //只有当myU2X=1时才会编译以下行
		UCSRA |= (1<<U2X); //传输速率加倍
	#endif
	UCSRC = (1<<URSEL)|(1<<USBS)|(1<<UCSZ1)|(1<<UCSZ0);// 8位传输,1个停止位

}

void USART_Transmit( unsigned char data ) //向USART通道传输一个字节
{
	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;// 将循环数输出到端口 C,准备在日志文件中固定新接收到的符号
			if (UCSRA & (1<<RXC)){ // 控制从 USART 通道接收信息
				ch=UDR;// 读取接收缓冲区以准备接收下一个字节
				if (UCSRA & ((1<<FE)|(1<<DOR))){ //检查是否有接收错误
					ch='.';//接收到的有错误的字节被替换为'.'
					PORTC=0xFF;//便于识别日志文件中的情况
				}
				// 没有接收错误
				PORTC=ch;//将接收到的字节输出到端口C,以便在日志文件中修复
				USART_Transmit(ch);
				i++;
			}
		}
		while (i<10);
		
		while ( !(UCSRA & (1<<TXC)) ); //检查空闲移位寄存器(传输完成)
//关闭并打开UART,
//导致需要新的接收同步(搜索起始位)
		UCSRB &= ~((1<<RXEN)|( 1<<TXEN));//禁用UART发送/接收,这会重置缓冲区中累积的接收位。
		PORTC=0; // 在日志文件中记录 UART 被禁用的那一刻
		for (i=0;i<(3*myUBRR);i++);//持续时间等于几位传输时间的时间延迟
		UCSRB|=((1<<RXEN)|( 1<<TXEN));// 启用 UART 发送/接收,开始搜索起始位
		PORTC=1;// 在启用 UART 的那一刻记录在日志文件中
	}
}

推荐练习

无论是汇编语言还是C语言等单片机编程,还是硬件基础知识中的常用网络通信协议,除了查看相关数据百度外,也要通过大量的练习进行掌握,我推荐可以去牛客网(点击可直达)看看,他们现在的题库内容很丰富,属于国内做的很好的了,里面的资源也是全部免费的,很好的一个平台,欢迎大家进入学习查看。
在这里插入图片描述

  • 3
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

啥都鼓捣的小yao

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值