楽天市場
[無料でホームページを作成] [通報・削除依頼]

番外 ATTINY13A ソフトシリアル

ATTINY13Aで84ワードのブートローダーを検討する過程で、
AVLのアプリケーションノート AVR305: Half Duplex Compact Software UART
を元にATTINY13Aソフトシリアルのコード短縮を検討しました。
(2014.05.20加筆修正)

<結果>
オリジナルコード32ワードから4ワード低減でき、これを用いて
ATTINY13Aで84ワードのブートローダーを作成することができました。

以下に両者のコードを比較し、記載します。
以下のコードを使用する上でATTINYのクロックを知り補正を行なう必要があります。
検討したコードのビットディレイの定数はクロック9.6MHz+9600bpsの値です。

(2014.03.08加筆)---------------------------------

ボーレートやクロックの変更に対応するための修正

.equ    xtal    =    8000000  ;Hz
.equ    baud    =    19200    ;bps

などと定義し、bwait2のldiの行を赤文字のように変更してください。
低ボーレートの場合、(xtal/baud-22)/6の値が256より大きくなる条件は設定できません。
(bwait2のサブルーチンを作り直す必要があります。)

bwait:                                      ; wait 1 bit
                rcall    bwait2            ;3+493+493=989
bwait2:                                    ; wait 1/2bit
                ldi    rs,(xtal/baud-22)/6    ;1
                subi    rs,1                ;1
                brne    PC-1               ;2/1
                ret                            ;4 1+(1+2)*163-1+4=493

-------------------------------------------------------------------------------

ATTINY13Aの84ワードのブートローダーはこちらからダウンロードできます。
ttp://sourceforge.net/p/tinypicbootload/discussion/general/thread/24e44bca/
Tiny_Avr-Pic_Bootloader+ (v0.8.3.1).zip 



<avr305オリジナルコード>

.def    bitcnt    =R16            ;bit counter
.def    temp    =R17            ;temporary storage register
.def    Txbyte    =R18            ;Data to be transmitted
.def    RXbyte    =R19            ;Received data

;***************************************************************************
;*
;* "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
;*
;***************************************************************************

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
;*
;***************************************************************************

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




<検討したコード>

.def    rs    =R17              ;ビットディレイカウンター
.def    cn    =R18             ;ビットループカウンター
.def    rxd    =R19            ;送受信バッファー

        #define TX      4                 ; ATTINY13A TX Data output pin (i.e. 2 = PORTB,2)
        #define RX      3                 ; ATTINY13A RX Data input pin (i.e. 3 = PORTB,3)
        #define Direct_TX               ; RS-232C TX Direct Connection(No use MAX232)
        #define Direct_RX               ; RS-232C RX Direct Connection(No use MAX232)


        SBI    DDRB,TX                    ; set TX Port

; ********************************************************************
;
;        RS-232C Send 1byte
;
;        rxdに値をセットして呼び出す(13ワード)
;
; ********************************************************************

PUTC:
    #ifdef  Direct_TX
            CBI      PORTB,TX
    #else
            SBI      PORTB,TX
    #endif
            LDI      cn,1+8+1   ; 10-bit Data
            COM    rxd             ; Data inverce
            RJMP    PC+5          ; Start bit

            LSR     rxd              ; shift right LSB to Carry    [1]

     #ifdef    Direct_TX
            brcs    PC+2            ;                                     [2/1]
            cbi     PORTB,TX      ; set TX='0' if Carry='0'     [2]
            brcc    PC+2            ;                                     [2/1]
            sbi     PORTB,TX      ; set TX='1' if Carry='1'     [2]
     #else
            brcs    PC+2
            sbi     PORTB,TX      ; set TX='1' if Carry='0'
            brcc    PC+2
            cbi     PORTB,TX      ; set TX='0' if Carry='1'
     #endif

            rcall    bwait            ; wait 1 bit                        [992]
            dec     cn                ;                                       [1]
            brne    PC-7             ;                                      [2] 1+7+992+1+2=1003
            ret

; ********************************************************************
;
;        RS-232C Recieve 1byte
;
;        受信データはrxdに返る(14ワード)
;
; ********************************************************************

GETC:
        #ifdef  Direct_RX
                SBIS    PINB,RX
        #else
                SBIC    PINB,RX
        #endif
                RJMP    PC-1

                LDI     rxd,0x80        ; rxd='10000000'
                RCALL    bwait2        ; wait 1/2 bit

                RCALL    bwait          ; wait 1 bit and set Carry=0    [992]

        #ifdef  Direct_RX
                SBIS    PINB,RX        ;                                           [2/3]
        #else
                SBIC    PINB,RX
        #endif
                SEC                         ;                                           [1]
                ROR    rxd                ; set Data                              [1]
                BRCC    PC-4             ;                                           [2] 992+3+1+1+2=999

bwait:                                      ; wait 1 bit
                rcall    bwait2            ;3+493+493=989
bwait2:                                    ; wait 1/2bit
                ldi    rs,163               ;1
                subi    rs,1                ;1
                brne    PC-1               ;2/1
                ret                            ;4 1+(1+2)*163-1+4=493





























































































.