战舰V3 USART1、USART2、UASRT3、UART4、UART5串口配置

战舰V3 USART1、USART2、UASRT3、UART4、UART5串口配置,第1张

在STM32中UART和USART是不相同的,在官方的文档中,大部分配置的都是USART2和UASRT3,对于UART4和UART5却很少有人配置,由于最近在集成项目,所以要用到多种串口,所以索性就配置了UART4和UART5

例如:

简单区分同步和异步就是看通信时需不需要对外提供时钟输出,我们平时用的串口通信基本都是UART。

USART支持同步模式,因此USART需要同步时钟信号USART_CK(如STM32 单片机),通常情况同步信号很少使用,因此一般的单片机UART和USART使用方式是一样的,都使用异步模式。

UART需要固定的波特率,就是说两位数据的间隔要相等。 UART总线是异步串口,一般由波特率产生器(产生的波特率等于传输波特率的16倍)、UART接收器、UART发送器组成,硬件上有两根线,一根用于发送,一根用于接收。 显然,如果用通用IO口模拟UART总线,则需一个输入口,一个输出口。

UART是一个并行输入成为串行输出的芯片,通常集成在主板上,多数是16550AFN芯片。因为计算机内部采用并行数据,不能直接把数据发到Modem,必须经过UART整理才能进行异步传输,其过程为:CPU先把准备写入串行设备的数据放到UART的寄存器(临时内存块)中,再通过FIFO(First Input First Output,先入先出队列)传送到串行设备,若是没有FIFO,信息将变得杂乱无章,不可能传送到Modem。

作为接口的一部分,UART还提供以下功能:将由计算机内部传送过来的并行数据转换为输出的串行数据流。将计算机外部来的串行数据转换为字节,供计算机内部使用并行数据的器件使用。在输出的串行数据流中加入奇偶校验位,并对从外部接收的数据流进行奇偶校验。在输出数据流中加入启停标记,并从接收数据流中删除启停标记。处理由键盘或鼠标发出的中断信号(键盘和鼠标也是串行设备)。可以处理计算机与外部串行设备的同步管理问题。

USART收发模块一般分为三大部分:时钟发生器、数据发送器和接收器。控制寄存器为所有的模块共享。时钟发生器由同步逻辑电路(在同步从模式下由外部时钟输入驱动)和波特率发生器组成。发送时钟引脚XCK仅用于同步发送模式下,发送器部分由一个单独的写入缓冲器(发送UDR)、一个串行移位寄存器、校验位发生器和用于处理不同浈结构的控制逻辑电路构成。使用写入缓冲器,实现了连续发送多浈数据无延时的通信。接收器是USART模块最复杂的部分,最主要的是时钟和数据接收单元。数据接收单元用作异步数据的接收。除了接收单元,接收器还包括校验位校验器、控制逻辑、移位寄存器和两级接收缓冲器(接收UDR)。接收器支持与发送器相同的帧结构,同时支持桢错误、数据溢出和校验错误的检测。USART是一个全双工通用同步/异步串行收发模块,该接口是一个高度灵活的串行通信设备。

综上可以看出,USART相对UART来说是在异步通信的基础上还有同步的功能,USART能够提供主动时钟。

先来看一下引脚图

[上传失败(image-5879a4-1545558491497)]

可以看到USART1、USART2、UASRT3、UART4、UART5对应的引脚,下面我们就来配置!

初始化程序:

初始化程序:

初始化程序:

初始化程序:

初始化程序:

对比一下不难发现UASRT的初始化和UART的初始化几乎相同!!!!!

由于没写中断处理程序当发送完成后,触发串口中断进入0x0023地址处运行,就相当于复位了一次一样。所以会出现2次的情况。(第二次由于TI已经为1了所以不会触发中断)

解决方法

1、关闭串口中断

EA=0;

ES=0;

2、写一个串口中断处理函数

void UARTInterrupt(void) interrupt 4

{

if(RI)//RI标志位为1代表接收到数据

{

RI = 0 ;//清零接收标志位

//在这里添加中断处理函数

}

else

TI = 0;//如果RI不为1一般是发送完成中断 把TI(发送完成标志位)清零

}

发送完成后清零TI

SBUF = 'i';

while(!TI);//等待发送完成

TI = 0;//发送完成后清零TI

这样就可以实现多个字节发送不会造成冲突

一、 IO模拟UART发送

串口通信属于 串行 异步 半双工 的通信模式

1、 最近在调试一个IO模拟UART的程序,把调试过程中遇到的问题总结一下。对于UART的发送部分(主机模式)还是比较容易实现的。比较麻烦的做从机时,UART接收还在调试,可以接收数据,但还存在很多问题。

(1) 起始位 :总线没通信是高电平状态,要进行通信时,总线拉低发出“逻辑0”信号,表示开始传输数据

(2) 数据位 :通常以1byte数据为标准,从低位开始传输,通过时钟频率来定位数据的传输

(3) 奇偶校验位 :通过在数据末尾加上1位,使得数据包中的1的个数为偶数(偶校验)或者是奇数(奇校验),来确定数据的准确性。

(4) 停止位 :在通信结束时,将总线拉高发出“逻辑1”信号,表示传输结束,也给下次进行通信提供了校准时间的机会

2、波特率

波特率表示每秒钟传送的码元符号的个数,是 衡量数据传输速率的指标 ,它用单位时间内载波调制状态改变的次数来表示,1波特即指每秒传输1个符号。

若 波特率为9600bps,那么传输一位数据的时间是在1000ms/9600bps=0104ms

3、串口发送数据组成

数据由:1bit起始位+8bit数据+1bit停止位构成;

所以,搞懂这些原理,串口发送并不难,主要把单片机的定时器配置在104us左右溢出中断,保证每一位时间间隔在104us 左右即可。

我用的是51单片机,51本身自带一个串口,但自己想用IO模拟一个串口出来,便于自己更好的理解串口,也作为自己的一个技术储备。

/51单片机IO模拟UART实验/

/

文件名:uartc

/

#include "reg52h"

#include "typeh"

#include "uarth"

#include "timerh"

void UART_INIT(void)

{

    TX_D=1;

    Timer1Init();    //T1 初始化

}

void WAIT_TF1(void)

{

    while(!TF1);  //查询计数器溢出标志位

    TF1=0;

}

//写数据很快的话,定时器不稳定而导致发送的数据会有错码,发送时应适当延时降低错码概率

void Write_DATA(uint8_t input)

{

    uint8_t i=8;  //写入1byte数据

    TR1=1;        //开始计时

    TX_D=0;        //拉低信号线准备发送数据  起始信号

    WAIT_TF1();    //106us溢出一次,溢出进行下一位的传输

    while(i--)    //开始写数据

    {

        TX_D=input&0X01;

        WAIT_TF1();

        input>>=1;

    }

    TX_D=1;      //8位数据发完拉高信号线  停止信号

    WAIT_TF1();

    TR1=0;        //停止计时

}

//发送字符串

void Send_Char(uint8_t buf)

{

    while(buf != '\0')

    {

    Write_DATA(buf);

    buf++;

    }

}

//发送数字

void Send_Num(uint8_t buf,uint16_t s)

{

    while(s--)

    {

        Write_DATA(buf+48);    //ASCII 将字符转换成数字

        buf++;

    }

}

//发送多个数据

void Send_ND(uint8_t buf,uint16_t len)

{

    while(len--)

    {

        Write_DATA(buf); 

        buf++;

    }

}

#include "typeh"

#ifndef  __UART_H__

#define  __UART_H__

sbit TX_D=P0^6;

extern uint8_t flag2;

extern void Send_Char(uint8_t buf);                //发送字符

extern void Send_ND(uint8_t buf,uint16_t len);    //发送N个数据

extern void Send_Num(uint8_t buf,uint16_t s);      //发送数字

extern void UART_INIT(void);                        //串口初始化

extern void WAIT_TF1(void);                        //等待TF1溢出

extern void Write_DATA(uint8_t input);              //写数据

#endif

/

文件名:timerc

/

#include "reg52h"

#include "typeh"

#include "timerh"

uint8_t flag1=0;

void Timer1Init()

{

  TMOD = 0x10;  //T1  方式1

    TH1 = 0xFF;    //波特率9600bps 1000ms/9600bps=0104ms

    TL1 = 0xA0;    //定时器误差2us左右  106us

    EA = 1;

    ET1 = 1;

    TR1 = 1;

  TF1=0;

}

void Time1() interrupt 3

{

if(TR1==1)

{

TH1=0XFF;

TL1=0xA0;

flag1=1;

}

}

#include "typeh"

#ifndef  __TIMER_H__

#define  __TIMER_H__

extern uint8_t flag1;

extern void Timer1Init(void);

#endif

#ifndef  __TYPE_H__

#define  __TYPE_H__

#define uint8_t  unsigned char

#define uint16_t  unsigned int

#endif

/主程序--测试部分/

#include "reg52h"

#include "typeh"

#include "timerh"

#include "uarth"

#include "delayh"

uint8_t buffer[5];

uint8_t Buff[5]={1,2,3,4,5};

void main(void)

{

UART_INIT();

Write_DATA('A');

Send_Char("testuart");

Send_Num(Buff,5);

while(1);

}

如果发送发在while(1)中跑的话,需要加延时来降低由于查询过快导致的发送乱码的概率,事实证明加延时效果更好,结果更准确。

二、 IO模拟UART接收

1、模拟串口接收部分是可以接收,但存在很多问题

2、我对问题进行了总结以便后期改进

3、读数据  接收数据的效果不是很好,需要连续的点击发送字符才会成功

    问题解析 :估计是等到单片机扫描时,串口helper已经把数据发送完了,单片机这边对不上起始信号从而导致错峰,所以串口helper需要不停的点击发送在这个期间对上了就进去了。

最近调试了一下,现在接收部分已经可以正常接收了。

接收部分

uint8_t Receive_Data(void)

{

uint8_t receive=0,t=0;

uint8_t i=8;

while(RX_D);    //等待起始信号,超时自动退出

TR1=1;    //开始计时

WAIT_TF1();

while(i--)

{

receive>>=1;

if(RX_D)receive|=0x80;

WAIT_TF1();

}

TR1=0;

return receive;

}

void Recevice(uint8_t temp,uint8_t data_size)   

{

while(data_size--)

{

temp++=Receive_Data();

}

}

TEST

uint8_t recv[20]={0};

void main(void)

{

UART_INIT();

while(1)

{

  Recevice(recv,5);

  Send_ND(recv,5);

}

}

软件准备:

NodeMCU v2提供三个UART。您可以在TXD0,RXD0,TXD1,TXD2,RXD2上看到它们:

我们可以使用UART库访问UART串口。

在本章中,我使用Arduino板作为UART源。我们从UART读取传入的消息。开始吧!

在串口通信的教程中,我使用Arduino Uno连接到NodeMCU板。我们在连接到Arduino板的NodeMCU上使用UART0。我们应该将RX引脚连接到TX引脚,将TX引脚连接到RX引脚。

以下是我们的连线方式:

我的接线实现如下图所示:

首先,我们使用Arduino IDE为Arduino UNO编写程序。我们使用SoftwareSerial模拟软串口10和11该程序将等待输入的UART数据,然后在0和1引脚上发送到Arduino UART。接下来开始写这个程序:

Arduino程序:

保存这个程序。然后,将其上传到Arduino板。在上传之前,请确保Arduino UART(数字0,1,10和11引脚)不能连接到任何电路或传感器。下一步是为NodeMCU板编写程序。创建一个名为uartdemopy的文件。开始编写程序:

Nodemcu程序:

现在您可以通过WebREPL上传和运行MicroPython程序。完成后,将NodeMCU UART连接到Arduino UART(数字引脚:10和11)。要查看UART输出,请从Arduino IDE打开串行监视器工具。设置波特9600您应该看到UART输出:

以下是WebREPL上的程序输出:

摘 要:UART是广泛使用的串行数据通讯电路。本设计包含UART发送器、接收器和波特率发生器。设计应用EDA技术,基于FPGA/CPLD器件设计与实现UART。

关键词:FPGA/CPLD;UART;VHDL

---UART(即Universal Asynchronous Receiver Transmitter 通用异步收发器)是广泛使用的串行数据传输协议。UART允许在串行链路上进行全双工的通信。

---串行外设用到RS232-C异步串行接口,一般采用专用的集成电路即UART实现。如8250、8251、NS16450等芯片都是常见的UART器件,这类芯片已经相当复杂,有的含有许多辅助的模块(如FIFO),有时我们不需要使用完整的UART的功能和这些辅助功能。或者设计上用到了FPGA/CPLD器件,那么我们就可以将所需要的UART功能集成到FPGA内部。使用VHDL将UART的核心功能集成,从而使整个设计更加紧凑、稳定且可靠。本文应用EDA技术,基于FPGA/CPLD器件设计与实现UART。

一 UART简介

1 UART结构

---UART主要有由数据总线接口、控制逻辑、波特率发生器、发送部分和接收部分等组成。

---功能包括微处理器接口,发送缓冲器(tbr)、发送移位寄存器(tsr)、帧产生、奇偶校验、并转串、数据接收缓冲器(rbr)、接收移位寄存器(rsr)、帧产生、奇偶校验、串转并。

---图1是UART的典型应用。

2 UART的帧格式

---UART的帧格式如图2所示。

---包括线路空闲状态(idle,高电平)、起始位(start bit,低电平)、5~8位数据位(data bits)、校验位(parity bit,可选)和停止位(stop bit,位数可为1、15、2位)。

---这种格式是由起始位和停止位来实现字符的同步。

---UART内部一般有配置寄存器,可以配置数据位数(5~8位)、是否有校验位和校验的类型、停止位的位数(1,15,2)等设置。

二 UART的设计与实现

1 UART发送器

---发送器每隔16个CLK16时钟周期输出1位,次序遵循1位起始位、8位数据位(假定数据位为8位)、1位校验位(可选)、1位停止位。

---CPU何时可以往发送缓冲器tbr写入数据,也就是说CPU要写数据到tbr时必须判断当前是否可写,如果不判这个条件,发送的数据会出错。

---数据的发送是由微处理器控制,微处理器给出wen信号,发送器根据此信号将并行数据din[70]锁存进发送缓冲器tbr[70],并通过发送移位寄存器tsr[70]发送串行数据至串行数据输出端dout。在数据发送过程中用输出信号tre作为标志信号,当一帧数据发送完毕时,tre信号为1,通知CPU在下个时钟装入新数据。

---发送器端口信号如图3所示。

---引入发送字符长度和发送次序计数器length_no,实现的部分VHDL程序如下。

---if std_logic_vector(length_no) = “0001” then

---tsr <= tbr ; --发送缓冲器tbr数据进入发送移位寄存器tsr

---tre <= '0' ; --发送移位寄存器空标志置“0”

---elsif std_logic_vector(length_no) = “0010” then

---dout <= '0' ; --发送起始位信号“0”

---elsif std_logic_vector(length_no) >= “0011” and std_logic_vector(length_no) <= “1010” then

---tsr <= '0' & tsr(7 downto 1); --从低位到高位进行移位输出至串行输出端dout

---dout <= tsr(0) ;

---parity <= parity xor tsr(0) ; --奇偶校验

---elsif std_logic_vector(length_no) = “1011” then

---dout <= parity ; 校验位输出

---elsif std_logic_vector(length_no) = “1100” then

---dout <= '1' ; --停止位输出

---tre <= '1' ; --发送完毕标志置“1”

---end if ;

---发送器仿真波形如图4所示。

2 UART接收器

---串行数据帧和接收时钟是异步的,发送来的数据由逻辑1变为逻辑0可以视为一个数据帧的开始。接收器先要捕捉起始位,确定rxd输入由1到0,逻辑0要8个CLK16时钟周期,才是正常的起始位,然后在每隔16个CLK16时钟周期采样接收数据,移位输入接收移位寄存器rsr,最后输出数据dout。还要输出一个数据接收标志信号标志数据接收完。

---接收器的端口信号如图5所示。

---实现的部分VHDL程序如下。

---elsif clk1x'event and clk1x = '1' then

---if std_logic_vector(length_no) >= “0001” and std_logic_vector(length_no) <= “1001” then

-----数据帧数据由接收串行数据端移位入接收移位寄存器

---rsr(0) <= rxda ;

---rsr(7 downto 1) <= rsr(6 downto 0) ;

---parity <= parity xor rsr(7) ;

---elsif std_logic_vector(length_no) = “1010” then

---rbr <= rsr ; --接收移位寄存器数据进入接收缓冲器

---

---end if ;

---接收器仿真波形如图6所示。

3 波特率发生器

---UART的接收和发送是按照相同的波特率进行收发的。波特率发生器产生的时钟频率不是波特率时钟频率,而是波特率时钟频率的16倍,目的是为在接收时进行精确地采样,以提出异步的串行数据。

---根据给定的晶振时钟和要求的波特率算出波特率分频数。

---波特率发生器仿真波形如图7所示。

三 小结

---通过波特率发生器、发送器和接收器模块的设计与仿真,能较容易地实现通用异步收发器总模块,对于收发的数据帧和发生的波特率时钟频率能较灵活地改变,而且硬件实现不需要很多资源,尤其能较灵活地嵌入到FPGA/CPLD的开发中。在EDA技术平台上进行设计、仿真与实现具有较好的优越性。

以上就是关于战舰V3 USART1、USART2、UASRT3、UART4、UART5串口配置全部的内容,包括:战舰V3 USART1、USART2、UASRT3、UART4、UART5串口配置、Linux Kernel UART 收发数据,该怎么解决、IO模拟UART等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/web/9803104.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-02
下一篇 2023-05-02

发表评论

登录后才能评论

评论列表(0条)

保存