历史上的今天
返回首页

历史上的今天

今天是:2025年03月07日(星期五)

正在发生

2018年03月07日 | 典型的ATmega128的软件USART的接口程序

2018-03-07 来源:eefocus

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

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


推荐阅读

史海拾趣

COMPUTAR公司的发展小趣事

进入90年代,电动变焦镜头逐渐成为市场的新宠。CBC株式会社紧跟时代潮流,于1992年成功推出电动6倍系列镜头。这款镜头采用电动变焦设计,操作简便、速度快捷,极大地提高了拍摄效率。电动6倍系列镜头的全球上市,不仅进一步扩大了CBC的市场影响力,也为公司的未来发展奠定了坚实的基础。

通过以上五个故事,我们可以看到COMPUTAR公司(前身为CBC株式会社)在电子行业中的发展历程。从创立之初的艰苦创业,到逐步拓展国际市场;从手动变焦镜头的研制成功,到非球面高速镜头和电动6倍系列镜头的诞生与上市,每一步都凝聚着COMPUTAR人的智慧和汗水。正是这些不懈的努力和持续的创新,使得COMPUTAR在电子行业中脱颖而出,成为一家备受尊敬的企业。

Atlantic Microwave Ltd公司的发展小趣事

随着电子行业的快速发展,Atlantic Microwave Ltd公司意识到,只有不断创新才能在激烈的市场竞争中立于不败之地。公司投入大量研发资金,吸引了一批优秀的科研人才,专注于微波技术的研发与创新。经过数年的努力,公司成功推出了一款具有颠覆性的微波产品,凭借其卓越的性能和稳定性,迅速获得了市场的认可,为公司带来了可观的收益。

博众电气(BOZHONG ELECTRIC)公司的发展小趣事

博众电气始终坚信,品质是企业生存和发展的根本。因此,公司始终将品质管理放在首位,并严格执行ISO9001等国际质量管理体系标准。

为了进一步提升产品品质和管理水平,博众电气还积极申请并通过了多项国际认证。这些认证不仅证明了博众电气的产品品质和管理水平达到了国际先进水平,还为公司的国际化发展提供了有力保障。

Array Microsystems Inc公司的发展小趣事

为了支持公司的快速发展和技术创新,Array Microsystems Inc高度重视人才引进和团队建设。公司积极招聘业内优秀的技术人才和管理人才,为他们提供良好的工作环境和福利待遇。同时,公司还注重员工的培训和晋升机制,鼓励员工不断学习和成长。这些措施使得Array Microsystems Inc拥有了一支高素质、专业化的团队,为公司的发展提供了有力的人才保障。

Ememory Technology Inc公司的发展小趣事

eMemory自1989年成立以来,始终致力于半导体硅智财(IP)的研发与创新。公司凭借其独特的可编程非挥发性内存(NVM)技术,如NeoFuse和NeoPUF,迅速在半导体IP领域崭露头角。eMemory不仅将这些技术应用于自家的芯片产品中,还通过IP授权的方式,与全球众多芯片设计厂商建立了紧密的合作关系,推动了整个电子行业的发展。

Anders DX公司的发展小趣事

为了满足市场对高性能、低功耗芯片的需求,eMemory在2016年宣布向150nm高电压制程工艺扩展其可编程Neobit技术。这一技术的成功开发,使得eMemory能够在LCD驱动IC、逻辑IC和功率控制IC等高速增长的市场中占据一席之地。Neobit技术的可擦编程只读存储器特性,为芯片设计提供了更大的灵活性和可定制性。

问答坊 | AI 解惑

智能车资料下载

本帖最后由 paulhyde 于 2014-9-15 09:15 编辑 顶顶!!!  …

查看全部问答>

s3c2410触摸屏程序中对外接晶体管控制的问题

《ARM Linux入门与实践》一书当中,关于触摸屏的那一节有几个地方不理解。 该程序的说明是:“代码并没有使用S3C2410A中的触摸屏控制器,而是通过直接控制FPIO的4个晶体管的导通和截止” P220: void Wait_Touch(void) {     XMON_O ...…

查看全部问答>

dll库加载的问题

自己写了一个实现tapi的库 怎么加载到windows ce中呢? 用的编译环境是EVC…

查看全部问答>

我的最新充电原理图提交

上次提交的原理图,由于美信没有提供MAX17005B充电管理芯片,导致无法进行下去。为此,重新在美信网站溜达一圈,按照以下原则,确定该次芯片选型和原理图设计。   1。 芯片没有停产,可以继续使用,美信提供样品。   2。 封装不能是QFN ...…

查看全部问答>

关于工业以太网问题请教

组建一个简单的工业以太网,一台x86工控机当服务器,用网线联一台工业以太网交换机,交换机再连一台PLC,PLC 连接底层设备。 假设服务器上我装的就是普通的windows XP操作系统,上面运行我的工控软件。 请问我这个算是工业以太网吗?工业以太网不 ...…

查看全部问答>

请问能否仅通过430的串口往里面烧写程序?

请问能否仅通过430的串口往里面烧写程序? 谢谢! 搜了一下,有很多卖BSL的,除了需要TXD、RXD外,还需要一些别的脚。 有没有这么一种软件?当430的串口与计算机串口通过MAX232之类的芯片一接,在电脑上运行这个软件,直接就把程序烧进去了。…

查看全部问答>

LPC1114控制18B20程序

如题,我最近在学习LPC1114,照着51编写了一个LPC1114控制18b20的程序,可是怎样都不能成功,希望那个大仙能分享下自己的成功的程序,在此谢谢啦…

查看全部问答>

12864中文显示乱码!!!

是这样的,我是用串行方式写的代码,上电后发现显示中文字符会乱码。英文和数字则显示正常,不知道怎么回事 [ 本帖最后由 冷板凳 于 2012-9-25 15:50 编辑 ]…

查看全部问答>

【晒心得】TI EZ430-CHRONOS-433 无线手表

昨天收到手表,今天戴了一整天,现在说说我的体验心得。(写的比较乱,跟大家交流分享)     这么大一个联邦快递,同事都说这个快递费都要好贵,再加上整个套件不单单只有一个手表,还有个MSP-eZ430仿真器(该仿真器只支持二线仿真)和 ...…

查看全部问答>