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

PIC 16F88 - Jak poprawnie zaprogramować mruganie diodą na RA1?

august_ 06 Sty 2006 10:36 2073 7
REKLAMA
  • #1 2151710
    august_
    Poziom 27  
    Posty: 1081
    Pomógł: 70
    Ocena: 47
    Witam!
    Zacząłem wczoraj naukę PICów od strony praktycznej.
    Kupiłem debugger.
    Mam problem z procesorem PIC 16F88. Tzn, doszedłem jak go podłączyć, jak skonfigurować, teraz programuje się bez problemu, umiem zapalić i zgasić diodę podłączoną do RA1, tylko chciałem żeby ta dioda mrugała...

    i wstawiam w kod taką pętlę:

    
    movlw	0xFF
    movwf	COUNT1
    
    LOOP_1
    DECFSZ	COUNT1,1
    GOTO LOOP_1
    


    i w tejże pętli procesor się "zapętla", tzn. nie wiem tego napewno, bo nie potrafię uruchomić debuggera jeszcze (ale to później).

    Stan portu RA1 pozostaje taki jaki był przed wejściem do pętli.

    Mruganie diodą udało mi się osiągnąć tylko poprzez wstawienie

    
    movlw	0xFF
    movwf	PORTA
    .
    .
    .
    
    movlw	0x00
    movwf	PORTA
    .
    .
    .
    


    Czy ktoś ma jakiś pomysł co robię nie tak?
    Dziękuję i pozdrawiam
    Michał

    Dodano po 22 [minuty]:

    Przez to przechodzi:

    
    LOOP_1
    DECFSZ	COUNT1,1
    GOTO OUT
    GOTO LOOP_1
    OUT
    


    A przez to nie:

    
    LOOP_1
    DECFSZ	COUNT1,1
    GOTO LOOP_1
    GOTO OUT
    OUT
    
  • REKLAMA
  • #2 2151850
    Darekg
    Poziom 17  
    Posty: 210
    Pomógł: 27
    Ocena: 11
    Tak powinno być:
    • movlw d'250'
      movwf COUNT1
      clrf TRISA,1
      clrf PORTA

      LOOP_1
      decfsz COUNT1,1
      goto LOOP_1
      comf PORTA,1
      movlw d'250'
      movwf COUNT1
      goto LOOP_1


    Na początku inicjalizacja licznika COUNT1 oraz portów, jako wyjść i wyzerowania portu PORTA. Dalej program wchodzi w petlę (niekończącą się), gdzie jest odejmowana wartość z licznika COUNT1. Tutaj taka uwaga instrukcja decfsz odejmuje wartość rejestru i sprawdza. Jeśli wartość tego rejestru jest równa 0, to omija nastepną instrukcję i skacze do nastepnej instrukcji. Jesli zaś wartość rejestru po odjęciu jest rózna od zera, to wykonuje rozkaz bezpośrednio po sobie. Czyli jeśli w tym przypadku poczatkowa wartość jest 250 i program wykona rozkaz

    • decfsz COUNT1,1

    to nastepnym krokiem będzie wykonanie skoku do etykiety LOOP_1.
    To tak obrazowo jak bedzie wykonywane odliczanie rejestru COUNT1.

    później sprawa prosta rozkaz comf neguje zawartość portu PORTA, czyli jak zainicjowaliśmy wartością 0 to po przejściu przez ten rozkaz wszystkie wyjścia na PORTA bedą miały ustawioną 1 na wyjściu.

    itd.

    Oczywiście czestotliwość błysków bedziesz miał bardzo dużą. Nie wiem, na jakim kwarcu to robisz, ale jak byś chciał, aby miganie to było wolniejsze, to trzeba zrobić więcej takich opóźnień pomiędzy negowaniem portu.

    Miłej zabawy[/url]
  • REKLAMA
  • #3 2151945
    diag
    Poziom 29  
    Posty: 1401
    Pomógł: 45
    Ocena: 209
    Pmiętaj o bankowaniu, TRIS jest na 1.
  • REKLAMA
  • #4 2152110
    august_
    Poziom 27  
    Posty: 1081
    Pomógł: 70
    Ocena: 47
    Dzięki, miałem ustawionego TRISA, i o bankowaniu pamiętam.. ale jednak coś jest nie tak. Udało mi się zamrugać diodą przez pętle.. ale wszystko jest jakieś takie dziwne.

    Czy przypadkiem nie trzeba wyłączyć jeszcze przetworników A/D?

    A żeby było śmieszniej to załączam kod, gdy są dwie linijki, które wskazałem - dioda mruga, gdy nie ma, nie mruga... ja żadnego powiązania nie widzę... ehh... co to może być?

    
    ;*****Set up the Constants**** 
    
    STATUS         equ       03h                 ;Address of the STATUS register
    TRISA          equ       85h                 ;Address of the tristate register for port A
    PORTA          equ       05h                 ;Address of Port A
    COUNT1         equ       08h                 ;First counter for our delay loops
    COUNT2         equ       09h                 ;Second counter for our delay loops 
    COUNT3         equ       0Ah 
    COUNT4		equ			0Bh
    ANSEL		   equ       09Bh
    
    ;****Set up the port**** 
    
    	bsf			STATUS,5       ;Switch to Bank 1
        movlw		00h            ;Set the Port A pins
        movwf		TRISA          ;to output.
        bcf			STATUS,5       ;Switch back to Bank 0 
    
    
    ;****Turn the LED on**** 
    
    Start
    
    	movlw d'250'
    	movwf COUNT1
    
    movlw 0xFF
    movwf PORTA
    
    ;clrf PORTA
    
    LOOP_1
    
    movlw d'250'
    movwf COUNT2
    		LOOP_2
    			movlw d'250'					;jesli tego nie ma to dioda mruga raz
    			movwf COUNT3					;a jesli jest, to dioda slabo pulsuje
    					
    							clrf PORTA
    					
    		decfsz	COUNT2,1
    		goto	LOOP_2
    decfsz COUNT1,1
    goto LOOP_1
    
    movlw d'250'
    movwf COUNT1
    goto LOOP_1 
    
    ;goto Start
    
    
    end
    


    Dodano po 10 [minuty]:

    W skrócie:
    Okazało się, że u mnie COUNT3 jest pod 0Ah,
    Nie wiem czy to ma związek, ale w datasheet jest pod 0Ah PCLATH
    i Jeśli tam wpiszę FF to wtedy mruga...
    Ten PCLATH jest w każdym banku..
  • Pomocny post
    #5 2152399
    elektryk
    Poziom 42  
    Posty: 11029
    Pomógł: 439
    Ocena: 241
    august_ napisał:
    Okazało się, że u mnie COUNT3 jest pod 0Ah,
    Nie wiem czy to ma związek, ale w datasheet jest pod 0Ah PCLATH
    i Jeśli tam wpiszę FF to wtedy mruga...
    Ten PCLATH jest w każdym banku..
    Może czas zacząć czytać ze zrozumieniem datasheeta? Już kolega jest bardzo blisko w znalezieniu rozwiązania. Proponuje zagłębić się w roździał 2.2 specyfikacji.

    PS dodatkowo sugeruje używać jako argumentu instrukcji o nazwie "d" mnemoników "w" i "f" (ułatwia to zrozumienie algorytmu) zamiast nic nie mówiącego "1". Pozatym domyślnie jest przyjęte że wynik jest zapisywany w rejestrze na którym się operuje i nie trzeba wtedy tego dodatkowo określać.
  • REKLAMA
  • #6 2153062
    Jacu$
    Poziom 27  
    Posty: 730
    Pomógł: 119
    Ocena: 26
    :arrow: august_
    Nie możesz wykorzystywać do przechowywania zmiennych programu komórek, które fizycznie nie są zaimplementowane w mikrokontrolerze. Do Twojej dyspozycji jest obszar pamięci od adresu $20 do $7F (GPR - general purpose register) czyli 96 bajtów w banku 0.
    Programu nie analizowałem więc nie powiem Ci na 100% czy jak zmienisz adresy zmiennych to ruszy z kopyta.
  • #7 2153780
    mkaczor
    Poziom 16  
    Posty: 97
    Pomógł: 13
    W µkontrolerach Microchip'a "na dzień dobry" port A jest zdefiniowany jako analogowy port wejściowy przetwornika A/D. Należy przestawić port A na cyfrowy (chyba rejestr ADCON1) a później ustawić port A jako wyjściowy. Być może LED mruga ale tak szybko, że dla oka jest to ciągłe świecenie. Wprowadź jakieś opóźnienie (pętlę w pętli). Ponadto w przykładzie na samym początku tylko raz włączasz diodę

    movlw 0xFF
    movwf PORTA

    a później już tylko permanentnie wyłączasz wyłączoną diodę

    CLRF PORTA

    Powodzenia
  • #8 2155698
    august_
    Poziom 27  
    Posty: 1081
    Pomógł: 70
    Ocena: 47
    Witam ponownie!
    Dziękuję wszystkim za pomoc. Udało się to uruchomić :)
    Zacząłem od zrobienia porządnego algorytmu, napisałem sobie wszystko na kartce, przestudiowałem datasheeta... co prawda ciężko się to czyta, ale można się dużo rzeczy dowiedzieć :)

    Niemniej jednak:
    - wyrzuciłem swoje zmienne ponad adres 20h
    - skonfigurowałem odpowiednio port A (ale to chyba już było zrobione, bo dało się sterować diodą).
    Ale największe błędy które popełniłem to:
    - rzuciłem się na to programowanie jak szczerbaty na suchary, pętle były kompletnie do kitu, jednak gdy nawet napisałem je na podstawie algorytmu... to i tak dioda albo się świeciła, albo nie... zwiększałem ilość pętli, bo myślałem, że mruga za szybko i tego nie widzę...
    a ona migała za wolno... i dlatego myślałem, że nie przechodzi przez pętlę..

    Procesor chodzi na wewnętrznym oscylatorze RC 31.25kHz.

    Gdy wstawiłem kilkaset NOP to było widać mruganie - i to całkiem wolno.
    Także wystarczyła nawet jedna pętla opóźniająca, żeby dało się to zaobserwować.
    A gdy wstawiłem pętlę w pętli to się świeciło non stop... tzn. tak mi się wydawało, bo mi się nie chciało czekać.

    No ale koniec końców mi się udało i jestem bogatszy o kilka doświadczeń... :)

    A oto mój wypocony listing:

    
    ;****************************************************************************************
    ;																						*
    ;	Name:			Blinking diode														*
    ;	Rev:			1.0																	*
    ;	Date: 			07-01-2006															*
    ;	uC:				PIC16F88															*
    ;	Description:	Blinking diode connected to RA1 less than once a second.			*
    ;																						*
    ;****************************************************************************************
    
    ;*****Set up the Constants**** 
    
    	STATUS	equ		03h                 ;Address of the STATUS register
    	TRISA	equ		85h                 ;Address of the tristate register for port A
    	PORTA	equ		05h                 ;Address of Port A
    	COUNT1	equ		7Fh                 ;First counter for our delay loops
    	COUNT2	equ		29h                 ;Second counter for our delay loops 
    	ANSEL	equ		9Bh					;Analog select register
    	ADCON0	equ		1Fh					;A/D Control register 0
    	ADCON1	equ		9Fh					;A/D Control register 1
    	OSCCON	equ		8Fh					;Bits configured to run from intrc (31.25kHz)
    
    ;****Set up the port**** 
    
    	bsf		STATUS,5       				;Switch to Bank 1
        movlw	00h           				;Set the Port A pins
        movwf	TRISA          				;	to outputs
        movlw	00h            				;Turn off ADC
        movwf	ANSEL          				;		
    	clrf	ADCON1						;
    	bcf		STATUS,5       				;Switch back to Bank 0
    	clrf	ADCON0						;Configure all pins as digital 
    
    ;****Main program****
    
    Start
    	movlw	0x10						;Move 10h to COUNT1
    	movwf	COUNT1						;
    	movlw	0x01						;Move 01h to COUNT2
    	movwf	COUNT2						;
    
    Loop_1									;Start Loop_1
    	decfsz	COUNT1,f					;Decrement COUNT1 and skip next instruction if it's zero
    	goto	Loop_2						;Goto Loop_2 (always jumping when COUNT1 != 0)
    	goto	Change_led					;Goto Change_led (jumping only when COUNT1 == 0)
    
    Loop_2									;Start Loop_2 (This Loop is inside Loop_1)
    	decfsz	COUNT2,f					;Decrement COUNT2 and skip next instruction if it's zero
    	goto	Loop_2						;Goto Loop_2 (always jumping when COUNT1 != 0)
    	goto	Loop_1						;Goto Loop_1 (jumping only when COUNT1 == 0)
    
    Change_led								;
    	comf	PORTA						;Change state of all PORTA pins
    	goto	Start						;Go to Start
    
    end										;End of program
    


    Pozdrawiam i dziękuję jeszcze raz
    Michał

Podsumowanie tematu

✨ Dyskusja dotyczy problemu z poprawnym zaprogramowaniem migania diodą podłączoną do pinu RA1 mikrokontrolera PIC 16F88. Użytkownik miał trudności z implementacją opóźnienia w asemblerze, stosując pętlę z instrukcją DECFSZ, która nie działała zgodnie z oczekiwaniami. Wskazano, że port A domyślnie jest skonfigurowany jako wejście analogowe przetwornika A/D i należy wyłączyć funkcję A/D (np. przez rejestr ANSEL) oraz ustawić odpowiednio rejestry TRISA i PORTA, aby port działał jako cyfrowe wyjście. Zwrócono uwagę na bankowanie pamięci i poprawne adresowanie zmiennych w zakresie dostępnej pamięci GPR (adresy od 0x20 do 0x7F). Zaproponowano poprawny algorytm pętli opóźniającej z negacją stanu pinu RA1 za pomocą instrukcji COMF, co pozwala na miganie diodą. Użytkownik potwierdził, że po poprawnym skonfigurowaniu portów, wyłączeniu przetwornika A/D oraz zastosowaniu odpowiednich pętli opóźniających dioda zaczęła migać, choć z powodu niskiej częstotliwości oscylatora wewnętrznego RC (31.25 kHz) miganie było wolne. Wskazano, że dodanie pętli opóźniających lub instrukcji NOP pozwala na uzyskanie widocznego efektu migania.
Podsumowanie AI na podstawie dyskusji. Może zawierać błędy.
REKLAMA