×
单片机 > 单片机程序设计 > 详情

用AVR单片机模拟的串口程序

发布时间:2020-05-28 发布时间:
|

在一些应用中经常要用到双串口,但是一般单片机只提供一个串口,其实完全可以用普通I/O口模拟一个串口。以下的程序是我编写的模拟串口程序,程序中使用了单片机的定时器0,和INT0中断。数据的发送和接收由中断程序自动进行。程序已经过AVR仿真器仿真和实际烧片使用,证明可靠。有一点需要说明的是,此模拟的串口为半双工方式。
    主程序中,单片机将标准串口设置为115200bps,将模拟串口设置为19200bps。单片机将标准串口收到的数据从模拟串口发送出去,将模拟串口接收到的数据从标准串口发送回来。


;*****************************************************************

*********************************
;*    title:        half duplex uart simulaton program
;*    version:        1.0
;*    program time:    2001/11/05
;*    target:        AT90S8515
;*    design:        zsmbj@beijing
;*****************************************************************

*********************************
.include "c:\program files\atmel\avr studio\appnotes\8515def.inc"
;BPS=19200
;F=11059200

.equ    N=72

.equ    txd0    =3        ;uart0 txd
.equ    rxd0    =2        ;uart0 rxd
;****************************************************************
    .equ    stack=0x0ff
;****************************************************************
;bit define
    .equ    rdr=0
    .equ    fe0=1
    .equ    td=6
    .equ    busy=7
;register define
    .def    temp=r16
    .def    sbuf0=r17
    .def    status=r18
    .def    bit_cnt=r19
;**********************************************************

****************************************
        .org    0x00
        rjmp    reset
        .org    0x01
        rjmp    int00
        .org    0x07
        rjmp    timer0_int
;**********************************************************
.cseg
;**********************************************************
;****initial
;**********************************************************
        .org    0x0010
;reset at90s8515
reset:
        ldi    temp,0b00001000
        out    ddrb,temp

        ldi    temp,high(stack)        ;stack
        out    sph,temp
        ldi    temp,low(stack)
        out    spl,temp

        ldi    temp,5                ;baud 115200bps at 11.0592M fosc
        out    ubrr,temp
        ldi    temp,0b00011000            ;enable rx and tx
        out    ucr,temp
;timer0 set
        ldi    temp,0x02            ;ck/8 0.72338us
        out    tccr0,temp

        ldi    temp,0x0a            ;disable outside sram,int0 fall edge make a interrupt
        out    mcucr,temp
        ldi    temp,0x40
        out    gimsk,temp            ;enable int0 and int1 interrupt

        ldi    temp,0
        mov    status,temp
        sbi    portb,txd0            ;txd0 bit=1

        sei                    ;globle interrupt enable
        rjmp    main            
;******************************************    
timer0_int:
        push    temp
        in    temp,sreg
        push    temp
        
        ldi    temp,(256-N)
        out    TCNT0,temp
        inc    bit_cnt

        sbrs    status,td
        rjmp    timer0_receive
;>>>>>>>>>>>>>>>>>>>>>>>>>>
;send data 8 data bit and 1 stop bit
timer0_send:
        sbrc    bit_cnt,3            ;if bit_cnt=8 then stop bit
        rjmp    timer0_send_stop
timer0_send_data:
        sbrc    sbuf0,0                ;txd=0
        sbi    portb,txd0
        sbrs    sbuf0,0                ;txd=1
        cbi    portb,txd0
        lsr    sbuf0
        rjmp    timer0_end
timer0_send_stop:
        sbi    portb,txd0            ;stop bit=1
        sbrc    bit_cnt,0
        rjmp    timer0_complete            ;if bit_cnt=9 then complete
;;;;;;;;;;;;;;;;;;;
        in    temp,gifr
        sbr    temp,(1<        out    gifr,temp            ;clr int0 flag
        
        in    temp,gimsk
        sbr    temp,(1<        out    gimsk,temp            ;enable gimsk/int0

        rjmp    timer0_end[page]

>>>>>>>>>>>>>>>>>>>>>>>>>>
;receive start 1bit data 8 bit stop 1bit
timer0_receive:
        cpi    bit_cnt,1            ;if bit_cnt=1 then start bit
        breq    timer0_receive_start
        cpi    bit_cnt,10            ;if bit_cnt=10 then stop bit
        breq    timer0_receive_stop
        
        rjmp    timer0_receive_data
timer0_receive_start:
        sbis    pind,rxd0
        rjmp    timer0_end
        
        cbr    status,(1<        rjmp    timer0_complete
timer0_receive_data:
        sec
        sbis    pind,rxd0            ;get rxd0 data
        clc
        ror    sbuf0
        rjmp    timer0_end
timer0_receive_stop:
        cbr    status,(1<        sbis    pind,rxd0
        rjmp    timer0_complete
        sbr    status,(1<        sbr    status,(1<;>>>>>>>>>>>>>>>>>>>>>>>>>>
timer0_complete:        
        in    temp,timsk
        cbr    temp,(1<        out    timsk,temp            ;disable timsk/toie0
;;;;;;;;;;;;;;;;;;;
        in    temp,gifr
        sbr    temp,(1<        out    gifr,temp            ;clr int0 flag
        
        in    temp,gimsk
        sbr    temp,(1<        out    gimsk,temp            ;enable gimsk/int0

        cbr    status,(1<timer0_end:
        pop    temp
        out    sreg,temp
        pop    temp

        reti        
;******************************************    
int00:
        push    temp
        in    temp,sreg
        push    temp

        ldi    temp,(256-N/2)            ;skip 0.5bit
        out    TCNT0,temp

        ldi    status,(1<        clr    bit_cnt
        
        in    temp,tifr
        sbr    temp,(1<        out    tifr,temp            ;clr tifr/tov0

        in    temp,timsk
        sbr    temp,(1<        out    timsk,temp            ;enable timsk/toie0

        in    temp,gimsk
        cbr    temp,(1<        out    gimsk,temp            ;disable gimsk/int0

        pop    temp
        out    sreg,temp
        pop    temp
        reti
;**********************************************************

rxd0_data:
txd0_data:
        ldi    status,(1<
        push    temp
        in    temp,gimsk
        cbr    temp,(1<        out    gimsk,temp            ;disable gimsk/int0
        pop    temp
        
        ser    bit_cnt                ;bit_cnt=0xff
        mov    sbuf0,temp            ;send data
        
        ldi    temp,(256-N)
        out    TCNT0,temp            ;wait 1 bit timer0 interrupt

        in    temp,tifr
        sbr    temp,(1<        out    tifr,temp            ;clr tifr/tov0

        in    temp,timsk
        sbr    temp,(1<        out    timsk,temp            ;enable timsk/toie0

        cbi    portb,txd0            ;uart start        

        ret
;******************************************    
rxd0_data:
        sbrs    status,fe0            ;if fe0=0 then exit
        rjmp    rxd0_data_end
        cbr    status,(1<        mov    temp,sbuf0
rxd0_data_end:
        ret
;******************************************    

;uart received a byts from uart  and then return it from uart0:
;uart received a byts from uart0 and then return it from uart :
main:
    sbic    usr,rxc
    rjmp    send_115200

    sbrs    status,rdr
    rjmp    uart_end
send_19200:    
    rcall    rxd0_data            ;get uart data from 19200bps uart0

wait2:    sbis    usr,udrie
    rjmp    wait2
    out    udr,temp            ;send data to 115200bps uart
    rjmp    uart_end

send_115200:
    in    temp,udr            ;get uart data from 115200bps uart
    sbic    usr,fe
    rjmp    uart_end            ;if fe err then end

wait3:    sbrc    status,td            ;wait send flag
    rjmp    wait3
    rcall    txd0_data            ;send data to 19200bps uart0
uart_end:
    rjmp    main
;**********************************************************
    .exit
;**********************************************************

关键字:AVR单片机  串口程序  模拟 

『本文转载自网络,版权归原作者所有,如有侵权请联系删除』

热门文章 更多
如何为单片机选择合适的负载电容