典型的ATmega128的软件USART的接口程序

发布者:Qilin520最新更新时间:2018-03-07 来源: eefocus关键字:ATmega128  软件USART  接口程序 手机看文章 扫描二维码
随时随地手机看文章

一般教科书上提供的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的串行通信接口程序都是非常好的借鉴。

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


关键字:ATmega128  软件USART  接口程序 引用地址:典型的ATmega128的软件USART的接口程序

上一篇:用软件实现DAA的方法
下一篇:ATmega128系统模块,设计一个数控雕刻机系统

推荐阅读最新更新时间:2024-03-16 15:56

基于ATmega128的无线数据采集系统设计
电力日益市场化的环境下,电力公司必须提高服务质量以保持竞争力。当前我国的一些地区,配网自动化程度低,人员工作效率低。根据这种需求,设计了无线数传系统.整个无线数据通信系统是基于RS-485串口通信的一点对多点网络结构。数传电台每站点设一部,分别连接主站的数据采集工作站和分站的RTU/FTU等,进行轮询通信。各分站作业数据上报以及数采工作站的控制指令下行传输都通过无线方式完成。 1 设计思想 数据采集单元采用先进的ATmega128嵌入式单片机作为核心部件,利用RS-485通信接口与控制系统通信。测量站主要是将捕捉的现场信号经转换器ADC采样、量化、编码后,变成数字信号传给微处理器,接收遥控指令并发送数据;主控站的主要工作
[单片机]
基于<font color='red'>ATmega128</font>的无线数据采集系统设计
SPI串行接口AD转换器TLC2543的驱动程序
SPI串行接口AD转换器TLC2543的驱动程序 //-----------------------函数声明,变量定义-------------------------------------------------------- #include reg51.h #include intrins.h //-------------------------------------------------------------------------------------------------- // 2543控制引脚宏定义 //-------------------------------------------
[单片机]
TMS320VC5410的McBSP串行接口技术与程序设计
    摘要: 介绍TMS320VC5410的多功能串行接口(McBSP),并结合McBSP与高精度,高速率串行数据转换器MAX5410之间的串行通信,从硬件和软件两个方面具体讨论McBSP的设计方法。     关键词: DSP McBSP SPI 模数转换器 一、DSP的串行接口技术 当今,嵌入式系统正迅速向低功耗、低成本、小体积、高性能、高速率方向发展。随着串行接口技术的不断成熟,逐步达到了以上设计要求,成为重要的接口方案。尤其在数字信号处理器方面,串行口的重要性体现得更加突出,几乎所有的数字信号处理器都提供了一个或多个串行接口,并且随着数字信号处理器的更新换代,其相应的串行接口,在功能上不断强化,
[应用]
ATmega128实现工业设备的主控制板
使用ATmega128实现一个工业设备的主控制板,它与由ATmega8管理的按键和 LED 显示构成的控制面板距离在2米左右,两者之间采用 USART通信联系。考虑到在实际应用中,俩者之间交换的数据很少,通信速度也不需要很高,重要的是保证通信的可靠和抗干扰,因此在硬件设计上采用电流环的连接方式,见图5.4。 在图中通信双方采用光隔和三极管,将USART的电平变化变成电流变化后传送连接,如同工业上使用的20mA电流环通信一样,大大提高了通信的抗干扰能力。 通信协议和规程的制定: l.通信速率采用2400bps(速率太高时电流环的变化会跟不上)。 2. 用户数据包采用定长格式,每个数据包长度为6个字节,其中第1个字
[单片机]
ATmega128 time1溢出中断。定时器1在该模式下用法和51的一样
#include iom128v.h #define uchar unsigned char #define uint unsigned int #pragma interrupt_handler timer1:15/*定时器溢出中断向量标号*/ uchar t=0; void timer1() { TCNT1H=(65536-50000)/256; TCNT1L=(65536-50000)%256; t++; if(t==20) { t=0; PORTA=~PORTA; PORTA|=0xfe; } } void IO_init() { DDRA=
[单片机]
基于ATmega128的家庭报警系统设计与实现
引言   随着电子技术的发展,防盗报警系统已从原来的简单化、局部化向智能化、集成化发展。目前市场上常见的防盗报警系统的通信方式有固定电话拨号、宽带网等。但是,利用固定电话拨号实现的报警器易遭受破坏并存在处于通话状态时可能无法报警的隐患。而宽带网同样面临着线路被切断的隐患,且不易普及。   本文提出了一种借助可靠、成熟的GSM移动网络,以最直观的中文短消息或电话形式实现远程报警和监控的智能家居报警系统,来实现家居环境的安全监控。它采用红外传感器进行检测,并配备烟雾传感器和燃气泄漏传感器,可实现防火、防燃气泄漏的作用。带有GSM网络功能的安防系统,使用户无论身在何处,都可以通过短信设防、撤防或查询安防系统的情况。 系统的构成及
[安防电子]
基于<font color='red'>ATmega128</font>的家庭报警系统设计与实现
AVR单片机Atmega128外扩RAM
由于AVR系列单片机采用的是内部外部RAM统一编址,ATmega128工作在非ATmega 103模式时具有4k+256B的包括寄存器文件(通用工作寄存器)、I/O寄存器、扩展I/O寄存器和内部SRAM的连续内部存储空间。所以在扩展外部RAM时,和内部SRAM地址重叠的外部RAM地址是不能直接访问的。也就是说扩展的外部RAM每64k要浪费掉内部SRAM那么大的空间(AT90系列如此)。所幸的是mega系列解决了这一缺点,专门有一个寄存器XMCRB用来解决对与内部SRAM地址空间相同地址的外部RAM访问。其低三位XMM2 、XMM1 、XMM0三位的设置,决定高位地址线PC口的哪些口线被释放为普通I/O,而不是作为高位地址。这
[单片机]
AVR单片机<font color='red'>Atmega128</font>外扩RAM
ATmega128 ALU
ATmega128 ALU 与32 个通用工作寄存器直接相连。寄存器与寄存器之间、寄存器与立即数之间 的ALU 运算只需要一个时钟周期。ALU 操作分为3 类:算术、逻辑和位操作。此外还提 供了支持无/ 有符号数和分数乘法的乘法器。具体请参见指令集。
[单片机]
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved