Witam kolegów,
mam dość dziwny kłopot. Poniższy program zawiera jedynie procedury służące do komunikacji Atmega16 z PC. Jest tu obsługa wejściowego i wyjsciowego bufora kołowego o pojemności 255znaków. Pętla główna jest w zasadzie pusta.
W celu przetestowania każdy przychodzacy znak jest dodawany do bufora wyjściowego i odsyłany (echo). Program testuje Bray terminalem wysyłając paczki po kilkadziesiąt znaków. Wszystko działało bez zarzutu, dopóki nie dodałem skoku rcall w pętli głównej programu Kiedy pętla główna składa się wyłącznie z kilku nop paczki wracają bez błędów, a kiedy jest taki krótki rcall lub call jak w przykładzie to ok.50% danych wraca wykrzaczona. Błędów jest tym więcej im mniej nop w pętli głównej. Umieszczanie w petli głównej innych rozkazów, skoków rjmp, jmp, add, or nie powoduje błędów.
Co Wy na to? Nie ma to chyba znaczenia ale ustawiłem 9600bps przy kwarcu 16MHz. Uzywam przejściówki USB-RS232 na Atmega8 wg Osama Tamury.
Oto program:
Proszę o pomoc
mam dość dziwny kłopot. Poniższy program zawiera jedynie procedury służące do komunikacji Atmega16 z PC. Jest tu obsługa wejściowego i wyjsciowego bufora kołowego o pojemności 255znaków. Pętla główna jest w zasadzie pusta.
W celu przetestowania każdy przychodzacy znak jest dodawany do bufora wyjściowego i odsyłany (echo). Program testuje Bray terminalem wysyłając paczki po kilkadziesiąt znaków. Wszystko działało bez zarzutu, dopóki nie dodałem skoku rcall w pętli głównej programu Kiedy pętla główna składa się wyłącznie z kilku nop paczki wracają bez błędów, a kiedy jest taki krótki rcall lub call jak w przykładzie to ok.50% danych wraca wykrzaczona. Błędów jest tym więcej im mniej nop w pętli głównej. Umieszczanie w petli głównej innych rozkazów, skoków rjmp, jmp, add, or nie powoduje błędów.
Co Wy na to? Nie ma to chyba znaczenia ale ustawiłem 9600bps przy kwarcu 16MHz. Uzywam przejściówki USB-RS232 na Atmega8 wg Osama Tamury.
Oto program:
.nolist ;
.include "m16def.inc" ;
.list ;
.listmac
;===== definicje
;komunikacja, bufory wejściowy i wyjściowy
.equ outBufferStart = $0100
.equ outBufferLength = 250
.def outBufferReadPos = R2
.def outBufferWritePos = R3
.def SendChar = R22
.equ inBufferStart = $0200
.equ inBufferLength = 250
.def inBufferReadPos = R5
.def inBufferWritePos = R6
;--- wektor przerwań
.cseg
.org $000 jmp RESET ; Reset Handler
.org $002 reti ;jmp EXT_INT0 ; IRQ0 Handler
.org $004 reti ;jmp EXT_INT1 ; IRQ1 Handler
.org $006 reti ;jmp TIM2_COMP ; Timer2 Compare Handler
.org $008 reti ;jmp TIM2_OVF ; Timer2 Overflow Handler
.org $00A reti ;jmp TIM1_CAPT ; Timer1 Capture Handler
.org $00C reti ;jmp TIM1_COMPA ; Timer1 CompareA Handler
.org $00E reti ;jmp TIM1_COMPB ; Timer1 CompareB Handler
.org $010 reti ;jmp TIM1_OVF ; Timer1 Overflow Handler
.org $012 reti ;jmp TIM0_OVF ; Timer0 Overflow Handler
.org $014 reti ;jmp SPI_STC ; SPI Transfer Complete Handler
.org $016 jmp USART_RXC ; USART RX Complete Handler
.org $018 reti ;jmp USART_UDRE ; UDR Empty Handler
.org $01A jmp USART_TXC ; USART TX Complete Handler
.org $01C reti ;jmp ADC ; ADC Conversion Complete Handler
.org $01E reti ;jmp EE_RDY ; EEPROM Ready Handler
.org $020 reti ;jmp ANA_COMP ; Analog Comparator Handler
.org $022 reti ;jmp TWSI ; Two-wire Serial Interface Handler
.org $024 reti ;jmp EXT_INT2 ; IRQ2 Handler
.org $026 reti ;jmp TIM0_COMP ; Timer0 Compare Handler
.org $028 reti ;jmp SPM_RDY ; Store Program Memory Ready Handler
RESET:
ldi r16, high(RAMEND) ; Main program start
out SPH, r16 ; Set Stack Pointer to top of RAM
ldi r16, low(RAMEND)
out SPL, r16
;komunikacja
ldi R17, 0
ldi R16, 103 ;9600bps przy 16MHz
out UBRRH, r17
out UBRRL, r16
ldi r16, (1<<RXCIE)|(1<<TXCIE)|(1<<RXEN)|(1<<TXEN)
out UCSRB,r16
ldi r16, (1<<URSEL)|(1<<UCSZ0)|(1<<UCSZ1) ; Set frame format: 8data, disabled parity, 1stop bit
out UCSRC,r16
ser R16 ;ustawia 255
mov outBufferReadPos, R16
mov outBufferWritePos, R16
mov inBufferWritePos, R16
mov inBufferReadPos, R16
ldi SendChar, RReset
rcall AddToOutBuffer
sei ; Enable interrupts
;###### główna pętla programu #######
MainLoop:
;rcall CzytajRozkaz
nop
nop
nop
nop
nop
nop
rjmp MainLoop
CzytajRozkaz:
ret
;--- dodaje do bufora wejściowego przysłany USARTem znak
USART_RXC:
push R18
in R18, SREG
push R18
;sprawdzmy czy nie stracono danych
sbic UCSRA, DOR ;Data OverRun
sbi ErrorPort, ErrorPin
;ustalmy pozycje do zapisu
inc inBufferWritePos
;zapis do bufora
ldi XH, high(inBufferStart)
ldi XL, low(inBufferStart)
add XL, inBufferWritePos
in R18, UDR
st X, R18
mov SendChar, R18
rcall AddToOutBuffer ;echo
;koniec
pop R18
out SREG, R18
pop R18
reti
;--- dodaje do bufora wyjściowego znak z rejestru SendChar
; brak obsługi błędów przepełnienia, zakładam, że bufor jest wystarczająco duży
AddToOutBuffer:
cli
in R18, SREG
push R18
;ustalenie pozycji do zapisu, czy nie ma przepełnienia
inc outBufferWritePos
;zapis do bufora
ldi XH, high(outBufferStart)
ldi XL, low(outBufferStart)
add XL, outBufferWritePos
st X, SendChar
;jeśli nic nie jest akurat wysyłane to wyślijmy
sbic UCSRA,UDRE
rcall USART_TXC
cli
;koniec
pop R18
out SREG, R18
ret
;--- wysyła dane z bufora przez USART
USART_TXC:
push R18
in R18, SREG
push R18
;czy w buforze jest coś jeszcze do wyslania?
cp outBufferReadPos, outBufferWritePos
breq UTXC_end ;bufor jest pusty
;jest coś do wysłania, ustalmy adres
inc outBufferReadPos
;wysyłamy
ldi XH, high(outBufferStart)
ldi XL, low(outBufferStart)
add XL, outBufferReadPos
ld R18, X
out UDR, R18
UTXC_end:
pop R18
out SREG, R18
pop R18
reti
Proszę o pomoc