位置:51电子网 » 技术资料 » 单 片 机

用于ATmega128的软件UART范例程序

发布时间:2008/8/18 0:00:00 访问次数:1958

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

#include <mega128.h>

#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<<fe)
#define parity_error (1<<upe)
#define data_overrun (1<<ovr)
#define data_register_empty (1<<udre)
#define rx_complete (1<<rxc)

// 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
inr26,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
popr26
outsreg,r26
popr31
popr30
popr27
popr26
#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
inr26,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
popr26
outsreg,r26
popr31
popr30
popr27
popr26
#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 <stdio.h>

// 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的硬件发送完一个数据后,产生中断,由中断服务程序负责将发送缓冲器中数据依次送

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

#include <mega128.h>

#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<<fe)
#define parity_error (1<<upe)
#define data_overrun (1<<ovr)
#define data_register_empty (1<<udre)
#define rx_complete (1<<rxc)

// 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
inr26,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
popr26
outsreg,r26
popr31
popr30
popr27
popr26
#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
inr26,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
popr26
outsreg,r26
popr31
popr30
popr27
popr26
#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 <stdio.h>

// 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的硬件发送完一个数据后,产生中断,由中断服务程序负责将发送缓冲器中数据依次送

相关IC型号

热门点击

 

推荐技术资料

硬盘式MP3播放器终级改
    一次偶然的机会我结识了NE0 2511,那是一个远方的... [详细]
版权所有:51dzw.COM
深圳服务热线:13751165337  13692101218
粤ICP备09112631号-6(miitbeian.gov.cn)
公网安备44030402000607
深圳市碧威特网络技术有限公司
付款方式


 复制成功!