Cos'è ElectroYou | Login Iscriviti

ElectroYou - la comunità dei professionisti del mondo elettrico

Registro CMCON PIC16F628

Raccolta di codici sorgenti

Moderatore: Foto UtentePaolino

0
voti

[1] Registro CMCON PIC16F628

Messaggioda Foto UtenteDavide90 » 14 set 2014, 11:52

Salve a tutti, sto usando il compilatore XC8 con MPLAB, ho scritto un firmware per il PIC 16f628. Uso il quarzo interno al PIC a 4 MHz.

Ho la necessità di usare le porte RA0,RA1,RA2,RA3 del PIC come input, leggendo il datasheet ho impostato il registro
Codice: Seleziona tutto
CMCON = 0x07


e quindi

Codice: Seleziona tutto
TRISA=0b00001111


Ho provato a simulare il firmware con il simulatore PIC Simulator IDE , il registro CMCON non viene mai impostato come specificato da me .

Ho provato anche a settare
Codice: Seleziona tutto
TRISA=0x111

ma con il medesimo risultato.
Devo specificare qualcos'altro?
O forse non è proprio possibile usare le porte A come Input quando è usato un oscillatore interno(anche se nel datasheet non ho trovato nulla a riguardo)?

Grazie a tutti!
Avatar utente
Foto UtenteDavide90
29 6
Frequentatore
Frequentatore
 
Messaggi: 130
Iscritto il: 5 lug 2012, 11:34

0
voti

[2] Re: Registro CMCON PIC16F628

Messaggioda Foto UtenteWALTERmwp » 14 set 2014, 15:12

Ciao Foto UtenteDavide90, i "pezzi" di codice così riportati, di per sé non credo siano indicativi.
Se il simulatore introduce qualche "differenza" non te lo saprei dire, non lo utilizzo.
Da quello che hai scritto però non si capisce se tu rilevi solo una incongruenza del valore del registro CMCON, rispetto a quello da te assegnato, o se "anche" la natura e l'utilizzo dei pins (RA0, 1, 2, 3) viene compromesso.

Saluti
W - U.H.F.
Avatar utente
Foto UtenteWALTERmwp
30,2k 4 8 13
G.Master EY
G.Master EY
 
Messaggi: 8982
Iscritto il: 17 lug 2010, 18:42
Località: le 4 del mattino

0
voti

[3] Re: Registro CMCON PIC16F628

Messaggioda Foto UtenteDavide90 » 17 set 2014, 8:48

Ciao WALTERmwp, grazie per la risposta, come sempre!

Hai ragione i pezzi di codice così riportati , non servono a nulla.

Il problema era nel registro INTCON.
Da quello che ho capito, se si imposta il registro INTCON per sfruttare gli interrupt, ma non si intercetta l' interrupt in una service routine, il PIC va in loop alla ricerca della service routine.

Nel mio caso:
Avevo impostato il registro INTCON per poter usare gli interrupt delle porte B (RBIF) , ma poi , durante la stesura del codice mi sono accorto che non mi serviva più intercettare quell' interrupt e quindi ho rimosso , nella service routine , l'istruzione :

Codice: Seleziona tutto
if (RBIF)

con il simulatore di mplab ho visto che il PIC andava in loop alla ricerca di questa istruzione all' interno della service routine.
Riconfigurato correttamente il registro, il PIC ha ripreso a funzionare(almeno sul simulatore), perché programmandolo ancora non funziona!
Avatar utente
Foto UtenteDavide90
29 6
Frequentatore
Frequentatore
 
Messaggi: 130
Iscritto il: 5 lug 2012, 11:34

0
voti

[4] Re: Registro CMCON PIC16F628

Messaggioda Foto UtenteWALTERmwp » 17 set 2014, 9:41

Davide90 ha scritto: grazie per la risposta
... di nulla, figurati.
Nel tuo ultimo Post mi pare, ma è solo una mia impressione appunto, vi siano delle imprecisioni.
Intendo scrivere, in generale, che un evento "interrupt" (se abilitato, ovviamente) ti riporta il Program Counter ad una allocazione di programma (posizione di programma) ben definita e pre-stabilita dal "silicio".
Se tu non hai previsto una routine ( ... di interrupt) che, come tale (in quanto tale) come codice, inizia proprio in quella posizione (perché il compilatore/assemblatore è lì che va a posizionare il suo inizio) credo che il contatore di programma poi vada a caricare le istruzioni che trova ma che tu, intenzionalmente, non avevi previsto di eseguire.
Per questo ...
Davide90 ha scritto:il PIC ha ripreso a funzionare(almeno sul simulatore), perché programmandolo ancora non funziona!
... se non riporti il sorgente si possono solo fare degli esercizi di fantasia; tra l'altro dovresti anche specificare il presunto malfunzionamento (senza escludere lo stato dell'hardware).

Saluti
W - U.H.F.
Avatar utente
Foto UtenteWALTERmwp
30,2k 4 8 13
G.Master EY
G.Master EY
 
Messaggi: 8982
Iscritto il: 17 lug 2010, 18:42
Località: le 4 del mattino

0
voti

[5] Re: Registro CMCON PIC16F628

Messaggioda Foto UtenteDavide90 » 17 set 2014, 12:20

Per ciò che riguarda l' interrupt credo tu abbia perfettamente ragione, sostanzialmente avevo abilitato sia gli interrupt del timer0 che quello delle porte B( RBIF).

In realtà nella service routine avevo solamente intercettato l'interrupt (T0IF) e non (RBIF). Molto probabilmente, dato che le porte sono inizializzate a 0 ( PORTB=0, da me ne codice), ed il simulatore, a runtime, me le porta a livello alto( quindi viene generato l' interrupt) , il Program counter si portava ad una allocazione di memoria ben precisa, nella quale io non ho scritto nulla, non gestendo RBIF.

Grazie per la spiegazione!

Invece per ciò che riguarda il codice, credo che funzioni perché al PIC non piacciono proprio le istruzioni OR e AND.

ecco il listato completo, sto cercando di ottenere un impulso PPM per comandare un' automobilina radiocomandata che abbia dei sensori ad ultrasuoni sui due lati in modo da evitare di urtare gli ostacoli!

Codice: Seleziona tutto
#define _XTAL_FREQ 4000000
#pragma config FOSC=INTOSCIO
#pragma config CP=0
#pragma config CPD=0
#pragma config PWRTE=0
#pragma config WDTE=0
#pragma config MCLRE=1
#pragma config LVP=0
#pragma config BOREN=0


// importo le librerie
#include<stdio.h>
#include <htc.h>
#include <xc.h>
#include <PIC.h>
#define FRONTinhibitedPort RA3 // Dal sensore frontale
#define REARinhibitedPort RA2 // Dal sensore dietro


// PORTE DI INGRESSO DEL SEGNALE
#define MOTORE1INpos RB4
#define MOTORE2INpos RB5

// PORTE DI USCITA DEL SEGNALE
#define MOTORE1OUTpos RB0
#define MOTORE2OUTpos RB1



// prototipi delle funzioni
void start();

// variabili globali


unsigned int tempo=0;

void main(void){
   start();// chiamo la funzione di inizializzazione
       
}

void start(){
// imposto le porte come input o output
INTCON=0b10100001;
// Configuro le porte A come uscite
CMCON=0x07;
OPTION_REG=0b00000000; //Prescaler =1/2


TRISA=0b00001111; //Tutte le porte sono input
TRISB=0b11110000;// solo le porte RB7>RB4 sono input( per sfruttare gli interrupt)
// imposto le porte come livello basso
PORTA=0;
PORTB=0;
T0IF=0;
// imposto il valore di partenza del TMR0
TMR0=206;



while(1){

     if (FRONTinhibitedPort || REARinhibitedPort  ){
       

//i sensori comunicano qualcosa?
//si
     if(FRONTinhibitedPort){
         if (tempo<151){
            // dovrebbe simulare il segnale ppm
            MOTORE1OUTpos=1;
            MOTORE2OUTpos=1;
         }
     if (tempo>150 && tempo<1851){
            MOTORE1OUTpos=0;
            MOTORE2OUTpos=0;
           }
         
     }
   

     if(REARinhibitedPort){
     if (tempo<151){
            // dovrebbe simulare il segnale ppm
            MOTORE1OUTpos=1;
            MOTORE2OUTpos=1;
         }
     if (tempo>150 && tempo<1851){
            MOTORE1OUTpos=0;
            MOTORE2OUTpos=0;
           }
       
}else{
         //no
   /* i dati in input dei due motori passano nel PIC ed escono tali
   //funzionamento Normale


*/
        MOTORE1OUTpos=MOTORE1INpos;
   MOTORE2OUTpos=MOTORE2INpos;

        tempo=0;
}

}
}
void interrupt ISR(void){


     if (T0IF) // l' interrupt è stato causato dall' overflow del timer0
{ //l'interrupt è generato ogni 100 microsecondi

        T0IF=0;
   TMR0=206;
        if (tempo==2000)
            tempo=0;
        tempo++;

}
 
  // fine interrupt service routine
}







attualmente mi interessa solamente generare solo gli impulsi ppm, cioè, 1,5 ms ON e 18,5 ms off dei due motori.

Uso il quarzo interno del PIC 16f628A

così come ho configurato l'OPTION_REG e il TMR0 inizializzato a 206 dovrebbero garantirmi un interrupt overflow ogni 10uS.

Il problema è che attualmente il programma funziona bene sul simulatore( MPLAB) , ma se lo provo sul simulatore PIC SIMULATOR IDE oppure sul PIC fisico, il programma non funziona proprio, non entra nei vari IF.

Grazie
Avatar utente
Foto UtenteDavide90
29 6
Frequentatore
Frequentatore
 
Messaggi: 130
Iscritto il: 5 lug 2012, 11:34

0
voti

[6] Re: Registro CMCON PIC16F628

Messaggioda Foto UtenteWALTERmwp » 17 set 2014, 14:15

Al momento non mi posso soffermare sul codice ma poi proverò ad interpretarlo.
Invece, onde evitare un possibile malinteso e prevenirne di eventuali, ti aggiungo una precisazione a quanto prima ho scritto nel caso possa aver dato spazio a più d'una lettura.

Per questo ...
Davide90 ha scritto:In realtà nella service routine avevo solamente intercettato l'interrupt (T0IF) e non (RBIF). Molto probabilmente, dato che le porte sono inizializzate a 0 ( PORTB=0, da me ne codice), ed il simulatore, a runtime, me le porta a livello alto( quindi viene generato l' interrupt) , il Program counter si portava ad una allocazione di memoria ben precisa, nella quale io non ho scritto nulla, non gestendo RBIF.
... considera che un possibile grave errore si può verificare nel momento in cui abiliti ed in seguito causi l'attivazione di un interrupt in assenza (come scrivevo) della relativa routine.
In questa, se invece presente, non gestisci la presenza di una flag di un interrupt, non pregiudichi il flusso del programma in base a quanto avevi stabilito; l'errore certo viene commesso in quanto in corrispondenza di un evento (che scatena l'interrupt che tu intenzionalmente hai abilitato e quindi previsto) non gestisci le conseguenze ma questo (oltre probabilmente a pregiudicarti successivamente l'insorgenza dello stesso interrupt), di per sè, non sposta l'esecuzione del codice su percorsi non voluti.

Saluti
W - U.H.F.
Avatar utente
Foto UtenteWALTERmwp
30,2k 4 8 13
G.Master EY
G.Master EY
 
Messaggi: 8982
Iscritto il: 17 lug 2010, 18:42
Località: le 4 del mattino

0
voti

[7] Re: Registro CMCON PIC16F628

Messaggioda Foto UtenteDavide90 » 18 set 2014, 9:22

Ciao, sono d'accordo con il tuo ragionamento( e sicuramente è così che funziona il mondo PIC), ma il PIC non stava funzionando secondo la logica da te spiegata, cioè, la service routine esisteva in quanto gestivo l'overflow del timer0.
Il PIC andava in LOOP nella service routine(nemmeno la variabile contenuta nel T0IF veniva incrementato), suppongo non trovando l'istruzione (IF RBIF), perché disabilitando la configurazione RBIF e RBIE del registro INTCON e non modificando null' altro nel codice, il PIC ha ripreso a funzionare.

Per quanto riguarda il codice, ora funziona anche sul PIC, il problema era dovuto al modello del PIC.
Io ho compilato il progetto per il PIC 16f628A e caricandolo nel micro questo non funzionava( ne ho provati due), ma veniva caricato correttamente. Ricompilando il progetto per il PIC16F628 e caricandolo sul PIC 16F628 questo funziona perfettamente.
Sai darmi un'idea del perché? Dovrei provare a cancellare il PIC 16F628A con qualche strumento particolare??

Il firmware, ora, in fase di test, mi sono accorto, misurando con un'oscilloscopio, che i segnali di output variano da 8us ai 18us. mentre a me serve che il segnale generato sia a livello alto per 1,5ms e basso per 18,5 ms.

Ho provato ad usare le funzioni __delay_ms() ma sono abbastanza imprecise.

Secondo me dovrei riposizionare meglio le istruzioni
Codice: Seleziona tutto
if(FRONTinhibitedPort)
       do{
           
          do{
            MOTORE1OUTpos=1;
            MOTORE2OUTpos=1;
          }while(tempo==150);
         
          do{
            MOTORE1OUTpos=0;
            MOTORE2OUTpos=0;
          }while(tempo==1850);         
        } while(FRONTinhibitedPo


a parte che questo ciclo dentro ciclo dentro un IF non mi piace. Hai altri suggerimenti ??
ti posto il codice completo:

Codice: Seleziona tutto
// definisco i fuses del PIC
#define _XTAL_FREQ 4000000
#pragma config FOSC=INTOSCIO
#pragma config CP=0
#pragma config CPD=0
#pragma config PWRTE=0
#pragma config WDTE=0
#pragma config MCLRE=1
#pragma config LVP=0
#pragma config BOREN=0


// importo le librerie
#include<stdio.h>
#include <htc.h>
#include <xc.h>
#include <PIC.h>
#define FRONTinhibitedPort RA3 // Dal sensore frontale
#define REARinhibitedPort RA2 // Dal sensore dietro


// PORTE DI INGRESSO DEL SEGNALE
#define MOTORE1INpos RB4
#define MOTORE2INpos RB5


// PORTE DI USCITA DEL SEGNALE
#define MOTORE1OUTpos RB0
#define MOTORE2OUTpos RB1



// prototipi delle funzioni
void start();

// variabili globali


unsigned int tempo=0;

void main(void){
   start();// chiamo la funzione di inizializzazione
       
}

void start(){
// imposto le porte come input o output
INTCON=0b10100001;
// Configuro le porte A come uscite
CMCON=0x07;
OPTION_REG=0b00000000; //Prescaler =1/2


TRISA=0b00001111; //Tutte le porte sono input
TRISB=0b11110000;// solo le porte RB7>RB4 sono input( per sfruttare gli interrupt)
// imposto le porte come livello basso
PORTA=0;
PORTB=0;
T0IF=0;
// imposto il valore di partenza del TMR0
TMR0=206;



while(1){

     if (FRONTinhibitedPort || REARinhibitedPort || DXinhibitedPort || SXinhibitedPort  ){
       
//inserire un while che controlla le varie porte
     //ottimizzare con il switch case
//i sensori comunicano qualcosa?

     if(FRONTinhibitedPort)
       do{
            // dovrebbe simulare il segnale ppm
          do{
            MOTORE1OUTpos=1;
            MOTORE2OUTpos=1;
          }while(tempo==150);
         
          do{
            MOTORE1OUTpos=0;
            MOTORE2OUTpos=0;
          }while(tempo==1850);
           
       
        } while(FRONTinhibitedPort);
   

     if(REARinhibitedPort)
      do{
            // dovrebbe simulare il segnale ppm
          do{
            MOTORE3OUTpos=1;
            MOTORE4OUTpos=1;
          }while(tempo==150);
           // __delay_us(1500);
          do{
            MOTORE3OUTpos=0;
            MOTORE4OUTpos=0;
          }while(tempo==1850);
          } while(REARinhibitedPort);

}else{
         
     MOTORE1OUTpos=MOTORE1INpos;
   MOTORE2OUTpos=MOTORE2INpos;
   
}

}
}



void interrupt ISR(void){
// per il momento non è usato.forse non serve, bisogna verificare l' overing

     if (T0IF) // l' interrupt è stato causato dall' overflow del timer0
{ //l'interrupt è generato ogni 100 microsecondi
/*
   T0IF=0;
   TMR0=206;
        if (impulsoStick==2000)
            impulsoStick=1000;
   impulsoStick++;
*/
        T0IF=0;
   TMR0=206;
        if (tempo==2000)
            tempo=0;
        tempo++;

}
  // fine interrupt service routine
}

Avatar utente
Foto UtenteDavide90
29 6
Frequentatore
Frequentatore
 
Messaggi: 130
Iscritto il: 5 lug 2012, 11:34

0
voti

[8] Re: Registro CMCON PIC16F628

Messaggioda Foto UtenteWALTERmwp » 18 set 2014, 10:56

Prima di indagare sulle anomalie da te indicate in merito alle tempistiche avrei bisogno di un risposta in merito alla sintassi del codice.
In corrispondenza degli statement ...

Codice: Seleziona tutto
if(FRONTinhibitedPort)
            do
            {
e ...
Codice: Seleziona tutto
if(REARinhibitedPort)
            do
            {
... la parentesi "graffa" subito dopo la chiusura di quella tonda del test " if " non c'è; è intenzionale, è una eccezione gestita dal tuo compilatore ?
Grazie.

Mi permetto un suggerimento, consideralo come ritieni opportuno: l'indentazione, dal mio punto di vista, è importante perché ti consente di "acquisire" maggiore leggibilità.
Se invece ti trovi bene così, null'altro da aggiungere.

Saluti
W - U.H.F.
Avatar utente
Foto UtenteWALTERmwp
30,2k 4 8 13
G.Master EY
G.Master EY
 
Messaggi: 8982
Iscritto il: 17 lug 2010, 18:42
Località: le 4 del mattino

0
voti

[9] Re: Registro CMCON PIC16F628

Messaggioda Foto UtenteDavide90 » 18 set 2014, 11:09

La parentesi graffa non c'è perché ho assunto che , essendoci il il Do con la graffa proprio sotto l' IF , mettere o non mettere la graffa dopo l'if e prima del ciclo Do è equivalente al metterla.

Ho stravolto un po il codice, ho usato il timer2 che forse è più preciso del timer0.
Eccolo nella sua ultima versione
Codice: Seleziona tutto
// definisco i fuses del PIC
#define _XTAL_FREQ 4000000
#pragma config FOSC=INTOSCIO
#pragma config CP=0
#pragma config CPD=0
#pragma config PWRTE=0
#pragma config WDTE=0
#pragma config MCLRE=1
#pragma config LVP=0
#pragma config BOREN=0


// importo le librerie
#include<stdio.h>
#include <htc.h>
#include <xc.h>
#include <PIC.h>
#define FRONTinhibitedPort RA3 // Dal sensore frontale
#define REARinhibitedPort RA2 // Dal sensore dietro


// PORTE DI INGRESSO DEL SEGNALE
#define MOTORE1INpos RB4
#define MOTORE2INpos RB5


// PORTE DI USCITA DEL SEGNALE
#define MOTORE1OUTpos RB0
#define MOTORE2OUTpos RB1



// prototipi delle funzioni
void start();

// variabili globali


unsigned int tempo=0;

void main(void){
   start();// chiamo la funzione di inizializzazione

}

void start(){
// imposto le porte come input o output
INTCON=0b10100001;
// Configuro le porte A come uscite
CMCON=0x07;
T2CON=0b0000100;// Timer2
PR2=100;//Timer2
PIE1=0b00000010; // Abilito il flag Interrupt TMR2IE
OPTION_REG=0b00000000; //Prescaler =1/2


TRISA=0b00001111; //Tutte le porte sono input
TRISB=0b11110000;// solo le porte RB7>RB4 sono input( per sfruttare gli interrupt)
// imposto le porte come livello basso
PORTA=0;
PORTB=0;
T0IF=0;
// imposto il valore di partenza del TMR0
TMR2IF=0;
//impulsoStick=1000;
tempo=0;

while(1){
if (FRONTinhibitedPort || REARinhibitedPort  ){

//inserire un while che controlla le varie porte
     //ottimizzare con il switch case
//i sensori comunicano qualcosa?

     if(FRONTinhibitedPort){

            // dovrebbe simulare il segnale ppm
          do{
            MOTORE1OUTpos=1;
            MOTORE2OUTpos=1;
          }while(tempo==150);

          do{
            MOTORE1OUTpos=0;
            MOTORE2OUTpos=0;
          }while(tempo==2000);

           
     }
   



     if(REARinhibitedPort){

            // dovrebbe simulare il segnale ppm
          do{
            MOTORE3OUTpos=1;
            MOTORE4OUTpos=1;
          }while(tempo==150);

          do{
            MOTORE3OUTpos=0;
            MOTORE4OUTpos=0;
          }while(tempo==2000);

           
     }
}else{
         //no
   /* i dati in input dei due motori passano nel PIC ed escono tali
   //funzionamento Normale


*/
        MOTORE1OUTpos=MOTORE1INpos;
   MOTORE2OUTpos=MOTORE2INpos;
   
}

}
     
}

void interrupt ISR(void){
// per il momento non è usato.forse non serve, bisogna verificare l' overing
if(TMR2IF){
       TMR2IF=0;
       if (tempo==2001)
           tempo=0;
       tempo++;

     }
     if (T0IF) // l' interrupt è stato causato dall' overflow del timer0
{ //l'interrupt è generato ogni 100 microsecondi
        T0IF=0;
   TMR0=206;
        //if (tempo==2000)
        //    tempo=0;
       // tempo++;
}

}


Il problema è che riesco si a generare un segnale alto ed uno basso. ma non con la frequenza che desidero, ovvero:
1,5 ms alto e 18,5ms basso.

Attualmente ottengo valori più o meno casuali nell' ordine dei us e non ms.

Il ragionamento che ho seguito è stato :

faccio scattare l'interrupt overflow ogni 100us , quando la variabile tempo arriva a 150 ( 100us * 150 = 1500us = 1,5ms ) inverto lo stato, e quando la variabile arriva a 2000 allora la inizializzo a zero e ricomincio.
Avatar utente
Foto UtenteDavide90
29 6
Frequentatore
Frequentatore
 
Messaggi: 130
Iscritto il: 5 lug 2012, 11:34

0
voti

[10] Re: Registro CMCON PIC16F628

Messaggioda Foto UtenteWALTERmwp » 18 set 2014, 11:29

Davide90 ha scritto:La parentesi graffa non c'è perché ho assunto che , essendoci il il Do con la graffa proprio sotto l' IF , mettere o non mettere la graffa dopo l'if e prima del ciclo Do è equivalente al metterla.
... ho qualche dubbio in merito (mi riservo comunque di verificare).
Quello che fai è valido per una singola istruzione, esempio :
Codice: Seleziona tutto
if(a==b) ++i;

Non so se il "do/while" sia assimilato in tal modo, pur essendo una esecuzione "finita" e completa.
Può darsi che non serva a niente ma potresti provare a ricompilare il codice del Post [7] considerando ciò.
A questo si aggiunge, a mio parere, che una scrittura in questo "stile" ti può portare a commettere facili errori d'esecuzione (vedi anche "indentazione").

Per quanto riguarda le tempistiche, la tua affermazione e relativo sospetto in merito alla "qualità" del timer li ritengo fuorvianti: dipende da come lo si usa.
Con questo approccio potresti, dopo varie modifiche, anche arrivare ad ottenere il risultato che ti aspetti ma, non perché le tue osservazioni fossero corrette come presupposti, semplicemente perché per tentativi sistemi le "cose".
Se si verifica questo ti trovi con il codice che fa quello che vuoi tu e con la convinzione d'aver compiuto passaggi corretti (esclusione di una periferica a favore di un'altra, esclusione di un timer a favore di un altro) mentre invece non sono tali.

Saluti
W - U.H.F.
Avatar utente
Foto UtenteWALTERmwp
30,2k 4 8 13
G.Master EY
G.Master EY
 
Messaggi: 8982
Iscritto il: 17 lug 2010, 18:42
Località: le 4 del mattino

Prossimo

Torna a Firmware e programmazione

Chi c’è in linea

Visitano il forum: Nessuno e 2 ospiti