logo elektroda
logo elektroda
X
logo elektroda
Adblock/uBlockOrigin/AdGuard mogą powodować znikanie niektórych postów z powodu nowej reguły.

[AVR] [Bascom] PORTA.2 a PINA.2

Freddy 19 Gru 2009 18:53 2624 15
  • #1 7410300
    Freddy
    Poziom 43  
    Zmieszany niektórymi postami postanowiłem sprawdzić różnicę między komendami
    Set PORTA.2 oraz
    Set PINA.2

    Program w Bascomie banalny:
    
    $regfile = "m32def.dat"
    $crystal = 16000000
    Set Porta.2
    Set Pina.3
    


    kod wynikowy w asemblera:
    
    -----------------------------------
    AVR DISASSEMBLER LISTING
    Address Opcode  Instruction
    -----------------------------------
    000000  940C    	JMP L1
    000001  002A
    000002  9518    	RETI
    000003  0000    	NOP
    000004  9518    	RETI
    000005  0000    	NOP
    000006  9518    	RETI
    000007  0000    	NOP
    000008  9518    	RETI
    000009  0000    	NOP
    00000A  9518    	RETI
    00000B  0000    	NOP
    00000C  9518    	RETI
    00000D  0000    	NOP
    00000E  9518    	RETI
    00000F  0000    	NOP
    000010  9518    	RETI
    000011  0000    	NOP
    000012  9518    	RETI
    000013  0000    	NOP
    000014  9518    	RETI
    000015  0000    	NOP
    000016  9518    	RETI
    000017  0000    	NOP
    000018  9518    	RETI
    000019  0000    	NOP
    00001A  9518    	RETI
    00001B  0000    	NOP
    00001C  9518    	RETI
    00001D  0000    	NOP
    00001E  9518    	RETI
    00001F  0000    	NOP
    000020  9518    	RETI
    000021  0000    	NOP
    000022  9518    	RETI
    000023  0000    	NOP
    000024  9518    	RETI
    000025  0000    	NOP
    000026  9518    	RETI
    000027  0000    	NOP
    000028  9518    	RETI
    000029  0000    	NOP
    00002A  E58F    L1:	LDI R24,$5F
    00002B  BF8D    	OUT SPL,R24
    00002C  E4C0    	LDI YL,$40
    00002D  E3E8    	LDI ZL,$38
    00002E  2E4E    	MOV R4,ZL
    00002F  E088    	LDI R24,$08
    000030  BF8E    	OUT SPH,R24
    000031  E0D8    	LDI YH,$08
    000032  E0F8    	LDI ZH,$08
    000033  2E5F    	MOV R5,ZH
    000034  EFEE    	LDI ZL,$FE
    000035  E0F7    	LDI ZH,$07
    000036  E6A0    	LDI XL,$60
    000037  E0B0    	LDI XH,$00
    000038  95A8    	WDR
    000039  B784    	IN R24,MCUCSR
    00003A  2E08    	MOV R0,R24
    00003B  7F87    	ANDI R24,$F7
    00003C  BF84    	OUT MCUCSR,R24
    00003D  E188    	LDI R24,$18
    00003E  2799    	CLR R25
    00003F  BD81    	OUT WDTCR,R24
    000040  BD91    	OUT WDTCR,R25
    000041  2788    	CLR R24
    000042  938D    L2:	ST X+,R24
    000043  9731    	SBIW ZH:ZL,1
    000044  F7E9    	BRNE L2
    000045  2466    	CLR R6
    000046  9ADA    	SBI PORTA,PA2
    000047  9ACB    	SBI PINA,PINA3
    000048  9731    L3:	SBIW ZH:ZL,1
    000049  F7F1    	BRNE L3
    00004A  9508    	RET
    00004B  9468    	BSET 6
    00004C  F862    	BLD R6,2
    00004D  9508    	RET
    00004E  94E8    	BCLR 6
    00004F  F862    	BLD R6,2
    000050  9508    	RET
    


    Drugi przykład:
    $regfile = "m32def.dat"
    $crystal = 16000000
    Config Porta = Output
    Set Porta.2
    Set Pina.3

    kod wynikowy asemblera:
    -----------------------------------
    AVR DISASSEMBLER LISTING
    Address Opcode  Instruction
    -----------------------------------
    000000  940C    	JMP L1
    000001  002A
    000002  9518    	RETI
    000003  0000    	NOP
    000004  9518    	RETI
    000005  0000    	NOP
    000006  9518    	RETI
    000007  0000    	NOP
    000008  9518    	RETI
    000009  0000    	NOP
    00000A  9518    	RETI
    00000B  0000    	NOP
    00000C  9518    	RETI
    00000D  0000    	NOP
    00000E  9518    	RETI
    00000F  0000    	NOP
    000010  9518    	RETI
    000011  0000    	NOP
    000012  9518    	RETI
    000013  0000    	NOP
    000014  9518    	RETI
    000015  0000    	NOP
    000016  9518    	RETI
    000017  0000    	NOP
    000018  9518    	RETI
    000019  0000    	NOP
    00001A  9518    	RETI
    00001B  0000    	NOP
    00001C  9518    	RETI
    00001D  0000    	NOP
    00001E  9518    	RETI
    00001F  0000    	NOP
    000020  9518    	RETI
    000021  0000    	NOP
    000022  9518    	RETI
    000023  0000    	NOP
    000024  9518    	RETI
    000025  0000    	NOP
    000026  9518    	RETI
    000027  0000    	NOP
    000028  9518    	RETI
    000029  0000    	NOP
    00002A  E58F    L1:	LDI R24,$5F
    00002B  BF8D    	OUT SPL,R24
    00002C  E4C0    	LDI YL,$40
    00002D  E3E8    	LDI ZL,$38
    00002E  2E4E    	MOV R4,ZL
    00002F  E088    	LDI R24,$08
    000030  BF8E    	OUT SPH,R24
    000031  E0D8    	LDI YH,$08
    000032  E0F8    	LDI ZH,$08
    000033  2E5F    	MOV R5,ZH
    000034  EFEE    	LDI ZL,$FE
    000035  E0F7    	LDI ZH,$07
    000036  E6A0    	LDI XL,$60
    000037  E0B0    	LDI XH,$00
    000038  95A8    	WDR
    000039  B784    	IN R24,MCUCSR
    00003A  2E08    	MOV R0,R24
    00003B  7F87    	ANDI R24,$F7
    00003C  BF84    	OUT MCUCSR,R24
    00003D  E188    	LDI R24,$18
    00003E  2799    	CLR R25
    00003F  BD81    	OUT WDTCR,R24
    000040  BD91    	OUT WDTCR,R25
    000041  2788    	CLR R24
    000042  938D    L2:	ST X+,R24
    000043  9731    	SBIW ZH:ZL,1
    000044  F7E9    	BRNE L2
    000045  2466    	CLR R6
    000046  EF8F    	LDI R24,$FF
    000047  BB8A    	OUT DDRA,R24
    000048  9ADA    	SBI PORTA,PA2
    000049  9ACB    	SBI PINA,PINA3
    00004A  9731    L3:	SBIW ZH:ZL,1
    00004B  F7F1    	BRNE L3
    00004C  9508    	RET
    00004D  9468    	BSET 6
    00004E  F862    	BLD R6,2
    00004F  9508    	RET
    000050  94E8    	BCLR 6
    000051  F862    	BLD R6,2
    000052  9508    	RET
    



    Teraz prośba i pytanie do znawców asemblera o sprawdzenie i wykazanie różnicy.
    Pierwszy przykład celowo bez config porta = output.
  • Pomocny post
    #2 7410490
    Konto nie istnieje
    Poziom 1  
  • #3 7410512
    Freddy
    Poziom 43  
    Jeśli możesz porównaj jeszcze obydwa listingi, w jednym celowo nie było deklaracji :
    Config PortA=Output
  • #5 7410638
    Freddy
    Poziom 43  
    Wzrokowo to ja też widzę różnice.
    Chodzi o to aby pokazać jakie skutki ma coś takiego.
  • Pomocny post
    #6 7410660
    BoskiDialer
    Poziom 34  
    wpisanie 0xFF (=$FF) do DDRA ustawia wszystkie piny portu A jako wyjścia. Pierwsza linijka wczytuje do r24 wartość $FF, druga zapisuje wartość r24 do DDRA.
  • #7 7410724
    Freddy
    Poziom 43  
    OK, dzięki
    
    000048  9ADA       SBI PORTA,PA2 
    000049  9ACB       SBI PINA,PINA3 
    

    a powyższe różnice wiadome.
  • Pomocny post
    #8 7410772
    Konto nie istnieje
    Poziom 1  
  • #9 7412513
    Freddy
    Poziom 43  
    Jeśli pozwolisz zróbmy to samo z portem jako Input.
    Moim celem jest doświadczalne wykazanie, raz na zawsze, czy ma być PortA.2, czy PinA.2.
    W instrukcji jest co prawda napisane.
    
    So : when you want to use a pin as an input set it low first in the DDRx!
           and read with PINx and when you want to use the pin as output, write a 1 first
           and write the value to PORTx
    


    W bascomie:
    Cytat:

    $regfile = "m32def.dat"
    $crystal = 16000000
    Dim Aa As Byte

    Config Porta = Input

    Aa = Porta.2
    Aa = Pina.3


    Wynikowy w asemblerze :

    Cytat:
    -----------------------------------
    AVR DISASSEMBLER LISTING
    Address Opcode Instruction
    -----------------------------------
    000000 940C JMP L1
    000001 002A
    000002 9518 RETI
    000003 0000 NOP
    000004 9518 RETI
    000005 0000 NOP
    000006 9518 RETI
    000007 0000 NOP
    000008 9518 RETI
    000009 0000 NOP
    00000A 9518 RETI
    00000B 0000 NOP
    00000C 9518 RETI
    00000D 0000 NOP
    00000E 9518 RETI
    00000F 0000 NOP
    000010 9518 RETI
    000011 0000 NOP
    000012 9518 RETI
    000013 0000 NOP
    000014 9518 RETI
    000015 0000 NOP
    000016 9518 RETI
    000017 0000 NOP
    000018 9518 RETI
    000019 0000 NOP
    00001A 9518 RETI
    00001B 0000 NOP
    00001C 9518 RETI
    00001D 0000 NOP
    00001E 9518 RETI
    00001F 0000 NOP
    000020 9518 RETI
    000021 0000 NOP
    000022 9518 RETI
    000023 0000 NOP
    000024 9518 RETI
    000025 0000 NOP
    000026 9518 RETI
    000027 0000 NOP
    000028 9518 RETI
    000029 0000 NOP
    00002A E58F L1: LDI R24,$5F
    00002B BF8D OUT SPL,R24
    00002C E4C0 LDI YL,$40
    00002D E3E8 LDI ZL,$38
    00002E 2E4E MOV R4,ZL
    00002F E088 LDI R24,$08
    000030 BF8E OUT SPH,R24
    000031 E0D8 LDI YH,$08
    000032 E0F8 LDI ZH,$08
    000033 2E5F MOV R5,ZH
    000034 EFEE LDI ZL,$FE
    000035 E0F7 LDI ZH,$07
    000036 E6A0 LDI XL,$60
    000037 E0B0 LDI XH,$00
    000038 95A8 WDR
    000039 B784 IN R24,MCUCSR
    00003A 2E08 MOV R0,R24
    00003B 7F87 ANDI R24,$F7
    00003C BF84 OUT MCUCSR,R24
    00003D E188 LDI R24,$18
    00003E 2799 CLR R25
    00003F BD81 OUT WDTCR,R24
    000040 BD91 OUT WDTCR,R25
    000041 2788 CLR R24
    000042 938D L2: ST X+,R24
    000043 9731 SBIW ZH:ZL,1
    000044 F7E9 BRNE L2
    000045 2466 CLR R6
    000046 E080 LDI R24,$00
    000047 BB8A OUT DDRA,R24
    000048 E3AB LDI XL,$3B
    000049 E0B0 LDI XH,$00
    00004A 918C LD R24,X
    00004B FB82 BST R24,2
    00004C E6A0 LDI XL,$60
    00004D E0B0 LDI XH,$00
    00004E 2788 CLR R24
    00004F F980 BLD R24,0
    000050 938C ST X,R24
    000051 E3A9 LDI XL,$39
    000052 E0B0 LDI XH,$00
    000053 918C LD R24,X
    000054 FB83 BST R24,3
    000055 E6A0 LDI XL,$60
    000056 E0B0 LDI XH,$00
    000057 2788 CLR R24
    000058 F980 BLD R24,0
    000059 938C ST X,R24
    00005A 9731 L3: SBIW ZH:ZL,1
    00005B F7F1 BRNE L3
    00005C 9508 RET
    00005D 9468 BSET 6
    00005E F862 BLD R6,2
    00005F 9508 RET
    000060 94E8 BCLR 6
    000061 F862 BLD R6,2
    000062 9508 RET
  • Pomocny post
    #10 7412669
    BoskiDialer
    Poziom 34  
    // [...]
    
    // Config Porta = Input
    000046 E080 LDI R24,$00 
    000047 BB8A OUT DDRA,R24 
    
    // Aa = Porta.2
    000048 E3AB LDI XL,$3B 
    000049 E0B0 LDI XH,$00 
    00004A 918C LD R24,X 
    00004B FB82 BST R24,2 
    00004C E6A0 LDI XL,$60 
    00004D E0B0 LDI XH,$00 
    00004E 2788 CLR R24 
    00004F F980 BLD R24,0 
    000050 938C ST X,R24 
    
    // Aa = Pina.3
    000051 E3A9 LDI XL,$39 
    000052 E0B0 LDI XH,$00 
    000053 918C LD R24,X 
    000054 FB83 BST R24,3 
    000055 E6A0 LDI XL,$60 
    000056 E0B0 LDI XH,$00 
    000057 2788 CLR R24 
    000058 F980 BLD R24,0 
    000059 938C ST X,R24
    
    // [...]

    Tutaj "Config Porta = Input" zostało zamienione na wpisanie 0 do DDRA czyli zmienia piny na wejście - poza tym nic innego się nie dzieje.

    Swoją drogą zaskoczyła mnie nieoptymalność kodu wynikowego na przykładzie przeniesienia bitów - tam jednak są wczytane odpowiednie rejestry i przenoszony jest odpowiedni bit. Nic poza tym się nie dzieje.
  • #11 7412983
    Freddy
    Poziom 43  
    Czyli wniosek z tego jeden. (Ja stosuję się do zacytowanych zaleceń MCS)

    Przy Config PortA = Input można używać bezkarnie PortA.x oraz PinA.x
    natomiact przy Config PortA = Output tylko PortA

    Jeśli źle myślę, popraw mnie. Wartoby może "opublikować to jako przyklejone"
  • #12 7413114
    Konto nie istnieje
    Poziom 1  
  • #13 7413151
    Freddy
    Poziom 43  
    Żle napisałem, chodziło mi po Config PortA = input
    można używać
    
     aa = porta.2   lub
     aa = pina.2 
    

    i ma to to samo znaczenie.

    Natomiast po zastosowaniu Config Porta = Output
    
      Set Porta.2   jest dobre
    
      Set Pina.2   już nie za bardzo
    

    tak wynika chyba z listingów w asemblerze.
  • #14 7413182
    BoskiDialer
    Poziom 34  
    PortX (x dowolne) zawsze zawiera wartość jaką wystawia procesor na wyjście (dla pinu wyjściowego to będzie stan wysoki/niski, dla wejściowego pullup/open), natomiast PinX przy odczycie daje rzeczywisty stan panujący na pinie. Warunki zewnętrzne są w stanie zmienić tylko wartości w PinX (wpisanie wartości do tego rejestru w zależności od procesora nie powoduje nic, albo powoduje negację odpowiedniego bitu w PortX - patrz dokumentacja konkretnego procka).

    Rozpisując tabelarycznie:
    Zapis do DDR: ustawienie kierunku pinu (1 jako wyjście, 0 jako wejście)
    Odczyt z DDR: pobranie kierunku pinów
    Zapis do PORT: ustawienie wystawianej wartości (1/0: dla wyjścia: hi/lo, dla wejścia pullup/oc)
    Odczyt z PORT: pobranie wystawianej wartości. Nie zależy od warunków zewnętrznych
    Zapis do PIN: zależnie od procesora: nic, albo w nowszych zmienia bity PortX na przeciwne, jeśli odpowiedni bit we wpisywanej wartości jest ustawiony (inaczej: wpisanie PinX = a; jest wtedy traktowane PortX = PortX xor a;)
    Odczyt PIN: pobranie aktualnego stanu panującego na pinach.

    Używać PortA oraz PinA możesz zawsze, po prostu zawierają one wartości o różnym znaczeniu - pin może być wejściem/pullup, wtedy ddr=0, port=1, ale odczyt pin może zwrócić 0 jeśli pin jest ściągany do masy - i jako takie traktowanie ich zamiennie zawsze jest błędem. Jak widać po kodzie, kompilator nie śledzi tego czy pin jest wejściem czy wyjściem a więc użycie Portx zamiast Pinx lub odwrotnie nie jest poprawne:
    - chcąc pobrać stan wejść powinno się użyć PinX: użycie PortX będzie wyglądać tak, jak by piny nie zmieniały wartości;
    - chcąc np zmienić stan wyjścia na ustaloną wartość powinno się modyfikować wartość w PortX: użycie PinX nic nie da lub spowoduje wyzerowanie pozostałych bitów w portx (lub inne anomalie). W szczególności pobrana wartość powinna pochodzić z PortX - w przeciwnym przypadku jeśli inny pin był by wejściem z pullup ale był by tam stan niski, to w pinx pojawiło by się zero, które przepisane do portx wyłączyło by pullup.
    - chcąc pobrać stan wyjść większej różnicy nie ma pomiędzy odczytem z PortX a PinX, mimo wszystko powinno się odczytać z PortX. Jeśli stopień wyjściowy jest uszkodzony, to pomimo że pin był by wyjściem mogła by być różnica pomiędzy PortX a PinX. Dodatkowo jeśli uC posiada synchronizator dla każdego pinu, to wpisanie wartości do PortX po czym natychmiastowe odczytanie wartości z PinX nie zwróci tej samej wartości tylko dopiero w następnym cyklu.

    Ogólnie prosty podział: ddr oraz port do konfiguracji pinu oraz sterowania wyjściami (odczyt zawsze zwraca to co wpisano), pinx do odczytu wejść.
  • #15 7413297
    Freddy
    Poziom 43  
    BoskiDialer napisał:

    ...
    Rozpisując tabelarycznie:
    Zapis do DDR: ustawienie kierunku pinu (1 jako wyjście, 0 jako wejście)
    Odczyt z DDR: pobranie kierunku pinów
    Zapis do PORT: ustawienie wystawianej wartości (1/0: dla wyjścia: hi/lo, dla wejścia pullup/oc)
    Odczyt z PORT: pobranie wystawianej wartości. Nie zależy od warunków zewnętrznych
    Zapis do PIN: zależnie od procesora: nic, albo w nowszych zmienia bity PortX na przeciwne, jeśli odpowiedni bit we wpisywanej wartości jest ustawiony (inaczej: wpisanie PinX = a; jest wtedy traktowane PortX = PortX xor a;)
    Odczyt PIN: pobranie aktualnego stanu panującego na pinach.
    ...

    Ja rozumie zasady i się ich trzymam,. chodziło mi tylko o empiryczne sprawdzenie tego w plikach asm, a że nie znam asemblera, więc Was poprosiłem o pomoc.
    Może warto zamieścić te zasady jako "przyklejone"
  • Pomocny post
    #16 7413434
    BoskiDialer
    Poziom 34  
    Empirycznie mówiąc, kod w asm będzie różny dla pobierania z porta.2 a pobierania z pina.2. W twoim kodzie widać to na poniższych fragmentach:
    // wczytanie adresu rejestru PORTA do wskaźnika X
    000048 E3AB LDI XL,$3B 
    000049 E0B0 LDI XH,$00
    // [...]
    // wczytanie adresu rejesru PINA do wskaźnika X
    000051 E3A9 LDI XL,$39 
    000052 E0B0 LDI XH,$00
    // [...]

    Przy ustawianiu było o tyle łatwiej Tobie zauważyć różnicę, że pojawiło się PORTA i PINA zamiast ich adresu (przy czym tam adresy były by trochę inne co wynika z użycia sbi)
REKLAMA