Ciao forum.
Avrei bisogno di questo tipo di seriale, scritta in assembly per evitare che si creino malfunzionamenti dovuti ad altre fonti di interrupt. Almeno c`e` la speranza che sia molto meno influenzata rispetto ad una che usa dei delay in software per ogni bit in RTX, che non accetta altre operazioni durante il periodo di pausa. E se ci fossero interrupts, e` facile che sballa la lettura della seriale.
org 0x0000
goto Main
org 0x0004
;==============================================================================
; Interrupt Service Routine
;==============================================================================
movwf W_TEMP ; save W-reg
swapf STATUS,W ; doesn`t change STATUS bits
movwf STATUS_TEMP ; save STATUS reg
clrf STATUS ; bank 0
movf PCLATH,W ; get PCLATH
movwf P_ISR ; save PCLATH
movf FSR,W ; get FSR
movwf F_ISR ; save FSR
btfss INTCON,T0IE ; timer0 interrupt enabled?
goto ckExInt ; no, check something else
btfsc INTCON,T0IF ; timer0 interrupt?
goto ISR_SET ; yes, check what`s to move
ckExInt btfss INTCON,INTF ; RXD \"start bit\" interrupt?
goto ISR_NXT ; no, branch
bcf INTCON,INTE ; start reception and stop interrupts
bcf INTCON,INTF ; clear external interrupt flag
bcf TXFLAG ; indicate RX in progress
movlw 10 ; (1 start + 8 data + 1 stop)
movwf CHARCNT ; initialize RX bit counter
bcf INTCON,T0IF ; clear TMR0 interrupt flag
movlw -51 ; 1/2 bit time
movwf TMR0
bsf INTCON,T0IE ; start the timer0
goto ISR_NXT ; wait next timer0 interrupt
ISR_SET bcf INTCON,T0IF ; clear TMR0 interrupt flag
movlw -103 ; setup for next int
movwf TMR0
btfsc TXFLAG ; TX in progress?
goto ISR_TX ; no, branch
ISR_RX movf WR_PTR,W ; get WR_PTR (RXBUFF + 00..07)
movwf FSR ; setup indirect address
clrc ; clear Carry, assume data = 0
btfsc RXD ; TRPIN = 0 ?
setc ; no, set Carry, data = 1
rrf INDF,F ; shift bit into our character
decfsz CHARCNT,F ; all 10 bits?
goto ISR_NXT ; no, branch
rlf INDF,F ; yes, get rid of the stop bit
incf WR_PTR,W ; W = WR_PTR + 1
sublw buffer+BUFLEN ; this works for 20..27
xorwf RD_PTR,W ; WR_PTR+1 = RD_PTR (full)?
skpz ; yes, ignore new character
incf WR_PTR,F
bcf WR_PTR,3
goto END_TX
ISR_TX movf CHARCNT,W ; get TX bit count
bnz ISR_TX0 ; no, branch, send next bit
movlw 10 ; 10 bits (start + 8 data + st
movwf CHARCNT ; initialize TX bit counter
goto ISR_TX1 ; send the start bit
ISR_TX0 rrf RXCHAR,F ; shift lsb into C
bsf RXCHAR,7 ; set bit 7 for stop bits
skpnc ; skip if C=0
bsf TXD ; set TX pin
skpc ; skip if C=1
ISR_TX1 bcf TXD ; clr TX pin
decfsz CHARCNT,F ; last bit shifted out?
goto ISR_NXT
END_TX bcf TXFLAG ; yes, indicate end of TX
bcf INTCON,T0IE ; stop timer0, transmission ended
bsf INTCON,INTE ; permit reception
ISR_NXT
banksel PIR1 ; select bank 0
btfss PIR1,TMR1IF ; If TMR1IF is set Then
goto ISR_XIT ; no, then return
call reloadTMR1 ; reload the Timer1
bcf PIR1,TMR1IF ; PIR1.TMR1IF = 0
decfsz ticks,F ; if ticks zero
goto ISR_XIT ; no, see for the next
bsf zeroX ; signalize reached zero count
movlw TICKSVAL ; reload ticks
movwf ticks
ISR_XIT movf F_ISR,W
movwf FSR ; restore FSR
movf P_ISR,W
movwf PCLATH ; restore PCLATH
swapf STATUS_TEMP,W
movwf STATUS ; restore STATUS
swapf W_TEMP,F ; don`t screw up STATUS
swapf W_TEMP,W ; restore W-reg
retfie ; return from interrupt
ATTENZIONE il codice e` formattato per compatibilita` all ` impaginazione di grix !!! (Gli apostrofi sono stati cambiati)
Al naturale lo si puo` scaricare da qui
http://www.grix.it/UserFiles/picmicro675/File/TransitFiles/s… Penso che questo esempio possa funzionare anche su altri micro. Di sicuro su un 12F629 senza modifiche. Comunque la simulazione con Proteus funziona egregiamente, mentre se la provo in hardware, non lampeggia nemmeno il LED al GP4.
C`e` qualcuno capace di notare dove sta l \' errore ?
Per quello che ho potuto riscontrare, nelle mie esperienze, a volte ci sono problemi se i piedini sono lasciati liberi, che il simulatore non denota. Forse ci vuole almeno un collegamento a positivo o a massa con una resistenza.
Anno nuovo, forum nuovo.
Mi sa che lascio.
marsram
postato il: 10.06.2018, alle ore 15:09
Senza entrare nei dettagli del listato:
1. - cosa vuol dire "se la provo in hardware, non lampeggia nemmeno il LED al GP4" ? Come fai a "provarlo in hardware" se la lista NON si compila, dato che MPASM rende immediatamente un errore formale?
2.- lascia perplessi anche questo pezzo
GetTable
movf PTRH,W
movwf PCLATH
movf PTRL,W
movwf PCL
Main call init
Dopo aver modificato il PC, chiami la routine di inizializzazione?
Non entro nei dettagli del sorgente.
- Primo, perchè non ho idea del motivo di avere ben due timer in interrupt per trasmettere un segnale asincrono, dove di timer ne basta uno.
- Secondo, e fondamentale, perchè senza un flow chart, recuperare cosa si vuole che faccia il programma non è una cosa da poco.
Se hai un flow chart sensato, se ne può discutere.
- Terzo, perchè ci sono punti altamente critici, come accendere o spegnere flag IE di interrupt non sincroni nella routine di interruzione, cosa che può facilmente portare a crash.
picmicro675
postato il: 10.06.2018, alle ore 18:19
1) mpasm compila senza errore. Altrimenti come posso dire che lo carico in hardware.
2) la routine GetTable non ha un seguito dato che va a caricare una tabella di RETW "carattere ASCII".
Se serve potrei includere il listing del programma.
Comunque nel sorgente intero ho usato un metodo simile per ricavare le tabelle dei messaggi da inviare alla seriale. Migliore che il modo di inserire questa macro.
Quella è usata dalla routine Put232. In pratica il Program Counter viene indirizzato ad una locazione che deve ritornare con un valore ASCII in W, al punto che è stato salvato sullo stack.
In fondo ho ripreso un sorgente pubblicato su internet con eventuali modifiche per lo scopo che va ben oltre il semplice RTX della seriale.
Filename: 12F675 Serial Demo 3.asm ;* Author: Mike McLaren, K8LH (k8lh@arrl.net)
Avrei bisogno una critica, per capire se ci sono gravi sintomi di sbadataggine.
a) il timer0 serve per dare il periodo di pausa tra due bit trasmessi o ricevuti. Di fatto si usa il prescaler a 1:8 poi 104 cicli per un totale di 833 uSec, che si avvicina ai 1200 bps.
b) il timer1 è usato per tenere una cadenza di un secondo che in altre parti del programma sono usate per contare periodi più lunghi. Ora comunque si può avere solo il massimo di mezzo secondo e compensare con un secondo conteggio. Scelto al periodo più lungo proprio al caso di non disturbare tanto.
Nel qui caso viene fatto uso solo per segnalare se il micro sta facendo il suo lavoro.
Poi ci sono le preferenze di non tenere attivi gli interrupt che non devono disturbare il percorso voluto. Infatti se sto ricevendo un byte, non deve esistere una interruzione da esterno, visto che posso solo gestire in half duplex. E quando non c'è trasmissione il timer0 dovrebbe stare fermo fino a che non è richiesto di fare le cadenze di trasmissione.
Perchè nella sua completezza, il programma prevede di controllare almeno 4 interrupts. Dei quali i rimanenti 2 dovrei anche esaminare se posso filtrare i fronti per diminuire il carico dei periodi in ISR.
Ultimo, magari fosse semplice usare i flow-chart. Dopo anni, comincio ora a capire come si usa il C, figuriamoci se mi metto a capire anche il flow-chart.
Anno nuovo, forum nuovo.
Mi sa che lascio.
marsram
postato il: 10.06.2018, alle ore 18:54
Se non usi un flow chart, che non richiede alcuna comprensione particolare, essendo solo la rappresentazione grafica del percorso logico del programma, come puoi pensare di risolvere problemi appena poco più che semplicistici? Come pensi di organizzare senza? Se hai una capacità di astrazione elevata da QI 160, ci può anche stare, ma in generale non esiste un buon programmatore che non usi un flowchart.
Nei Midrange NON esiste la possibilità di un interrupt di interromperne un altro. Fino a che l'interruzione attuale NON è stata chiusa dal retfie, qualsiasi altra chiamata è in attesa.
Quindi NON può esserci alcun problema di interferenze.
Peraltro, se disabiliti l'interrupt di Timer0 NON fermi per niente il conteggio del timer e neppure eviti che il flag IF vada a 1 all'overflow. Timer0 NON si può spegnere. Timer1 e Timer2 si, ma Timer0 proprio NO.
Se accendi e spegni flag durante la gestione dell'interrupt e per caso la periferica ha attivato una interruzione, all'uscita, , se non hai cancellato anche il flag IF, ti ritrovi immediatamente dentro di nuovo, con qualche possibile problemino di gestione.
Per venirne a capo, usa MPLAB-SIM o ancora meglio un micro con ICD e in una oretta hai risolto il problema.
picmicro675
postato il: 10.06.2018, alle ore 21:19
marsram: Se non usi un flow chart, che non richiede alcuna comprensione particolare
Su questo convengo che devo prenderne atto. Il mio metodo si basa su try&fail, fino che trovo il difetto.
marsram: Nei Midrange NON esiste la possibilità di un interrupt di interromperne un altro.
Infatti, solo che se devo guidare una sequenza di operazioni, quindi gli altri interrupt non devono riempirmi l' ISR di richieste inutili. Come infatti dici, finito un retfie mi ritrovo magari un altro interrupt dall' esterno che non deve essere preso in considerazione.
marsram: Quindi NON può esserci alcun problema di interferenze.
Questo è ovvio che durante un ciclo di ISR non ci sono altri interrupt. Ma appare che appena si completa il ciclo rischio di ritornarci subito.
marsram: neppure eviti che il flag IF vada a 1 all'overflow. Timer0 NON si può spegnere.
Comprendo che non si fermi, comunque posso escluderlo dal causare un interrupt.
marsram: Se accendi e spegni flag durante la gestione dell'interrupt e per caso la periferica ha attivato una interruzione, all'uscita, , se non hai cancellato anche il flag IF, ti ritrovi immediatamente dentro di nuovo, con qualche possibile problemino di gestione.
Come sto cercando di gestire, per non essere sovraccaricato da interruts. Specialmente se non servono.
marsram: Per venirne a capo, usa MPLAB-SIM
Come forse citato in altro argomento, ho un certo numero di questi micro e quelli con il debug non ho ancora preso una decisione.
Trovo tal programma scomodo da usare. In particolar modo quando si deve lavorare con stimoli di natura sequenziale, che molto probabilmente richiede un certo apprendimento nella programmazione del simulatore.
Non penso che un simulatore come Proteus faccia di meno. Come pure si possa anche provare con un Real Pic simulator, con qualche difficoltà anche lì nel capire come si possa usare la comunicazione seriale e poter leggere il disassemblato, che è privo ormai di tutto quello che potrebbe dare un coff.
Comunque farò degli esperimenti anche con MPLAB-SIM, che pare che con MPLABX ci sia anche una possibilità di interfacciare un terminale con il porgramma per dare gli stimoli che avrei bisogno di provare.
Anno nuovo, forum nuovo.
Mi sa che lascio.
picmicro675
postato il: 10.06.2018, alle ore 21:25
Ad ogni modo, se qualcuno volesse provarlo, con il simulatore che sa usare meglio, io ho messo a disposizione il necessario. Con l' eventuale possibilità di variare anche le cose che si ritengono sbagliate.
Anno nuovo, forum nuovo.
Mi sa che lascio.
picmicro675
postato il: 12.06.2018, alle ore 13:51
Nelle ultime prove, togliendo tutti gli interrpts, meno quello del Timer1, ancora non si vede il segnale sul piedino dedicato. Direi che sebbene GIE e TMR1IE abilitati non avviene un interrupt da arrivare in ISR.
Anno nuovo, forum nuovo.
Mi sa che lascio.
marsram
postato il: 12.06.2018, alle ore 18:04
Insisto che simulatori come Proteus e simili NON SERVONO A NIENTE. Non sono mai serviti a niente e mai a niente serviranno. Forse sul'analogica o piccole logiche, più per didattica che altro.
Ti dovrebbe essere chiaro, ormai: se nel proteus va e nell'hardware no, vuol semplicemente dire che la risposta di proteus è inaffidabile e inutile.
Infatti, provato, l'int di Timer1 funge.
MPLAB. Va bene anche l'IDE 8.92 senza passare a MPLABX che è meno immediato.
- Crea un project con il wizard di MPLAB
- seleziona MPSIM come simulatore
- modifica il sorgente in modo da avere solo l'interrupt di Timer1
io ho provato con queste poche modifiche
goto ISR_NXT
btfss INTCON,T0IE ; timer0 interrupt enabled?
Put232 btfsc TXFLAG ; busy?
goto Put232 ; yes, branch and wait
; bsf INTCON,T0IE ; start timer0, new transmission
- fallo compilare con Make in assoluto
- metti un breakpoint all'inizio dell routine di interrupt
Se vai Step Into vai passo passo e vedi cosa fanno le singole istruzioni.
Però puoi lanciare l'esecuzione con Run.
L'esecuzione si ferma al break point, ovvero Timer1 genera una richiesta di interruzione.
Ugualmente funge se attivi anche il Timer0.
Ora occorre andare Step Into per vedere passo passo cosa fa il programma per la trasmissione e se è corretto il procedimento logico.
Come aiuto accendi con View la finestra Special Function Register e quella Program Memory e controlli che le cose giuste vadano nei giusti registri al giusto momento.
Fatto questo, potrai provare la ricezione.
Non dovrebbe richiedere neppure un eccesso di tempo.
picmicro675
postato il: 12.06.2018, alle ore 19:57
Vediamo le cose in sincrono. Ho provato con Proteus e con Real Pic Sim, sicuramente sto facendo la cosa sbagliata.
Avviato MPLAB IDE 8.60
1) Ricopiato il sorgente di cui sopra con le correzioni date dal caso che grix storpia.
2) Commentato dalla riga 68 alla 120 inclusa e ricompilato
3) Messo un breakpoint alla linea 129, dato il RUN e funziona arrivando alla detta linea.
4) Fatto una prova a caricare il sorgente come sopra descritto ma non c'è segnale sul GP4, come sarebbe da aspettarsi. Infatti non ho valutato che il _Print è bloccante. Commentato la linea 225 e ricompilato. I breakpoint arrivano alla linea 233 e alla 236. Ora lo carico nel micro
5) caricato, ma non appare nessun segnale sul piedino 3.
6) ho provato anche a caricare l' hex su due micro. Comincio ad avere dei sospetti su questi due micro (forse troppo bistrattati
7) Ho caricato l' hex su un terzo micro vergine e il lampeggio avviene
Credo che farò ancora qualche altra prova domani. Forse ho scoperto la causa principale.
Anno nuovo, forum nuovo.
Mi sa che lascio.
agric
postato il: 13.06.2018, alle ore 11:31
marsram:
Timer0 NON si può spegnere.
Non lo si può spegnere Ma lo si può fermare.
Utilizzatndo il flag per selezionare il clk di sistema o la modalità count da esterno.
In count su pin esterno il conteggio del timer0 si ferma
Tra l'altro se il pin esterno è usato in analogico non ci sono problemi io ho utilizzato questo sistema per tenere fermo o e far continuare il conteggio del timer nel cronometro utilizzato per spiegare liinterrupt in un mio vecchio tutorial
meglio essere un granello di pepe che una cacca d'asino
Come utente anonimo puoi leggere il contenuto di questo forum ma per aprire una discussione
o per partecipare ad una discussione esistente devi essere registrato ed accedere al sito