Full Version : Lanconelli's RS232 Program (ASM)
avr >>COMMUNICATIONS & WEB PROJECTS >>Lanconelli's RS232 Program (ASM)


Admin3- 04-19-2006
Claudio Lanconelli's RS232.asm program

CODE


;FILE:MACRO.INC
.LISTMAC



.MACRO  ADDI    

subi @0, -(@1)

.ENDMACRO



;skip next instruction if not equal to zero

.MACRO skipne                  

.SET    _skipne = PC+2

brne    _skipne

.ENDMACRO



;skip next instruction if carry set

.MACRO skipcs                  

.SET    _skipcs = PC+2

brcs    _skipcs

.ENDMACRO



;skip next instruction if carry clear

.MACRO skipcc

.SET    _skipcc = PC+2

brcc    _skipcc

.ENDMACRO



;skip next instruction if equal to zero

.MACRO  skipeq

.SET    _skipeq = PC+2

breq    _skipeq

.ENDMACRO



;skip next instruction if lower

.MACRO skiplo                  

.SET    _skiplo = PC+2

brlo    _skiplo

.ENDMACRO



;skip next instruction if half carry set

.MACRO skiphs                  

.SET    _skiphs = PC+2

brhs    _skiphs

.ENDMACRO



;skip next instruction if half carry clear

.MACRO skiphc

.SET    _skiphc= PC+2

brhc   _skiphc

.ENDMACRO



;skip next instruction if T set

.MACRO skipts                  

.SET    _skipts = PC+2

brts    _skipts

.ENDMACRO



;skip next instruction if T clear

.MACRO skiptc                  

.SET    _skiptc = PC+2

brtc    _skiptc

.ENDMACRO



;skip next instruction if minus

.MACRO skipmi

.SET    _skipmi = PC+2

brmi    _skipmi

.ENDMACRO



;skip next instruction always

.MACRO skipnext

.SET _skipnext = PC+2

rjmp _skipnext

.ENDMACRO



;wait two cycles but waste only one instruction

.MACRO  doublenop

.SET    _doublenop = PC+1

rjmp    _doublenop

.ENDMACRO



;compare Port bit with T, and branch to @2 if are not equal

.MACRO cpeqPortBit

sbic @0,@1

.SET _cpPortBit1 = PC+3

rjmp _cpPortBit1

brts @2

.SET _cpPortBit0 = PC+2

rjmp _cpPortBit0

brtc @2

.ENDMACRO



;compare Port bit with T, and branch to @2 if are equal

.MACRO cpnePortBit

sbic @0,@1

.SET _cpPortBit1 = PC+3

rjmp _cpPortBit1

brtc @2

.SET _cpPortBit0 = PC+2

rjmp _cpPortBit0

brts @2

.ENDMACRO



;compare Register bit with T, and branch to @2 if are not equal

.MACRO cpeqRegBit

sbrc @0,@1

.SET _cpRegBit1 = PC+3

rjmp _cpRegBit1

brts @2

.SET _cpRegBit0 = PC+2

rjmp _cpRegBit0

brtc @2

.ENDMACRO



;compare Register bit with T, and branch to @2 if are equal

.MACRO cpneRegBit

sbrc @0,@1

.SET _cpRegBit1 = PC+3

rjmp _cpRegBit1

brtc @2

.SET _cpRegBit0 = PC+2

rjmp _cpRegBit0

brts @2

.ENDMACRO



;***************************************************************************
;* RS232.ASM
;*
;* rs232 Tx only example based on
;* AVR MINI THREADS v.1.02
;* ---> nanoKernel for the AVR AT90S1200
;*
;* To try this code you need AvrTools from ATMEL, PonyProg and a simple
;* hardware (See schematics in PDF).
;*
;* Copyright (c) 1998 by Claudio Lanconelli
;* e-mail: lanconel@cs.unibo.it
;* WWW: http://www.cs.unibo.it/~lanconel
;*
;/ This program is free software; you can redistribute it and/or //
;/ modify it under the terms of the GNU General Public License //
;/ as published by the Free Software Foundation; either version2 of //
;/ the License, or (at your option) any later version. //
;/ //
;/ This program is distributed in the hope that it will be useful, //
;/ but WITHOUT ANY WARRANTY; without even the implied warranty of //
;/ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU //
;/ General Public License for more details. //
;/ //
;/ You should have received a copy of the GNU General Public License //
;/ along with this program (see COPYING); if not, write to the //
;/ Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. //
;***************************************************************************
.DEVICE AT90S1200

.include "macro.inc"
.include "1200def.inc"

; Follows an example of the use of mini-threads (three threads).
;-the first thread (main) send data to the Serial driver thread
;-the second thread do nothing
;-the third thread (the serial driver) wait for the timer or thread1 request
; and send the data to the SerTx pin in a 1200 8N1 data format (with a 3.6864MHz xtal)
;


.CSEG

;***************************************************************************
;* VARIABLE ASSIGNEMENTS
;***************************************************************************

   .def    SaveThr1Status    =     r0;status copy for thread 1
   .def    SaveThr2Status    =     r1  ;status copy for thread 2
   .def    SaveThr3Status    =     r2  ;status copy for thread 3
   .def    SaveStatus    =     r3  ;status copy for interrupts

   .def    SerNbit         =    r16    ;serial bit to transmit
   .def    SerData         =    r17    ;serial data byte to transmit

   .def Main1        =     r21  ;Temp variable used by main program
   .def    MiscFlags    =     r31  ;threads status flags + signal flags

 ;flags bit definition
   .equ    Thread1Status    =     0  ; 1 --> ready, 0 --> waiting
   .equ    Thread2Status    =     1
   .equ    Thread3Status    =     2
   .equ    Thread1Signal    =     3
   .equ    Thread2Signal    =     4
   .equ    Thread3Signal    =     5
   .equ    SerRequest    =     6

   .equ    THRSTATUSMASK =         7
   .equ    SIGNALMASK =         112


;***************************************************************************
;* Port Pin Assignements
;***************************************************************************

 ;port D bit definitions
   .equ    Led1    =    0    ;out
   .equ    Led2    =    1    ;out

 ;port B bit definitions
   .equ    Key1    =    0    ;in (pullup)
   .equ    SerTx    =    4    ;out
   

;***************************************************************************
;* VECTORS
;***************************************************************************

       rjmp RESET            ;Reset Handle
       rjmp INT0DRV            ;Ext. interrupt request 0
       rjmp TIMERDRV        ;Timer


;***************************************************************************
;*
;* MAIN PROGRAM
;*
;***************************************************************************
;* INITIALIZATION
;***************************************************************************

RESET:
       ldi    Main1, 0b01111011    ;set port D bits to outputs (INT0 as an input)
       out    DDRD, Main1
       ldi    Main1, 0b00000111    ;preset output state (activate INT0 pull-up)
       out    PortD, Main1
       ldi    Main1, 0b00010000    ;set port B to inputs
       out    DDRB, Main1
       ldi    Main1, 0b11101111    ;turn on pullups on inputs
       out    PortB, Main1

       ldi    Main1, 5
       out    TCCR0, Main1        ;set prescaler to CK/1024
       ldi    Main1, 32+2
       out    MCUCR, Main1        ;enable sleep idle mode (ext int on falling edge)
       ldi    Main1, 2
       out    TIMSK, Main1        ;enable timer interrupt
       ldi    Main1, 64
       out    GIMSK, Main1        ;enable external interrupt

       ldi    Main1, 256-3
       out    TCNT0, Main1

       ldi    MiscFlags,THRSTATUSMASK

       sei                ;enable interrupts

       in    SaveThr1Status,SREG        ;initialize status (interrupts enabled in all thread)
       mov     SaveThr2Status,SaveThr1Status
       mov     SaveThr3Status,SaveThr1Status
       
;=====================================
;THREAD 1
; main loop
THR1LOOP:
       sbic    PinB,Key1
       rjmp    L001
       cbi    PortD,Led1

       sbr    MiscFlags, EXP2(SerRequest)
       ldi    SerData,66        ;Carattere 'B'
       sbr    MiscFlags, EXP2(Thread3Signal)      ;send the request to serial thread
       rcall    WAIT1

       sbr    MiscFlags, EXP2(SerRequest)
       ldi    SerData,65        ;Carattere 'A'
       sbr    MiscFlags, EXP2(Thread3Signal)      ;send the request to serial thread
       rcall    WAIT1

       sbr    MiscFlags, EXP2(SerRequest)
       ldi    SerData,66        ;Carattere 'B'
       sbr    MiscFlags, EXP2(Thread3Signal)      ;send the request to serial thread
       rcall    WAIT1

       sbr    MiscFlags, EXP2(SerRequest)
       ldi    SerData,69        ;Carattere 'E'
       sbr    MiscFlags, EXP2(Thread3Signal)      ;send the request to serial thread
       rcall    WAIT1

       rjmp    THR1LOOP
L001:
       sbi    PortD,Led1
       rjmp    THR1LOOP

;-----------------
WAIT1:
     ;save status before switch to another thread
       in    SaveThr1Status,SREG
       sbrs    MiscFlags, Thread1Signal        ;check for reeceived signal
       cbr    MiscFlags, EXP2(Thread1Status)      ;thread1 in wait state
       cbr    MiscFlags, EXP2(Thread1Signal)      ;reset signal
       rjmp    SCHEDULER2
THR1WAKEUP:
       ret


;=================================
;THREAD 2    (do nothing in this example)
; main loop
THR2LOOP:
     ;thread 2 WAIT
     ;we can't do a separate Wait subroutine for every thread. Note that
     ;the stack is hardware, and not accessible.
     ;save status before switch to another thread
       in    SaveThr2Status,SREG
       sbrs    MiscFlags, Thread2Signal        ;check for received signal, if we have already
                             ;received the signal don't go sleep
       cbr    MiscFlags, EXP2(Thread2Status)      ;thread2 in wait state
       cbr    MiscFlags, EXP2(Thread2Signal)
       rjmp    SCHEDULER3
THR2WAKEUP:
       rjmp    THR2LOOP


;===================================
;SERIAL DRIVER THREAD
; main loop
THR3LOOP:
     ;thread 3 WAIT
     ;save status before switch to another thread
       in    SaveThr3Status,SREG
       sbrs    MiscFlags, Thread3Signal        ;check for received signal
       cbr    MiscFlags, EXP2(Thread3Status)      ;thread3 in wait state
       cbr    MiscFlags, EXP2(Thread3Signal)
       rjmp    SCHEDULER1
THR3WAKEUP:
     ;test SerRequest to know who have sent the the signal (Thr1 or Timer)
       sbrc    MiscFlags, SerRequest
       rjmp    THR3_L1

     ;waked up from Timer, are some data bits to transmit?
       tst    SerNBit                    ;if zero do nothing
       breq    THR3LOOP

       dec    SerNBit
       breq    THR3_TXEND                ;if zero tx stop and finish

       cpi    SerNBit,9                ;tx start
       breq    THR3_TX0
THR3_TXDATA:
       lsr    SerData                    ;tx next bit (in the carry)
       brcc    THR3_TX0
THR3_TX1:
       cbi    PortB,SerTx
       rjmp    THR3LOOP
THR3_TX0:
       sbi    PortB,SerTx
       rjmp    THR3LOOP
THR3_L1:
     ;new request from Thr1
       cbr    MiscFlags, EXP2(SerRequest)
       ldi    SerNBit,10                ;tx 10 bits: 1start + 8data + 1stop
       rjmp    THR3LOOP
THR3_TXEND:
       sbr    MiscFlags, EXP2(Thread1Signal)      ;wakeup thread 1
       rjmp    THR3_TX1


;---------------
;Interrupts routine just send a signal to a thread. If you need a VERY short interrupt
;response you can put some instructions here, then send the signal to the thread
;---------------
TIMERDRV:
       in    SaveStatus,SREG

       ldi    Main1, 256-3
       out    TCNT0, Main1
       sbr    MiscFlags, EXP2(Thread3Signal)      ;wakeup thread 3 (serial driver)

       out    SREG,SaveStatus
       reti


;---------------
INT0DRV:
       in    SaveStatus,SREG
       sbr    MiscFlags, EXP2(Thread2Signal)      ;wakeup thread 2
       out    SREG,SaveStatus
       reti


;-----------------
;This is the scheduler, the core of the nanoKernel. You can decide to go sleep
; when there's nothing to do. You can also put there the watchdog reset instruction.
;-----------------
SCHEDULER:
       sei                        ;be sure interrupts on here

     ;if you don't want to go sleep remove next 3 instr
       tst    MiscFlags
       brne    SCHEDULER1
       sleep
SCHEDULER1:
       sbrc    MiscFlags, Thread1Status        ;test if thread1 is ready
       rjmp    SCHEDRDY1
     ;check for wakeup
       sbrs    MiscFlags, Thread1Signal        ;test if thread1 received a signal
       rjmp    SCHEDULER2
       cbr    MiscFlags, EXP2(Thread1Signal)      ;clear signal
SCHEDRDY1:
     ;switch to thread 1
       sbr    MiscFlags, EXP2(Thread1Status)
       out    SREG,SaveThr1Status
       rjmp    THR1WAKEUP

SCHEDULER2:
       sbrc    MiscFlags, Thread2Status        ;test if thread2 is ready
       rjmp    SCHEDRDY2
     ;check for wakeup
       sbrs    MiscFlags, Thread2Signal        ;test if thread1 received a signal
       rjmp    SCHEDULER3
       cbr    MiscFlags, EXP2(Thread2Signal)      ;clear signal
SCHEDRDY2:
     ;switch to thread 2
       sbr    MiscFlags, EXP2(Thread2Status)
       out    SREG,SaveThr2Status
       rjmp    THR2WAKEUP
SCHEDULER3:
       sbrc    MiscFlags, Thread3Status        ;test if thread3 is ready
       rjmp    SCHEDRDY3
     ;check for wakeup
       sbrs    MiscFlags, Thread3Signal        ;test if thread1 received a signal
       rjmp    SCHEDULER
       cbr    MiscFlags, EXP2(Thread3Signal)      ;clear signal
SCHEDRDY3:
     ;switch to thread 3
       sbr    MiscFlags, EXP2(Thread3Status)
       out    SREG,SaveThr3Status
       rjmp    THR3WAKEUP





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