当前位置:首页 > 单片机 > 单片机
[导读] 一般教科书上提供的UART收发的程序往往是一段采用轮循(Polling)方式完成收发的简单代码。但对于高速的AVR来讲,采用这种方式大大降低了 MUC的效率。在使用AVR时,应根据芯片本身的特点(片内大容量数据存

一般教科书上提供的UART收发的程序往往是一段采用轮循(Polling)方式完成收发的简单代码。但对于高速的AVR来讲,采用这种方式大大降低了 MUC的效率。在使用AVR时,应根据芯片本身的特点(片内大容量数据存储器RAM,更适合采用高级语言编写系统程序),编写高效可靠的UART收发接口(低层)程序。下面是一个典型的ATmega128软件USART接口程序

#include

#define RXB8 1

#define TXB8 0

#define UPE 2

#define OVR 3

#define FE 4

#define UDRE 5

#define RXC 7

#define FRAMING_ERROR (1<

#define PARITY_ERROR (1<

#define DATA_OVERRUN (1<

#define DATA_REGISTER_EMPTY (1<

#define RX_COMPLEte (1<

// USART0 Receiver buffer

#define RX_BUFFER_SIZE0 8

char rx_buffer0[RX_BUFFER_SIZE0];

unsigned char rx_wr_index0,rx_rd_index0,rx_counter0;

// This flag is set ON USART0 Receiver buffer overflow

bit rx_buffer_overflow0;

// USART0 Receiver interrupt servICe routine

#pragma savereg-

interrupt [USART0_RXC] void uart0_rx_isr(void)

{

char status,data;

#asm

push r26

push r27

push r30

push r31

in r26,sreg

push r26

#endasm

status=UCSR0A;

data=UDR0;

if ((status & (FRAMING_ERROR | PARITY_ERROR | DATA_OVERRUN))==0)

{

rx_buffer0[rx_wr_index0]=data;

if (++rx_wr_index0 == RX_BUFFER_SIZE0) rx_wr_index0=0;

if (++rx_counter0 == RX_BUFFER_SIZE0)

{

rx_counter0=0;

rx_buffer_overflow0=1;

};

};

#asm

pop r26

out sreg,r26

pop r31

pop r30

pop r27

pop r26

#endasm

}

#pragma savereg+

#ifndef _DEBUG_TERMINAL_IO_

// Get a character from the USART0 Receiver buffer

#define _ALTERNATE_GETCHAR_

#pragma used+

char getchar(void)

{

char data;

while (rx_counter0==0);

data=rx_buffer0[rx_rd_index0];

if (++rx_rd_index0 == RX_BUFFER_SIZE0) rx_rd_index0=0;

#asm("cli")

--rx_counter0;

#asm("sei")

return data;

}

#pragma used-

#endif

// USART0 Transmitter buffer

#define TX_BUFFER_SIZE0 8

char tx_buffer0[TX_BUFFER_SIZE0];

unsigned char tx_wr_index0,tx_rd_index0,tx_counter0;

// USART0 Transmitter interrupt service routine

#pragma savereg-

interrupt [USART0_TXC] void uart0_tx_isr(void)

{

#asm

push r26

push r27

push r30

push r31

in r26,sreg

push r26

#EDAsm

if (tx_counter0)

{

--tx_counter0;

UDR0=tx_buffer0[tx_rd_index0];

if (++tx_rd_index0 == TX_BUFFER_SIZE0) tx_rd_index0=0;

};

#asm

pop r26

out sreg,r26

pop r31

pop r30

pop r27

pop r26

#endasm

}

#pragma savereg+

#ifndef _DEBUG_TERMINAL_IO_

// Write a character to the USART0 Transmitter buffer

#define _ALTERNATE_PUTCHAR_

#pragma used+

void putchar(char c)

{

while (tx_counter0 == TX_BUFFER_SIZE0);

#asm("cli")

if (tx_counter0 || ((UCSR0A & DATA_REGISTER_EMPTY)==0))

{

tx_buffer0[tx_wr_index0]=c;

if (++tx_wr_index0 == TX_BUFFER_SIZE0) tx_wr_index0=0;

++tx_counter0;

}

else

UDR0=c;

#asm("sei")

}

#pragma used-

#endif

// Standard Input/Output functions

#include

// Declare your global variables here

void main(void)

{

// USART0 initialization

// Communication Parameters: 8 Data, 1 Stop, No Parity

// USART0 Receiver: On

// USART0 Transmitter: On

// USART0 Mode: Asynchronous

// USART0 Baud rate: 9600

UCSR0A=0x00;

UCSR0B=0xD8;

UCSR0C=0x06;

UBRR0H=0x00;

UBRR0L=0x67;

// Global enable interrupts

#asm("sei")

while (1)

{

// Place your code here

};

}

这段由CVAVR程序生成器产生的UART接口代码是一个非常好的、高效可靠,并且值得认真学习和体会的。其特点如下:

l. 它采用两个8字节的接收和发送缓冲器来提高MCU的效率,如当主程序调用Putchar()发送数据时,如果UART口不空闲,就将数据放入发送缓冲器中,MCU不必等待,可以继续执行其它的工作。而UART的硬件发送完一个数据后,产生中断,由中断服务程序负责将发送缓冲器中数据依次送出。

2.数据缓冲器结构是一个线性的循环队列,由读、写和队列计数器3个指针控制,用于判断队列是否空、溢出,以及当前数据在队列中的位置。

3. 用编译控制命令#pragma savereg-和#pragma savereg+,使得由CVAVR在生成的中断服务程序中不进行中断保护(CVAVR生成中断保护会将比较多的寄存器压入堆栈中),而在中断中嵌入汇编,只将5个在本中断中必须要保护的寄存器压栈。这样提高了UART中断处理的速度,也意味着提高了MCU的效率。

4.由于在接口程序Putchar()、Getchar()和中断服务程序中都要对数据缓冲器的读、写和队列计数器3个指针判断和操作,为了防止冲突,在Putchar()、Getchar()中对3个指针操作时临时将中断关闭,提高了程序的可靠性。

建议读者能逐字逐句地仔细分析该段代码,真正理解和领会每一句语句(包括编译控制命令的作用)的作用,从中体会和学习如何编写效率高,可靠性好,结构优良的系统代码。这段程序使用的方法和技巧,对编写SPI、I2C的串行通信接口程序都是非常好的借鉴。

作为现在的单片机和嵌入式系统的工程师,不仅要深入全面的掌握芯片和各种器件的性能,具备丰富的硬件设计能力;同时也必须提高软件的设计能力。要学习和掌握有关数据结构、操作系统、软件工程、网络协议等方面的知识,具有设计编写大的复杂系统程序的能力。


本站声明: 本文章由作者或相关机构授权发布,目的在于传递更多信息,并不代表本站赞同其观点,本站亦不保证或承诺内容真实性等。需要转载请联系该专栏作者,如若文章内容侵犯您的权益,请及时联系本站删除。
换一批
延伸阅读

上海2024年4月22日 /美通社/ -- 恶性的攻击和意外事件总是防不胜防,提前部署灾备方案可以在遭遇意外时尽可能减少企业损失。那么面对无处不在的勒索病毒和潜在风险,为什么依然有很多企业还会遭遇数据丢失?

关键字: 勒索病毒 软件 电脑 群晖数据

SAP(思爱普)近日发出的裁员计划,不仅涉及全球范围内约8000个职位,更是在中国区造成了近1500名正式员工和合同工不续的情况。

关键字: 软件 互联网

上海2024年4月17日 /美通社/ -- 每年4月17日是世界血友病日。今年,世界血友病日以"认识出血性疾病,积极预防和治疗"为主题,呼吁关注所有出血性疾病,提升科学认知,提高规范化诊疗水平,让每一位出血性疾病患者享有...

关键字: VII 动力学 软件 BSP

德国埃朗根2024年4月16日 /美通社/ -- Elektrobit 今日宣布推出 EB zoneo GatewayCore——首款支持、配置和集成现代微控制器新一代硬件加速器的软件产品,可应用于先进的汽车电子/电气架...

关键字: 汽车 软件 硬件加速 通信网络

随着科技的飞速发展,电子产品在我们日常生活中扮演着越来越重要的角色。而在这些电子产品中,接口作为连接设备与外部设备的桥梁,其重要性不言而喻。其中,Type-C接口作为一种新型的接口标准,因其独特的优势,逐渐成为了众多电子...

关键字: 电子产品 Type-C 接口

Windows Embedded Compact 7(简称WinCE)是一种专为嵌入式系统设计的操作系统,具有体积小、效率高、可定制性强的特点。在WinCE中设置自动运行软件,通常是为了满足设备在启动后自动执行特定任务的...

关键字: 嵌入式系统 软件 操作系统

业内消息,日前欧洲软件巨头SAP宣布了一项重组计划推动人工智能增长,该计划将涉及大约8000名员工的岗位调整,这些员工将被纳入自愿休假计划和内部再培训措施,即鼓励员工自愿离职或进行内部转岗。

关键字: AI 重组 软件 裁员 SAP

业内消息,国家工信部近日公布了今年前三季度我国软件和信息技术服务业的具体情况,整体运行态势平稳,软件业务收入两位数增长,利润总额保持较快增长,软件业务出口降幅收窄。

关键字: 工信部 软件

随着电动汽车的普及,充电桩作为电动汽车的重要基础设施,越来越受到人们的关注。然而,对于许多电动汽车用户来说,直流充电桩和交流充电桩的接口和区别仍然是一个令人困惑的问题。本文将从接口和区别两个方面,详细探讨直流充电桩和交流...

关键字: 电动汽车 接口 充电桩

嵌入式系统是一种特殊的计算机系统,它被嵌入到其他设备中,以完成特定的任务。嵌入式系统的结构组成是由硬件和软件两部器、输入输出设备和总线等组件,而软件部分则包括操作系统、应用程序和驱动程序等。

关键字: 嵌入式 计算机 软件
关闭
关闭