No nie to żebym od razu się domagał

po prostu myślałem, że się ktoś zainteresuje i jak nie będzie widział tutaj potrzebnych informacji to powie mi jakich (a nie od razu zmiesza z błotem:) bo ja nie wiem co jest potrzebne żeby zdiagnozować ten błąd.
Po kolei.
Cytat:
Do tego nie robisz wcięć, przez co program jest nieczytelny.
Szukałem jak wygląda na tym forum formatowanie kodu w postach, ale znalazłem tylko kod wrzucany w słupku, jedna komenda pod drugą, więc nie wiem jak mam sformatować to co zaraz wyślę. Pokaż przykład, to tak przeformatuję.
Nie chciałem od razu wrzucać całego kodu programu, bo jest on dosyć długi, no ale jak widać, nie obejdzie się bez tego.
Będzie z opisami:)
Używane zmienne:
.INCLUDE "m32def.inc"
.def a = r16 // zmienne pomocnicze, używane w różnych celach
.def b = r17 //
.def c = r22 //
//
.def pom1 = r18 //
.def pom2 = r19 //
.def pom3 = r20 //
.def pom4 = r21 //
.def rejestr1 = r0 // bajty wysyłane na porty. sterownie końcówkami mocy
.def rejestr2 = r1 //
.def rejestr3 = r2 //
.def rejestr4 = r3 //
.def del1 = r24 // liczniki zarazerwowany dla delaya
.def del2 = r25 // liczniki zarazerwowany dla delaya
.def del00 = r30 // Lb czasu opoznienia
.def del01 = r31 // Hb czasu opoznienia
Struktura pamięci, opis słowa z PC itd.
//////////////////////////////////////////
//
// struktura SRAM:
// 0x0060 Hb krokow silnika S1
// 0x0061 Lb krokow silnika S1
// 0x0062 kirunek obrotu S1
// 0x0063 ~EN silnika S1
// 0x0064 rezerwa S1
//
// 0x0065 Hb krokow silnika S2
// 0x0066 Lb krokow silnika S2
// 0x0067 kirunek obrotu S2
// 0x0068 ~EN silnika S2
// 0x0069 rezerwa S2
//
// 0x006A Hb krokow silnika S3
// 0x006B Lb krokow silnika S3
// 0x006C kirunek obrotu S3
// 0x006D ~EN silnika S3
// 0x006E rezerwa S3
//
// 0x006F Hb krokow silnika S4
// 0x0070 Lb krokow silnika S4
// 0x0071 kirunek obrotu S4
// 0x0072 ~EN silnika S4
// 0x0073 rezerwa S4
//
// 0x0074 Hb krokow silnika S4
// 0x0075 Lb krokow silnika S4
// 0x0076 kirunek obrotu S4
// 0x0077 ~EN silnika S4
// 0x0078 rezerwa S4
//
// 0x0079 czas trwania 1 kroku [ms]
//
// 0x007A wskaznik odebranych liczby odebranych danych z UART
// 0x007B UART bajt 1
// 0x007C UART bajt 2
// 0x007D UART bajt 3
// 0x007E UART bajt 4
//
// 0x007F 1 parametr do funkcji
// 0x0080 2 parametr do funkcji
//
// 0x0090 poczatek miejsca na kopiowane rejestry
// ......
// 0x00aF koniec miejsca na kopiowane rejestry
//
//////////////////////////////////////////
//
// Struktura slowa z PC:
// 00 11 22 33
// nr_silnika
// kierunek
// Hb_ilosci_krokow
// Lb_ilosci_krokow
//
// 1,2,3,4
// "L"0x4C,"P"0x50 kierunek obrotu "L"=stan 0 na porcie
// "T"0x54 "T"-zmiana opoznienia pomiedzy kolejnymi krokami [ms], bajt 3-dowolny, bajt 4-opozninie
// "E"0x45 enabled (slowo ma postac 1 E 0 1 aby wlaczyc S1) 0xFF w SRAM jezeli enabled, 0x00 jezeli not enabled (na porcie odwrotnie- stan wysoki to not enabled)
// 0x00-0xFF
// 0x00-0xFF
//
//
//////////////////////////////////////////
//
// Porty:
// PortD.0 [1] -------------- rejestr1
// PortD.1 [2] --------------
// PortD.2 [3] --------------
// PortD.3 [4] --------------
// PortD.4 [5] --------------
// PortD.5 [6] --------------
// PortD.6 [7] --------------
// PortD.7 [8] 1 CLK S1
//
// PortC.0 [9] 1 CW/CCW S1 rejestr2
// PortC.1 [10] 1 ~EN S1
// PortC.2 [11] 0 krancowka1 S1
// PortC.3 [12] 0 krancowka2 S1
// PortC.4 [13] 1 CLK S2
// PortC.5 [14] 1 CW/CCW S2
// PortC.6 [15] 1 ~EN S2
// PortC.7 [16] 0 krancowka1 S2
//
// PortB.0 [17] 0 krancowka2 S2 rejestr2
// PortB.1 [18] 1 CLK S3
// PortB.2 [19] 1 CW/CCW S3
// PortB.3 [20] 1 ~EN S3
// PortB.4 [21] 0 krancowka1 S3
// PortB.5 [22] 0 krancowka2 S3
// PortB.6 [23] 1 CLK S3
// PortB.7 [24] 1 CW/CCW S4
//
// PortA.0 [25] 1 ~EN S4 rejestr4
// PortA.1 [26] 0 krancowka1 S4
// PortA.2 [27] 0 krancowka2 S4
// PortA.3 [28] 1 CLK S5
// PortA.4 [29] 1 CW/CCW S5
// PortA.5 [30] 1 ~EN S5
// PortA.6 [31] 0 krancowka1 S5
// PortA.7 [32] 0 krancowka2 S5
//
//////////////////////////////////////////
Ustawienia początkowe:
.cseg
.org 0x0000 jmp main
.org 0x0002 reti
.org 0x0004 reti
.org 0x0006 reti
.org 0x0008 reti
.org 0x000a reti
.org 0x000c reti
.org 0x000e reti
.org 0x0010 reti
.org 0x0012 reti
.org 0x0014 reti
.org 0x0016 reti
.org 0x0018 reti
.org 0x001a jmp odbior2
.org 0x001c reti
.org 0x001e reti
.org 0x0020 reti
.org 0x0022 reti
.org 0x0024 reti
.org 0x0026 reti
.org 0x0028 reti
main:
ldi a, LOW(RAMEND) // inicjalizacja stosu
out SPL, a //
ldi a, HIGH(RAMEND) //
out SPH, a //
ldi a, 0b10000000 // ustaienia początkowe rejestrów
mov rejestr1, a //
ldi a, 0b01110011 //
mov rejestr2, a //
ldi a, 0b11001110 //
mov rejestr3, a //
ldi a, 0b00111001 //
mov rejestr4, a //
out DDRD, rejestr1 // ustawienia portow
out PortD, rejestr1 //
//
out DDRC, rejestr2 //
out PortC, rejestr2 //
//
out DDRB, rejestr3 //
out PortB, rejestr3 //
//
out DDRA, rejestr4 //
out PortA, rejestr4 //
ldi a, 0 // ustawienia usart
out UBRRH, a //
ldi a, 103 //
out UBRRL, a //
//
ldi a, (1<<RXCIE) | (1<<RXEN) | (1<<TXEN) //
out UCSRB, a //
ldi a, 0x45 // wyslanie "E" na USART
out UDR, a //
ldi a, (1<<JTD) // disable JTAG interface (2 sec external reset lo, enables JTAG interface)
// out MCUCSR, a //
// out MCUCSR, a // musi byc 2x!!!
rcall czyscmemo
rcall ustawienia_poczatkowe
sei //włączenie przerwań
Pętla główna, w niej jest sprawdzana ilość kroków (stanów niskich pinu CLK dla danego silnika), stanu pinów ENABLED, pinu kierunku CW/CCW i stanu pinów krańcówek (stan wysoki na pinie krańcówki, oznacza zadziałanie krańcówki):
loop:
in rejestr1, PinD // wczytanie do rejestrów stanu pinów (aby zdiagnozować stan krańcówek)
in rejestr2, PinC //
in rejestr3, PinB //
in rejestr4, PinA //
ldi c, 8 // nie ruszac, poczatkowe ustawienie dla ustawiania bitow w rejestrach (funkcja ustaw_bit_rejestru)
loop_s1:
push c
subi c, 8
clr R29 // wczytanie wartosci parametrow do wyslania do silnika (CK, CW/CCW, EN)
ldi R28, 0x0060 //
add R28, c //
pop c //
ld R27, Y+ // wczytanie Hb ilości kroków dla danego silnika
ld R26, Y+ // wczytanie Lb ilości kroków
ld pom1, Y+ // wczytanie kierunku działania
ld pom2, Y+ // wczytanie stanu pinu enabled
subi R28, 4
push c // --- ENABLED --- ustawienie pinu
inc c //
inc c // c - który bit rejestrów ustawić (bity numerowane od 1, czyli bit 0 rejestr1, ma nr 1, bit 0 rejestr2 ma nr 9 itd.)
ldi a, 0 // a - jaki ma być stan bitu
sbrs pom2, 0 //
ldi a, 1 //
rcall ustaw_bit_rejestru //
pop c // --- /ENABLED ---
loop_s1_0: // --- KIERUNKU DZIAŁANIA --- zdefiniowanie (0x4C = "L" = 0 na porcie)
//
push c //
inc c
ldi a, 0 //
cpi pom1, 0x4C //
breq loop_s1_skipR //
ldi a, 1 //
loop_s1_skipR: //
rcall ustaw_bit_rejestru //
pop c // --- /KIERUNKU DZIAŁANIA ---
push c // --- KRAŃCÓWKI ---
clr a
inc c
inc c
inc c
rcall s_k // funkcja sprawdzająca stan krańcówek
pop c // zwraca w zmiennej a liczbę 1 jeżeli zadziałała krańcówka prawa, liczbę 2 jeżeli lewa, 3 jeżeli obie (ktoś wcisnął:)
push c
inc c
inc c
inc c
inc c
rcall s_k
pop c
cpi pom1, 0x4C
brne loop_s1_kP
loop_s1_kL:
sbrs a, 1
rjmp loop_s1_3
rjmp loop_s1_krancowka
loop_s1_kP:
sbrs a, 0
rjmp loop_s1_3
rjmp loop_s1_krancowka
loop_s1_krancowka:
ldi a, 1 // wyslanie sygnalu ze zadzialala krancowka
out UDR, a //
ldi a, 0x4B //
out UDR, a //
ldi a, 0x00 //
out UDR, a //
mov a, pom1 //
out UDR, a //
ldi a, 1 // wyslanie wartosci pozostalej ilosci krokow do zrealizowania
out UDR, a //
ldi a, 0x4B //
out UDR, a //
ld R27, Y+ // wczytanie obecnej liczby krokow do wykonania
ld R26, Y+ //
subi R28, 2 //
mov a, R27 //
out UDR, a //
mov a, R26 //
out UDR, a //
rjmp loop_s1_2 //
loop_s1_2:
clr R27 // jezeli zadzialala krancowka, kasujemy kroki
clr R26 //
st Y+, XH // i zapisujemy to w SRAM
st Y+, XL //
subi YL, 2 // --- /KRAŃCÓWKI ---
loop_s1_3: // --- CLK --- ustawienie pinu
//
push c // wstepne ustawienie na 1 pinu clk
ldi a, 1 //
rcall ustaw_bit_rejestru //
pop c //
cpi R27, 0 // sprawdzenie ilosci krokow do wykonania
brne loop_s1_4 //
cpi R26, 0 //
breq loop_s1_5 //
loop_s1_4: //
sbiw XH:XL, 1 // jezeli ilosc > 0 odjecie jednego kroku, zapisanie nowej ilosci
st Y+, XH //
st Y+, XL //
subi YL, 2 //
push c // i wpisanie 0 na pin clk
ldi a, 0 //
rcall ustaw_bit_rejestru //
pop c // --- /CLK ---
loop_s1_5:
cpi c, 28
breq loop_wypisanie_rejestrow
inc c
inc c
inc c
inc c
inc c
rjmp loop_s1
loop_wypisanie_rejestrow:
// mov a, rejestr1 // wyczyszczenie pinow input od krancowek w rejestrach
// cbr a, 0b00000000 //
// mov rejestr1, a //
//
mov a, rejestr2 //
cbr a, 0b10001100 //
mov rejestr2, a //
//
mov a, rejestr3 //
cbr a, 0b00110001 //
mov rejestr3, a //
//
mov a, rejestr4 //
cbr a, 0b11000110 //
mov rejestr4, a //
out PortD, rejestr1 // wypisanie rejestrow na porty
out PortC, rejestr2 //
out PortB, rejestr3 //
out PortA, rejestr4 //
ldi del00, 100 // delay 100 us
call delay_us //
mov a, rejestr1 // wyczyszczenie bitow CLK w rejestrach
sbr a, 0b10000000 //
mov rejestr1, a //
mov a, rejestr2 //
sbr a, 0b00010000 //
mov rejestr2, a //
mov a, rejestr3 //
sbr a, 0b01000010 //
mov rejestr3, a //
mov a, rejestr4 //
sbr a, 0b00001000 //
mov rejestr4, a //
out PortD, rejestr1 // wypisanie rejestrow na porty
out PortC, rejestr2 //
out PortB, rejestr3 //
out PortA, rejestr4 //
clr R29 // wywolanie opoznienia pomiedzy krokami
ldi R28, 0x0079 //
clr del01 //
ld del00, Y //
call delay //
loop_end:
rjmp loop
Używane w programie funkcje.
Ustaw_bit_rejestru - ustaw bit o numerze c rejestru złożonego z 4 bajtów (rejestr1, rejestr2, rejestr3, rejestr4). 0x0000 to rejestr1 itd. Ustawia stan w zależności od liczby wpisanej do a. a=1 ustaw 1, a=0 ustaw 0.
ustaw_bit_rejestru:
clr R29
ldi R28, 0x0000
ustaw_bit_rejestru_0:
cpi c, 9
brlo ustaw_bit_rejestru_1
subi c, 8
inc R28
rjmp ustaw_bit_rejestru_0
ustaw_bit_rejestru_1:
ldi b, 0b00000001
cpi a, 0
brne ustaw_bit_rejestru_3
ldi b, 0b11111110
ustaw_bit_rejestru_2: // ustaw 0
dec c
cpi c, 0
breq ustaw_bit_rejestru_4
sec
rol b
rjmp ustaw_bit_rejestru_2
ustaw_bit_rejestru_3: // ustaw 1
dec c
cpi c, 0
breq ustaw_bit_rejestru_5
clc
rol b
rjmp ustaw_bit_rejestru_3
ustaw_bit_rejestru_4: // and
ld c, Y
and c, b
rjmp ustaw_bit_rejestru_end
ustaw_bit_rejestru_5: // or
ld c, Y
or c, b
ustaw_bit_rejestru_end:
st Y, c
ret
S_k - sprawdza stan bitu o numerze c w rejestrze 4 bajtowym. Zwraca stan w zmiennej a.
s_k:
clr R29
ldi R28, 0x0000
s_k_0:
cpi c, 9
brlo s_k_1
subi c, 8
inc R28
rjmp s_k_0
s_k_1:
ldi b, 0b00000001
s_k_2:
dec c
cpi c, 0
breq s_k_3
lsl b
rjmp s_k_2
s_k_3:
ld c, Y+
mov c, r1
and c, b
cpi c, 0
breq s_k_end
cpi pom1, 0x4C
brne s_k_P
s_k_L:
sbr a, 0b00000010
rjmp s_k_end
s_k_P:
sbr a, 0b00000001
rjmp s_k_end
s_k_end:
ret
Odbiór z uart - jeżeli jest przerwanie RXC, pobiera daną, zapisuje ją do SRAM, zwiększa licznik pobranych danych (licznik też do sram). Jeżeli licznik==4, wykonuje s0.
odbior2:
cli
rcall zapisz_rejestry // zapisanie rejestrów r0 - r31 do sram
clr R29
ldi R28, 0x007A
ld a, Y
inc a
st Y, a
add R28, a
in b, UDR
st Y, b
cpi a, 4
breq s0
rcall wczytaj_rejestry // wczytanie rejestrów
sei
reti
s0 - interpretacja 4 bajtowego słowa które przyszło z PC:
s0:
clr a
clr R29
ldi R28, 0x007A
st Y+, a
ld pom1, Y+
ld pom2, Y+
ld pom3, Y+
ld pom4, Y+
s_0_T:
cpi pom2, 0x54 // "T" - ustgaw czas opóźnienia pomiędzy cyklami CLK
brne s_0_1 //
ldi R28, 0x0079 //
st Y+, pom4 //
rjmp s_end //
s_0_1:
cpi pom1, 1 // jezeli pierwszybajt jest numerem silnika, zwieksz adresy rejestrow
brne s_0_2 //
ldi a, 0 //
rjmp s_0_E //
s_0_2: //
cpi pom1, 2 //
brne s_0_3 //
ldi a, 5 //
rjmp s_0_E //
s_0_3: //
cpi pom1, 3 //
brne s_0_4 //
ldi a, 10 //
rjmp s_0_E //
s_0_4: //
cpi pom1, 4 //
brne s_0_5 //
ldi a, 15 //
rjmp s_0_E //
s_0_5: //
cpi pom1, 5 //
brne s_error //
ldi a, 20 //
rjmp s_0_E //
s_0_E:
cpi pom2, 0x45 // "E" - ustawienie enable/not enable dladanego silnika
brne s_1_1 //
inc a //
inc a //
inc a //
ldi R28, 0x0060 //
add R28, a //
clr a //
sbrc pom4, 0 //
ldi a, 0xFF //
st Y, a //
rjmp s_end //
s_1_1:
clr R29 // przyszla nowa wartosc krokow, wpisanie do rejestrow wartosci krokow
ldi R28, 0x0060 //
add R28, a //
st Y+, pom3 //
st Y+, pom4 //
st Y+, pom2 //
rjmp s_end //
s_error: // recieve error
ldi a, 0x45 // wyslanie "E" na USART
out UDR, a //
rcall wczytaj_rejestry //
sei //
reti //
s_end:
ldi a, 1 // wyslanie 1 na USART
out UDR, a //
rcall wczytaj_rejestry
sei
reti
Inne mniej znaczące funkcje:
ustawienia_poczatkowe:
ldi a, 0x50 // ustawienie "P" jako kierunku dla kazdego silnika
ldi R28, 0x0062 //
st Y, a //
std Y+5, a //
std Y+10, a //
std Y+15, a //
std Y+20, a //
ldi a, 0xFF // ustawienia ~EN na disabled (0xFF)
ldi R28, 0x0063 //
st Y, a //
std Y+5, a //
std Y+10, a //
std Y+15, a //
std Y+20, a //
ldi a, 0x99 // ustawienie bajtu rezerwowego (0x99)
ldi R28, 0x0064 //
st Y, a //
std Y+5, a //
std Y+10, a //
std Y+15, a //
std Y+20, a //
ldi R28, 0x0079 // ustawienie opoznienia kroku na 3 ms
ldi a, 2 //
st Y+, a //
clr R29 // wyczyszczenie uzywanych zmiennych
clr a //
ret
//////////////////////////////////////////
zapisz_rejestry:
sts 0x0090, R0
sts 0x0091, R1
sts 0x0092, R2
sts 0x0093, R3
sts 0x0094, R4
sts 0x0095, R5
sts 0x0096, R6
sts 0x0097, R7
sts 0x0098, R8
sts 0x0099, R9
sts 0x009A, R10
sts 0x009B, R11
sts 0x009C, R12
sts 0x009D, R13
sts 0x009E, R14
sts 0x009F, R15
sts 0x00A0, R16
sts 0x00A1, R17
sts 0x00A2, R18
sts 0x00A3, R19
sts 0x00A4, R20
sts 0x00A5, R21
sts 0x00A6, R22
sts 0x00A7, R23
sts 0x00A8, R24
sts 0x00A9, R25
sts 0x00AA, R26
sts 0x00AB, R27
sts 0x00AC, R28
sts 0x00AD, R29
sts 0x00AE, R30
sts 0x00AF, R31
ret
//////////////////////////////////////////
wczytaj_rejestry:
lds R0, 0x0090
lds R1, 0x0091
lds R2, 0x0092
lds R3, 0x0093
lds R4, 0x0094
lds R5, 0x0095
lds R6, 0x0096
lds R7, 0x0097
lds R8, 0x0098
lds R9, 0x0099
lds R10, 0x009A
lds R11, 0x009B
lds R12, 0x009C
lds R13, 0x009D
lds R14, 0x009E
lds R15, 0x009F
lds R16, 0x00A0
lds R17, 0x00A1
lds R18, 0x00A2
lds R19, 0x00A3
lds R20, 0x00A4
lds R21, 0x00A5
lds R22, 0x00A6
lds R23, 0x00A7
lds R24, 0x00A8
lds R25, 0x00A9
lds R26, 0x00AA
lds R27, 0x00AB
lds R28, 0x00AC
lds R29, 0x00AD
lds R30, 0x00AE
lds R31, 0x00AF
ret
//////////////////////////////////////////
delay:
delay_0:
ldi del1, 10 ; --- !!! 10 !!!
delay_1:
ldi del2, 100 ; --- !!! 100 !!!
delay_2:
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop ; ---
nop ; --- 1ms ma teoretycznie ok 1003us
nop ; ---
dec del2
cpi del2, 0
brne delay_2
dec del1
cpi del1, 0
brne delay_1
clz ; --- zeroj flage zera
sbiw del01:del00, 1 ; --- odejmij 1 od liczby 2bajtowej
brbs 1, delay_end ; --- przeskocz jezeli ustawiona flaga 0
brne delay_0
delay_end:
clz ; --- zeroj flage zera
ret
//////////////////////////////////////////
delay_us:
delay_us_1:
clz
nop
nop
nop
nop
nop
nop
nop
nop
clz
sbiw del01:del00, 1
brbs 1, delay_us_end
brne delay_us_1
delay_us_end:
clz ; --- zeroj flage zera
ret
Tak to wygląda, jak mam coś dowyjaśnić, piszcie. Wiem że sprawdzanie cudzego asm to mordęga:) dzieki za zainteresowanie i proszę o wyrozumiałość. Nie krzyczeć, podporządkuję się
Cytat:
Hmm piszesz w kompilatorze gcc ASMem... nie prościej odinstalować plugin i sprawdzić, czy po drodze nic nie dodał?
Wydaje mi się że nie da rady, ale nie sprawdzałem przeniesienia dll'a gcc gdzie indziej. A poza tym, jeżeli piszę w asm, to i tak to idzie przez gcc?
Cytat:
Przerwanie nie jest wykonywane od razu bez namysłu, tylko trzeba poczekac kilka cykli, ale to chyba wiesz.
No tak, ale ja mogłem po wysłaniu przez minutę nie pauzować tego programu i dopiero po spauzowaniu i ruszeniu krokowo startowało przerwanie.
Uf. Dużo. Tak jak mówiłem, jak będzie trzeba przeformatuję, ale może tak da rade.
Dzięki.