Full Version : 8515 Half-Duplex Interrupt Driven UART (ASM)
avr >>ASSMBLER ROUTINES >>8515 Half-Duplex Interrupt Driven UART (ASM)


Admin5- 04-19-2006
Stelios Koroneos Half-Duplex Interrupt Driven Software UART for the 8515
a correction to Atmel AVR AppNote #305

CODE

;**** A P P L I C A T I O N   N O T E   A V R 3 0 5-85 ************************
;*
;* Title        : Half Duplex Interrupt Driven Software UART
;* Version      : 1.00
;* Last update      : 98.11.12
;* Update Author        : Stelios Koroneos
;* Target       : 90s8515
;*
;* Support email    : avr@atmel.com
;* Author's e-mail      : skoron@netor.gr
;*
;* Code Size        : 57 Words
;* Low Register Usage   : 0
;* High Register Usage  : 4
;* Interrupt Usage  : None
;*
;* This is a modification of the original application note 305.
;* By minor modifications it can work on all AVR's with RAM
;* Modification were made from the original AVR305 so it will
;* run on 90s8515
;* By modyfing the Interrupt jump table it can be used on all
;* the AVR family except 90s1200
;*
;* DESCRIPTION
;* This Application note contains a very code efficient software UART.
;* The example program receives one character and echoes it back.
;***************************************************************************

.include "8515def.inc"

;***** Pin definitions

.equ    RxD =0        ;Receive pin is PD0
.equ    TxD =1        ;Transmit pin is PD1

;***** Global register variables

.def    bitcnt  =R16          ;bit counter
.def    temp    =R17          ;temporary storage register

.def    Txbyte  =R18          ;Data to be transmitted
.def    RXbyte  =R19          ;Received data


.cseg
.org 0
;*INTERRUPT JUMP TABLE
;*Modify for other AVR's

       rjmp   reset
       reti        ;IRQ0 handle
       reti        ;IRQ1 handle
       reti        ;Timer1 capture handle
       reti        ;Timer1 compA  
       reti        ;Timer1 compB
       reti        ;Timer1 overflow
       reti        ;Timer0 overflow
       reti        ;SPI
       reti        ;UART RX complete
       reti        ;UART UDR Empty
       reti        ;UART TX complete
       reti        ;Analog comp

reset:  
     ;We need to init the stack pointer for all parts except 90s1200
     ;Without SP we can not jump or call a subroutine
     ;Manual 5-24

             ldi     TEMP,low(RamEnd)      ;
             out     SPL,TEMP              ;init Stack Pointer Low    
             ldi     temp,high(RamEnd)      ;
             out     SPL+1,TEMP            ;init Stack Pointer High

;*********************************************************************
;***** Program Execution Starts Here

;***** Test program

               sbi PORTD,TxD  ;Init port pins
           sbi DDRD,TxD

       ldi Txbyte,12  ;Clear terminal
       rcall   putchar

forever:    rcall   getchar
       mov Txbyte,Rxbyte
       rcall   putchar    ;Echo received char
       rjmp    forever


;***************************************************************************
;*
;* "putchar"
;*
;* This subroutine transmits the byte stored in the "Txbyte" register
;* The number of stop bits used is set with the sb constant
;*
;* Number of words  :14 including return
;* Number of cycles :Depens on bit rate
;* Low registers used   :None
;* High registers used  :2 (bitcnt,Txbyte)
;* Pointers used    :None
;*
;***************************************************************************
.equ        sb  =1    ;Number of stop bits (1, 2, ...)

putchar:    ldi bitcnt,9+sb;1+8+sb (sb is # of stop bits)
       com Txbyte    ;Inverte everything
       sec        ;Start bit

putchar0:   brcc    putchar1  ;If carry set
       cbi PORTD,TxD  ;    send a '0'
       rjmp    putchar2  ;else  

putchar1:   sbi PORTD,TxD  ;    send a '1'
       nop

putchar2:   rcall UART_delay  ;One bit delay
       rcall UART_delay

       lsr Txbyte    ;Get next bit
       dec bitcnt    ;If not all bit sent
       brne    putchar0  ;   send next
                 ;else
       ret        ;   return


;***************************************************************************
;*
;* "getchar"
;*
;* This subroutine receives one byte and returns it in the "Rxbyte" register
;*
;* Number of words  :14 including return
;* Number of cycles :Depens on when data arrives
;* Low registers used   :None
;* High registers used  :2 (bitcnt,Rxbyte)
;* Pointers used    :None
;*
;***************************************************************************

getchar:    ldi     bitcnt,9  ;8 data bit + 1 stop bit

getchar1:   sbic    PIND,RxD  ;Wait for start bit
       rjmp    getchar1

       rcall UART_delay  ;0.5 bit delay

getchar2:   rcall UART_delay  ;1 bit delay
       rcall UART_delay        

       clc        ;clear carry
       sbic    PIND,RxD  ;if RX pin high
       sec        ;

       dec     bitcnt    ;If bit is stop bit
       breq    getchar3  ;   return
                 ;else
       ror     Rxbyte    ;   shift bit into Rxbyte
       rjmp    getchar2  ;   go get next

getchar3:   ret


;***************************************************************************
;*
;* "UART_delay"
;*
;* This delay subroutine generates the required delay between the bits when
;* transmitting and receiving bytes. The total execution time is set by the
;* constant "b":
;*
;*  3·b + 7 cycles (including rcall and ret)
;*
;* Number of words  :4 including return
;* Low registers used   :None
;* High registers used  :1 (temp)
;* Pointers used    :None
;*
;***************************************************************************
; Some b values:    (See also table in Appnote documentation)
;
; 1 MHz crystal:
;   9600 bps - b=14
;  19200 bps - b=5
;  28800 bps - b=2
;
; 2 MHz crystal:
;  19200 bps - b=14
;  28800 bps - b=8
;  57600 bps - b=2

; 4 MHz crystal:
;  19200 bps - b=31
;  28800 bps - b=19
;  57600 bps - b=8
; 115200 bps - b=2

.equ    b   =135  ;4800 bps @ 4 MHz crystal


UART_delay: ldi temp,b
UART_delay1:    dec temp
       brne    UART_delay1

       ret




Forumer™ is Voted #1 Free Forum Hosting provider
Build your own community today with the largest message board hosting company.