历史上的今天
返回首页

历史上的今天

今天是:2024年09月23日(星期一)

正在发生

2019年09月23日 | UART0串口编程(二):硬件原理;轮训方式的串口编程

2019-09-23 来源:eefocus

本节针对的是ARM2200环境下编写串口程序,其中设计轮循方式,中断方式,以及在UC/OS-II操作系统下的串口编程。使用轮循和中断两种方式来实现串口编程。用中断实现串口编程,系统的效率较高,但是难度也较大 ;轮循方式效率较低,但是编程比较简单。


一.串口编程的硬件原理


1.     串口特性:


1>16字节接收FIFO和16字节发送FIFO


2>接收FIFO触发点可设置为1,4,8或14字节。


3>内置波特率发生器。


2.     UART0引脚:


1>RxD0 引脚用于UART0接受数据,接受方式为串行输入。


2>TxD0引脚用于UART0发送数据,发送方式为串行发送数据。


3.     UART0的结构和工作方式


先看图在说明:

1>  VPB总线提供CPU与UART0之间得的通信连接


(CPU内核通过VPB接口对UART0的寄存器进行读写访问.)


2>  UART0 接收器模块监视串行输入线RxD0的有效输入。UART0 接收单元的移位寄存器(U0RSR)通过RxD0接收有效的字符。当U0RSR接受到一个有效字符时,它将该字符传送到UART0 接收单元缓冲寄存器FIFO中,等待CPU通过VPB接口进行访问。


3>  UART0发送器模块接收CPU或主机写入的数据并将数据缓存到UART0 的FIFO或U0THR中,UART0发送模块中的移位寄存器(U0TSR)读取U0THR或FIFO中的数据并将数据通过串行输出到引脚TxD0发送。


4>  UART0的接收模块和发送模块的状态信息保存在U0LSR中。


控制信息保存在U0LCR中。


5>  UART0波特率发送器模块产生UART0 发送模块所使用的定时。波特率发生器模块时钟源为VPB时钟(pclk)。主时钟与U0DLL和U0DLM寄存器所定义的除数相除得到UART0 发送器模块使用的时钟,该时钟必须为波特率的16倍。


6>  中断接口包含寄存器U0IER和U0IIR。中断接口接收UART0发送模块和接收模块发出的单时钟宽度的使能信号。


4.  UART0和ARM7 CPU之间的通信过程


1>CPU通过UART0发送模块发送信息给外设


第一:CPU发出信息通过AHB总线到AHB-VPB桥


第二:通过AHB-VPB桥把信息转换后发送给VPB总线。


第三:UART0接收模块接受来自VPB总线的数据。并将数据缓存到U0THR寄存器中。


第四:UART0接受模块的移位寄存器U0TSR读取U0THR中的数据 并将数据通过输出引脚TxD0发送。


2>外设通过UART0接收模块向ARM7 CPU发送信息


第一:UART0移位寄存器(U0RSR)通过引脚RxD0接收有效字符。


第二:当UART0接收到一个有效字符后,通过读取U0RBR寄存器可以将FIFO中最早接收到的字节读出,当FIFO中不再包含有效数据时,该寄存器反映接收到的最后一个有效字节数据。接收的数据不足8位时,高位用0填充。


第三:VPB总线将缓冲寄存器(U0RBR)中的数据通过AHB-VPB桥传到AHB总线上


第四:AHB总线将数据传送给ARM7 CPU。


二.轮训方式的串口编程


1.     串口程序都有那几部分组成如下图:


1>  串口初速化


A.    串口初始化的流程


第一:设置I/O引脚连接到UART0


第二:设置串口波特率


第三:设置串口工作模式


B.     串口初始化需要设置的寄存器


第一:U0LCR(控制寄存器):设置UART0的通信格式。


第二:U0DLL,U0DLM(寄存器):设置UART0的通信波特率。


C.     具体寄存器的设置


(1) U0LCR(线控制寄存器)


第一:作用:设置通信格式(通信字符长度,停止位个数,奇偶校验位


第二:长度:8位寄存器


第三:各位寄存器的含义:


第[1 ,0]位: 表示字长


00:表示5位字长


01:表示6位字符长度


10:表示7位字符长度


11:表示8位字符长度


第2位: 表示停止位选择


0:1个停止位


1:2个停止位


3位:表示奇偶使能


0:禁止奇偶产生和校验


1:使能奇偶产生和校验


注:奇偶使能:控制是否进行奇偶校验。如果使能,发送时将添加一位校验位。


第[5 4]位:表示奇偶选择位


  00:奇数(数据位+校验位=奇数)


  01:偶数(数据位+校验位=偶数)


 10:校验位强制为1


11:校验位强制为0


注:奇偶选择主要是设置奇偶校验类型。


第6位:间隔控制


 0:禁止间隔发送


 1:使能间隔发送


注:当该位为1时,输出引脚(TxD0)强制为逻辑0,可以引起通信对方产生间隔中断。在一些通信方式中,使用间隔中断作为通信的起始信号(eg:LIN Bus)      


 第7位:除数锁存访问位


 0:禁止访问除数锁存寄存器


 1:始能访问除数锁存寄存器

(2) U0DLL,U0DLM(除数锁存寄存器)


第一:作用:U0DLL和U0DLM寄存器一起构成一个16位除数。


第三:U0DLL和U0DLM都为8位寄存器。


第四:U0DLL:存放分频值的低8位


第五:U0DLM:存放分频值的高8位。


注意:


(1)使用U0DLL和U0DLM配置波特率之前,必须先计算分频值。


Fdiv=Fpclk/(16*baud)


(2)使用U0DLL和U0DLM配置波特率之前必须把U0LCR控制寄存器的第8位置为1才能进行配置。配置完后要把U0LCR控制寄存器的第8位置位0。



2.串口接收数据


用轮循方式接收数据


1>CPU通过串口接收数据时各个寄存器之间的关系


2>串口接受数据的流程:


第一:循环检测U0RBR是否有未读取的数据。


第二:如果有数据到来,则接收数据。


3>相关寄存器配置


(1) U0LSR(线状态寄存器)


第一:作用,只读寄存器,它提供UART0发送和接收模块的状态信息。


第二:长度:8位寄存器。


第三:各位寄存器的含义:


A.0位:表示接收数据就绪


置0表示U0RBR为空


置1表示U0RBR包含有效数据


注:当U0RBR包含未读的字符时,第0位被置位;当UART0的U0RBR或FIFO为空时,第0位置零。


B.第1位:溢出错误。


置0:溢出错误状态未激活


置1:溢出错误状态激活


注:溢出错误条件在错误发生后立即设置。对U0LSR读操作将清零第1位。当UART0的RSR已经有新的字符就绪,而UART0  RBR或FIFO已满时,第一位置1.此时的UART0 RBR或FIFO不会被覆盖,UART0 的RSR中的字符将丢失。


C.第2位:奇偶错误。


置0:奇偶错误状态未激活


置1:奇偶错误状态激活


注:当接收字符的奇偶位处于错误状态时产生一个奇偶错误。对U0LSR读操作清零该位。奇偶错误检测时间取决于U0FCR的bit0。奇偶错误与UART0 的RBR,FIFO中读出的字符相关。


D.第3位:帧错误


置0:帧错误状态未激活。


置1:帧错误状态激活


 注: 当接收字符的停止位为0时,产生帧错误。对读操作U0LSR清零该位。帧错误检测时间取决于U0FCR的bit0。帧错误与UART0的RBR,FIFO中读出的字符相关。当检测到一个帧错误时,Rx将尝试与数据重新同步并假设错误的停止位实际是一个超前的起始位。但即使没有出现帧错误,它也不能假设下一个接收到的字节是正确的。


E.第四位:间隔中断


置0:间隔中断状态未激活


置1:间隔中断状态状态激活


注: 在发送整个字符(起始位,数据,奇偶位和停止位)过程中RXD0如果都保持逻辑0,则产生间隔中断。当检测到中断条件时,接收器立即进入空闲状态直到RXD0变为全1状态。读操作U0LSR清零该状态位。 间隔检测的时间取决于U0FCR的bit0。间隔中断与UART0的RBR或FIFO中读出的字符相关。


F.第五位:发送保持寄存器空


置0:表示U0THR包含有效数据


置1:表示U0THR空


注:当检测到UART0 的THR空时,THRE置位。对U0THR写操作清零该位。


G.第6位:表示发送器空


置0:U0THR和或U0TSR包含有效数据。


置1:U0THR和U0TSR空


注:当U0THR和U0TSR都为空时,该位置1,当U0TSR或U0THR包含有效数据时,该位清零。


H第7位:表示Rx FIFO 错误。


置0:U0RBR中没有UART0 Rx错误,或U0FCR的bit为0.


置1:U0RBR包含至少一个UART0 Rx错误。


注: 当一个带有Rx错误(例如帧错误,奇偶错误或间隔中断)的字符装入U0RBR时,该位置1。 当读取U0LSR寄存器并且UART0的FIFO中不再有错误时,该位置零。


(2) U0RBR(接收器缓冲寄存器)


第一:作用,只读寄存器,是UART0 Rx FIFO的最高字节。它包含了最早接收到的字符,可通过总线接口读出。串口接收数据时低位在先,即U0RBR的bit0为最早接收到的数据位。如果接收到的数据小于8位,未使用的MSB填充为0.


第二:长度:8位寄存器。


 


3.串口发送数据


1>  用CPU通过串口发送数据时,各寄存器之间的关系


2>  串口发送数据时的流程


第一:将要发送的一字节数据写入U0THR


第二:等待数据发送完毕


3>  相关寄存器配置


(1)U0THR(发送保持寄存器)


第一:最用:只写寄存器。U0THR是UART0 Tx FIFO的最高字节。它包含了Tx FIFO 中最新的字符,可通过总线接口写入。串口发送数据时,低位在先,bit0代表最先发送的位。


长度:8位寄存器


(2)U0LSR(线状态寄存器)


在上面已经介绍,在此步再涉及。


 4.下面是完整的程序:用轮训方式实现接收上位机数据,并把数据再发送给上位机。


(通过上位机给串口发送8字节数据,ARM2200接收到串口数据后,把数据又发送回上位机)



/******************************************************************************

** Modified by:         TIGER0-JOHN

** Modified date:       2011-1-21

** Version:             1.1  

** Descriptions:        测试成功 ,在上面上发送16进制数时,每个之间用空格隔开

不加前缀

****************************************************************************/

 

#include "config.h"

 

/****************************************************************************

* 名    称: DelayNS()

* 功    能: 长软件延时

* 入口参数: dly 延时参数,值越大,延时越久

* 出口参数: 无

****************************************************************************/

void  DelayNS(uint32  dly)

{  

    uint32  i;

    

    for(; dly>0; dly--) 

    {

        for(i=0; i<5000; i++);

    }

 

}

/**********************************************************

* 名称: UART0_Init()

* 功能: UART0初始化(通讯波特率115200,8位数据位,

1位停止位,无奇偶校验)

* 入口参数: bps     串口波特率

* 出口参数: 无

**********************************************************/

void  UART0_Init(uint32 bps)

{  

    uint16 Fdiv;

    PINSEL0 = 0x00000005;               //设置串口引脚

    U0LCR = 0x83; //置为除数锁存位,进行配置

    Fdiv = (Fpclk >> 4) / bps;     // 设置波特率

    U0DLM = Fdiv >> 8;

    U0DLL = Fdiv & 0xff;

    U0LCR = 0x03;                      //清除除数锁存位,并设置工作模式

 

}

 

/**********************************************************

* 名    称:            UART0_RcvByte

* 功    能:            用查询方式接收一字节的数据

* 入口参数:            无

* 出口参数:            data              要接收的数据

**********************************************************/

uint8   UART0_RcvByte(void)

{

uint8 rcv_data ;

while((U0LSR&0X01)==0);         //等待数据到达

    rcv_data = U0RBR;               //从U0RBR中读出接收到的数据

    return  rcv_data;               //返回接收到的数据

 

}

/**********************************************************

* 名    称:            UART0_SendByte

* 功    能:            向串口发送字节数据,并等待发送完毕。

* 入口参数:            data              要发送的数据

* 出口参数:            无

**********************************************************/

void   UART0_SendByte(uint8 data)

{

U0THR = data;                 

while(0 == (U0LSR & 0x40));

}

/**********************************************************

* 名称: UART0_RecBuf()

* 功能: 接收串口发送过来的帧数据,

* 入口参数: *buffer  存放一帧数据

* 出口参数: 无

**********************************************************/

void UART0_RecBuf (uint8 *buffer)

{

uint8 *pbuffer;

    uint8  i;

for(pbuffer = buffer, i = 0;i < 8; i++)

{

*(pbuffer++) = UART0_RcvByte();

}

}

/**********************************************************

* 名称: UART0_SendBuf()

* 功能: 通过串口发送一帧数据

* 入口参数: *buffer  存放一帧数据

* 出口参数: 无

**********************************************************/

void UART0_SendBuf(uint8 *buffer)

{

uint8 *pbuffer;

    uint8 i;

for(pbuffer = buffer,i=0;i < 8; i++)

UART0_SendByte(*(pbuffer++));

}

 

int main (void)

    uint8 recver_buffer[8];                                           //定义接收帧缓冲区

    uint8 send_buffer[8] ={0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27};  //定义发送帧缓冲区

    UART0_Init(115200);

    while(1)

    {

      UART0_RecBuf(recver_buffer);   

      DelayNS(10);

     if(0x10 ==recver_buffer[0] && 0x11 == recver_buffer[1])

     UART0_SendBuf(recver_buffer);

     else

     UART0_SendBuf(send_buffer);

     }    

     return 0;

}


推荐阅读

史海拾趣

埃派克森微电子(Apexone)公司的发展小趣事

在埃派克森微电子的发展过程中,著名投资机构多尔基金和华登国际的风险投资起到了重要的推动作用。这些投资不仅为公司提供了资金支持,还带来了宝贵的市场资源和管理经验。借助这些资源,埃派克森加快了国际化步伐,积极拓展海外市场,与全球范围内的客户和合作伙伴建立了紧密的合作关系。

Flamar公司的发展小趣事

随着电子行业的全球化趋势日益明显,Flamar公司积极实施国际化战略,通过设立海外研发中心、生产基地和销售网络,不断拓展全球市场。公司先后在欧洲、亚洲等地建立分支机构,与当地企业建立紧密的合作关系,共同推动电子技术的创新与应用。通过国际市场的开拓,Flamar公司不仅实现了业务规模的快速增长,还进一步提升了品牌的国际知名度和影响力。

Fukushima Futaba Electric Co Ltd公司的发展小趣事

近年来,全球电子行业面临着诸多挑战,包括技术更新换代迅速、市场竞争加剧等。Futaba Electric积极应对这些挑战,不断加大研发投入,推出了一系列具有创新性和竞争力的新产品。同时,公司还注重与上下游产业链的合作与协同,通过整合资源、优化流程等方式降低成本、提高效率。此外,Futaba Electric还积极响应环保政策,推动绿色制造和可持续发展。这些努力使得公司在面对挑战时依然能够保持稳健的发展态势。

CWIND公司的发展小趣事

CWIND公司非常重视人才培养和团队建设。公司建立了完善的培训体系,为新员工提供全面的职业技能培训;同时,公司还鼓励员工参与各种技术交流和培训活动,提升自身的技术水平。在团队建设方面,CWIND注重营造积极向上的工作氛围和团队合作精神。通过定期举办团队建设活动和员工表彰大会等方式,公司成功打造了一支高效、协作、创新的团队。

Denyo Europa Gmbh公司的发展小趣事

Denyo Europa Gmbh公司一直将产品质量视为企业的生命线。公司建立了严格的质量管理体系,从原材料采购到生产流程,再到产品检测,每一个环节都严格把关。公司还定期对员工进行质量意识培训,确保每一个员工都能深刻理解质量对于企业发展的重要性。这种对质量的执着追求,使公司的产品在市场上赢得了良好的口碑。

富捷(FOJAN)公司的发展小趣事

富捷电子在积极拓展国内外市场的同时,也注重品牌建设和市场推广。公司建立了遍及全球的销售网络,产品广泛应用于微电子、计算机、光伏、新能源、车载等众多新兴和高科技领域。通过参加国内外知名展会、举办技术交流会等方式,富捷电子不断提升品牌知名度和影响力。此外,公司还积极与上下游企业建立战略合作关系,共同推动产业链协同发展。

问答坊 | AI 解惑

一种数字集成电路测试系统的设计

摘要:介绍了一种数字集成电路测试系统的工作原理、组成。提出了系统的软硬件设计方案。该系统基于自定义总线结构,可测试电平范围宽。   关键词:数字集成电路 测试功能 测试通道板 精密测量单元   随着数字集成电路的广泛应用,测试系统就显 ...…

查看全部问答>

USB HID with the LPC1300 on-chip driver

USB HID with the LPC1300 on-chip driver 英文资料,来自于NXP官方网站,http://www.nxp.com.…

查看全部问答>

建议:坛里面组织LM3S8962开发板的朋友,对TI的驱动程序仔细研读

分配有开发板的朋友,每月提交一篇关于LM3S8962的使用心得。其实最好还是,像周立功那样,对所有的驱动程序进行分析验证,最后形成使用习惯,分享给广大学习者。这个任务很重,建议统一论坛组织,是一个长期的工作。这工作做好了,以后利用LM3S系列 ...…

查看全部问答>

頂一下我的編程網吧

頂一下我的編程網吧 www.kingofcoders.com…

查看全部问答>

嵌入式linux不能启动

今天作试验,开发板用的是北京革新科技的2410ep,里面装的有linux,用windows的超级终端控制。正常情况下,将sw4拨在intel那边,sw1为nor,启动后会有mizilinux的图标,控制台里有#提示符。今天开启实验板后,选择启动linux出现 、 、 uncompres ...…

查看全部问答>

渥瑞达“3G移动开发”免费试听课于北京交通大学举行,欢迎大家光临!

渥瑞达“3G移动开发”免费试听课于北京交通大学举行,欢迎大家光临! 渥瑞达“3G移动开发”免费试听课于北京交通大学举行,欢迎大家光临! 详情请参见 www.neworigin.net 同时欢迎大家与我们的609期学员交流!这期学员已与2月11日毕业 ...…

查看全部问答>

安装ADS_1.2时的问题?

当我安装ADS_1.2时有个界面让我输入“the temporary license key”我没有找到,不知从哪里找。我已发那封邮件,可是没有给我回。谢谢!…

查看全部问答>

电容三点式震荡电路『紧急求教』

这个震荡电路,一直调不出波形。不知道什么有什么错误之处。以前一样的电路调出过。不知道现在怎么出不来了。请大家帮忙看看。谢谢1…

查看全部问答>

CCS加载中的一些问题的讨论

本帖最后由 dontium 于 2015-1-23 13:34 编辑 你好,我自己开发了一块6711的板子,我在用CCS LOAD PROGRAM 时候总是LOAD不进去,错误提示为: “FILE hello.out does not match the target endianness,not loaded.Check build options,or use th ...…

查看全部问答>