home | area personale         schemi | tutorial | robotica | pic micro | recensioni         forum | chat irc         faq | contatti         store | Ordina PCB
username
password
cerca

 
FORUM: Pic Micro
Tutto quanto riguarda questi microprocessori... progetti, suggerimenti, aiuti, discussioni...ecc


PORTA analogica in PIC16F873A
     
Autore Messaggio opzioni
e.ferriani





postato il:
08.01.2018, alle ore 07:49
Ci sono delle novità.
Sono riuscito a far parlare il Master. per ora però lo slave non riceve. Ovvero, se li collego assieme trovo il bus di I2C fermo, clock a 0v e data a 5V fissi.
Preso singolarmente, con le sole resistenze di pullup, il master manda in sequenza indirizzo a dati in questo modo:



dopo 200ms, come da codice, c'è una cosa analoga dove però la seconda parte è tutta alta, quindi non riceve niente, non vendo collegato l'altro pic. Come detto, se li collego entrambi la comunicazione si ferma.


Questo il codice:
 
//-----------------------------------------------
// 
// File:                Prova I2C - 1 - MASTER.c
// Versione:            06/01/2018
// Autore:              Enea Ferriani
// e.mail:              e.ferriani@alice.it 
// Descrizione:  Prova di comunicazione tra pic:
//                        Il programma ......
//                        ..... 
//                        ..... 
//                        .....
//
// microcontrollore: PIC16F873-04
// Oscillatore:         4MHz
// Display:             /
//
// link:                /
//
//
// Header files:      
// Source files:      
//
//
//-----------------------------------------------


//-----------------------------------------------
// D E S C R I Z I O N E     S E G N A L I
//-----------------------------------------------

/*

RA0 ------------------                  
RA1 ------------------
RA2 ------------------
RA3 ------------------
RA4 ------------------
RA5 ------------------

RB0 ------------------
RB1 ------------------
RB2 ------------------
RB3 ------------------
RB4 ------------------
RB5 ------------------
RB6 PROGRAMMAZIONE - CLOCK
RB7 PROGRAMMAZIONE - DATA


RC0 led test
RC1     pulsante test
RC2 ------------------
RC3 SCL                   clock
RC4 SDA                   dati
RC5 ------------------
RC6 ------------------
RC7 ------------------

*/

//-----------------------------------------------
//FUNZIONAMENTO ()
//----------------------------------------------- 

//  premendo il pulsante in RC1 del master si deve accendere il led in RC0 dello slave

//-----------------------------------------------
// CONFIGURATION
//-----------------------------------------------

#pragma config FOSC = XT   // Oscillator Selection bits (XT oscillator)
#pragma config WDTE = OFF  // Watchdog Timer Enable bit (WDT disabled)
#pragma config PWRTE = OFF // Power-up Timer Enable bit (PWRT disabled)
#pragma config BOREN = OFF // Brown-out Reset Enable bit (BOR disabled)
#pragma config LVP = OFF   // Low-Voltage In-Circuit Serial Programming Enable bit
#pragma config CPD = OFF   // Data EEPROM Memory Code Protection bit 
#pragma config WRT = OFF   // Flash Program Memory Write Enable bits 
#pragma config CP = OFF    // Flash Program Memory Code Protection bit


#define _XTAL_FREQ  4000000


//-----------------------------------------------
// INCLUDE
//-----------------------------------------------

#include "xc.h"
#include "pic16f873.h"

//-----------------------------------------------
//DEFINIZIONI (definitions)
//----------------------------------------------- 

//-----------------------------------------------
//INIZIALIZZAZIONI ()
//-----------------------------------------------

void I2C_Master_Init(const unsigned long c)
{
  SSPCON = 0b00101000;
  SSPCON2 = 0;
  SSPADD = (_XTAL_FREQ/(2*c))-1;
  SSPSTAT = 0;
  TRISC3 = 1;        //Setting as input as given in datasheet
  TRISC4 = 1;        //Setting as input as given in datasheet
}

void I2C_Master_Wait()
{
  while ((SSPSTAT & 0b00000100) || (SSPCON2 & 0b00011111)); //((SSPSTAT & 0x04) || (SSPCON2 & 0x1F));
}

void I2C_Master_Start()
{
  I2C_Master_Wait(); //attesa
  SEN = 1;
}

void I2C_Master_RepeatedStart()
{
  I2C_Master_Wait(); //attesa
  RSEN = 1;
}

void I2C_Master_Stop()
{
  I2C_Master_Wait(); //attesa
  PEN = 1;
}

void I2C_Master_Write(unsigned d)
{
  I2C_Master_Wait(); //attesa
  SSPBUF = d;
}

unsigned short I2C_Master_Read(unsigned short a)
{
  unsigned short temp;
  I2C_Master_Wait(); //attesa
  RCEN = 1;
  I2C_Master_Wait(); //attesa
  temp = SSPBUF;
  I2C_Master_Wait(); //attesa
  ACKDT = (a)?0:1;
  ACKEN = 1;
  return temp;
}

//-----------------------------------------------
//MAIN - (MAIN PROGRAM)
//-----------------------------------------------

void main()
{
  INTCON  = 0b00000000;
  nRBPU = 0;                      //Enable PORTB internal pull up resistor
  
  // 0= USCITA
  // 1= INGRESSO
  
  TRISB = 0xFF;                   //PORTB  input
  TRISC0 = 0; //led
  TRISC1 = 1; //pulsante
  TRISC7 = 0;                     //PORTC7  output per il led "sono vivo"

  I2C_Master_Init(100000);        //Initialize I2C Master with 100KHz clock
  while(1)
  {

    I2C_Master_Start();         //Start condition
    I2C_Master_Write(0x30);     //7 bit address + Write
    I2C_Master_Write(RC1);    //Write data
    I2C_Master_Stop();          //Stop condition
  __delay_ms(200);

    I2C_Master_Start();         //Start condition
    I2C_Master_Write(0x31);     //7 bit address + Read
    RC2 = I2C_Master_Read(0); //Read + Acknowledge
    I2C_Master_Stop();          //Stop condition
    __delay_ms(200);
    
  }
}


Questo lo Slave:
----------------------------------------------
//
// File: Prova I2C - 1 - MASTER.c
// Versione: 06/01/2018
// Autore: Enea Ferriani
// e.mail: e.ferriani@alice.it
// Descrizione: Prova di comunicazione tra pic:
// Il programma ......
// .....
// .....
// .....
//
// microcontrollore: PIC16F873-04
// Oscillatore: 4MHz
// Display: /
//
// link: /
//
//
// Header files:
// Source files:
//
//
//-----------------------------------------------


//-----------------------------------------------
// D E S C R I Z I O N E S E G N A L I
//-----------------------------------------------

/*

RA0 ------------------
RA1 ------------------
RA2 ------------------
RA3 ------------------
RA4 ------------------
RA5 ------------------

RB0 ------------------
RB1 ------------------
RB2 ------------------
RB3 ------------------
RB4 ------------------
RB5 ------------------
RB6 PROGRAMMAZIONE - CLOCK
RB7 PROGRAMMAZIONE - DATA


RC0 led test
RC1 pulsante test
RC2 ------------------
RC3 SCL clock
RC4 SDA dati
RC5 ------------------
RC6 ------------------
RC7 ------------------

*/

//-----------------------------------------------
//FUNZIONAMENTO ()
//-----------------------------------------------

// premendo il pulsante in RC1 del master si deve accendere il led in RC0 dello slave

//-----------------------------------------------
// CONFIGURATION
//-----------------------------------------------

#pragma config FOSC = XT // Oscillator Selection bits (XT oscillator)
#pragma config WDTE = OFF // Watchdog Timer Enable bit (WDT disabled)
#pragma config PWRTE = OFF // Power-up Timer Enable bit (PWRT disabled)
#pragma config BOREN = OFF // Brown-out Reset Enable bit (BOR disabled)
#pragma config LVP = OFF // Low-Voltage In-Circuit Serial Programming Enable bit
#pragma config CPD = OFF // Data EEPROM Memory Code Protection bit
#pragma config WRT = OFF // Flash Program Memory Write Enable bits
#pragma config CP = OFF // Flash Program Memory Code Protection bit


#define _XTAL_FREQ 4000000


//-----------------------------------------------
// INCLUDE
//-----------------------------------------------

#include "xc.h"
#include "pic16f873.h"

//-----------------------------------------------
//DEFINIZIONI (definitions)
//-----------------------------------------------

//-----------------------------------------------
//INIZIALIZZAZIONI ()
//-----------------------------------------------

short z;
void interrupt I2C_Slave_Read()
{
if(SSPIF == 1)
{
SSPCONbits.CKP = 0;

if ((SSPCONbits.SSPOV) || (SSPCONbits.WCOL))
{
z = SSPBUF; // Read the previous value to clear the buffer
SSPCONbits.SSPOV = 0; // Clear the overflow flag
SSPCONbits.WCOL = 0; // Clear the collision bit
SSPCONbits.CKP = 1;
}

if(!SSPSTATbits.D_nA && !SSPSTATbits.R_nW)
{
z = SSPBUF;
while(!BF);
RC0 = SSPBUF;
SSPCONbits.CKP = 1;
}
else if(!SSPSTATbits.D_nA && SSPSTATbits.R_nW)
{
z = SSPBUF;
BF = 0;
SSPBUF = RC1 ;
SSPCONbits.CKP = 1;
while(SSPSTATbits.BF);
}

SSPIF = 0;
}
}

void I2C_Slave_Init(short address)
{
SSPSTAT = 0x80;
SSPADD = address;
SSPCON = 0x36;
SSPCON2 = 0x01;
TRISC3 = 1; //Setting as input as given in datasheet
TRISC4 = 1; //Setting as input as given in datasheet
GIE = 1;
PEIE = 1;
SSPIF = 0;
SSPIE = 1;
}


//-----------------------------------------------
//MAIN - (MAIN PROGRAM)
//-----------------------------------------------

void main()
{
INTCON = 0b00000000;
nRBPU = 0; //Enable PORTB internal pull up resistor

// 0= USCITA
// 1= INGRESSO

TRISB = 0xFF; //PORTB input
TRISC0 = 0; //led
TRISC1 = 1; //pulsante
TRISC7 = 0; //PORTC7 output

I2C_Slave_Init(0x30); //Initialize as a I2C Slave with address 0x30
while(1);

}



Enea Ferriani
e.ferriani





postato il:
08.01.2018, alle ore 07:52
Questa era l'immagine che avevo allegato. Spero ora si veda.


Chiedo per l'ennesima volta, se è possibile, come si fa per modificare i post appena inviati? Non ho trovato istruzioni.




Enea Ferriani
picmicro675




una ogni 10 livelli


postato il:
08.01.2018, alle ore 14:40
Benvenuto su Grix .
Non c'è anteprima ne redazione del messaggio inviato.

Ora ho preso le due codici. Faccio delle prove col simulatore e vediamo cosa non funziona.
Mi domando una cosa.... Il progetto è per uso personale oppure per lavoro ?
Nel primo caso, penso che si possa anche cercare un buon simulatore [icon]occhiolino[/code], ma credo che Altium (come hai scritto) non sia in grado di simulare due 16F873.



Anno nuovo, forum nuovo.
Mi sa che lascio.
picmicro675




una ogni 10 livelli


postato il:
09.01.2018, alle ore 06:18
Ieri ho fatto qualche esperimento. Ho trovato qualche informazione sul sito microchip
http://ww1.microchip.com/downloads/en/AppNotes/Source_code.z… e ho messo insieme un programma per master ed uno slave adattato al 16F873.
http://www.grix.it/UserFiles/picmicro675/File/I2Ctest.7z

Ora il programma ha qualche pecca che non capisco perché si ferma al primo byte letto dallo slave. Comunque scoprendo dove è il difetto trovo che isa una base eccellente per continuare nel progetto. In pratica dovrebbe diventare una libreria che si possa usare sotto forma di una comunicazione seriale.
Primok, mettici un occhio

Da questo pezzo di codice, si potrà definire il dialogo che invia messaggi agli slave, che magari serve solo 5 al massimo 10 bytes per soddisfare la maggior parte di operazioni. Di questi bytes potrebbero benissimo esser in testo chiaro da leggere. Del tipo di programmazione che ho usato con http://www.grix.it/viewer.php?page=12722, vedendo la descrizione del programma.

Oppure anche http://www.grix.it/viewer.php?page=12725, con qualche ragionamento per capire il metodo adottato.



Anno nuovo, forum nuovo.
Mi sa che lascio.
e.ferriani





postato il:
09.01.2018, alle ore 07:43
Appena riesco leggo i link che hai messo. Cos'è il secondo? .7z?
Ad ogni modo ieri sera ho provato a fare qualcosa, ed ho visto che solo mettendo a zero SSPIE o commentandolo, il master riesce a comunicare, o meglio riesce a dire qualcosa seppur collegato allo slave. Me premendo il pulsante su RC1 del master non vedo variazioni sul led di RC0 sullo slave. Solo con l'oscilloscopio si vede il bit relativo al pulsante andare su.



Enea Ferriani
picmicro675




una ogni 10 livelli


postato il:
09.01.2018, alle ore 18:47
Il secondo link in 7zip è quello che ho sistemato io per il micro di questa discussione. Contiene un sorgente per il master ed uno per uno slave. È un esempio di trasferire 32 bytes da master a slave e viceversa, ma quest'ultimo non riesce.


Anno nuovo, forum nuovo.
Mi sa che lascio.
e.ferriani





postato il:
09.01.2018, alle ore 23:48
Provo a spiegare quanto ho fatto fino ad ora.
Ho sistemato il codice in modo da renderlo più comprensibile almeno per me, che non sono un programmatore, ma lo faccio per gioco.
Ho messo dei commenti in modo da rendermi più chiaro il funzionamento e le varie chiamate a cosa si riferiscono. Magari prova a vedere se ho scritto delle cavolate.
Scritto così funziona, ho preso un po' del tuo codice, un po' di quello di microchip, ho rimesso in ordine le varie righe secondo quanto scritto ed interpretato dal manuale, spero di aver capito bene.

La prima cosa che ho fatto è stato muovere i bit della configuration word, fusibili.
Come avevo detto, fino a ieri, collegando i due pic, SDA->SDA e SCL->SCL, si vedeva un solo ciclo di lettura scrittura del master poi il nulla. Entrambi i segnali morti.

Mettendo LVP = ON, ieri era OFF, il master riesce a lavorare, ed i segnali sono entrambi vivi.
Non so il perché, ne se è corretto, ma così almeno non è bloccato.

Una cosa che vedo, e vedevo anche ieri ed anche con lo slave scollegato, è che il primo blocco del master indirizzamento+scrittura funziona, nel senso che con l'oscilloscopio i bit confermano l'indirizzo 0x30 e, nel blocco dati, premendo il pulsante il relativo bit 1 sale quando viene premuto. Nel secondo blocco del master, l'indirizzo non è lo stesso, mi sembra un 0x31, cioè 00110001 con di seguito l'ACK. Di seguito è tutto alto.

Metto un video, così si capisce meglio, forse.
http://youtu.be/W56Pnrpu144
All'inizio si vede la pressione del pulsante.
Spero che il link funzioni.

Ho come l'impressione che il comando non venga letto dallo slave, e/o che il led non sia chiamato nel modo giusto. Dovrebbe accendersi alla pressione del pulsante sul master. Se riesco a fare andare questo poi potrò ritornare al resto del progetto.

Di seguito il codice.



 
//-----------------------------------------------
// CONFIGURATION
//-----------------------------------------------

#pragma config FOSC = XT   // Oscillator Selection bits (XT oscillator)
#pragma config WDTE = OFF  // Watchdog Timer Enable bit (WDT disabled)
#pragma config PWRTE = OFF // Power-up Timer Enable bit (PWRT disabled)
#pragma config BOREN = OFF // Brown-out Reset Enable bit (BOR disabled)
#pragma config LVP = ON   // Low-Voltage In-Circuit Serial Programming Enable bit
#pragma config CPD = OFF   // Data EEPROM Memory Code Protection bit 
#pragma config WRT = OFF   // Flash Program Memory Write Enable bits 
#pragma config CP = OFF    // Flash Program Memory Code Protection bit


#define _XTAL_FREQ  4000000//UL


//-----------------------------------------------
// INCLUDE
//-----------------------------------------------

#include "xc.h"
#include "pic16f873.h"

//-----------------------------------------------
//DEFINIZIONI (definitions)
//----------------------------------------------- 

#define I2cSlaveAddress 0x30

//-----------------------------------------------
//INIZIALIZZAZIONI ()
//-----------------------------------------------

short z;
void interrupt I2C_Slave_Read()
{
  if(SSPIF == 1)                    // check to see if SSP interrupt
  {
    SSPCONbits.CKP = 0;             // Clock Polarity Select bit CKP: 
                                    //0 = Holds clock low (clock stretch)
                                    //(Used to ensure data setup time.)

    if ((SSPCONbits.SSPOV) || (SSPCONbits.WCOL))
                                    //SSPOV: Receive Overflow Indicator bit
                                    //WCOL: Write Collision Detect bit
    {
      z = SSPBUF;                   // Legge il valore precedente del buffer
      SSPCONbits.SSPOV = 0;         // Receive Overflow Indicator bit SSPOV: 0 = No overflow
      SSPCONbits.WCOL = 0;          // Write Collision Detect bit WCOL: 0 = No collision
      SSPCONbits.CKP = 1;           // Clock Polarity Select bit CKP: 1 = Enable clock
    }

    if(!SSPSTATbits.D_nA && !SSPSTATbits.R_nW)
                                      //D/A: Data/_Address bit (I2C mode only) 
                                      //R/W: Read/_Write bit Information (I2C mode only) 
    {
      z = SSPBUF;                     // Legge il valore precedente del buffer
      while(!BF);
      RC0 = SSPBUF;                   // scrive in RC0 il buffer
      SSPCONbits.CKP = 1;             // Clock Polarity Select bit CKP: 1 = Enable clock
    }
    else if(!SSPSTATbits.D_nA && SSPSTATbits.R_nW)
                                      //D/A: Data/_Address bit (I2C mode only) 
                                      //R/W: Read/_Write bit Information (I2C mode only)
    {
      z = SSPBUF;                     // Legge il valore precedente del buffer
      BF = 0;
      SSPBUF = RC1 ;
      SSPCONbits.CKP = 1;             // Clock Polarity Select bit CKP: 1 = Enable clock
      while(SSPSTATbits.BF);          //Buffer Full Status bit BF: 
                                      //1 = Data transmit in progress (does not include 
                                      //the ACK and STOP bits), SSPBUF is full
                                      //0 = Data transmit complete (does not include the 
                                      //ACK and STOP bits), SSPBUF is empty
    }

    SSPIF = 0;
  }
}

void I2C_Slave_Init()
{
  TRISC3 = 1;                   //RC3 input per I2C
  TRISC4 = 1;                   //RC4 input per I2C
  

  SSPCON = 0b00110110;          //era 0x36

  SSPCON2bits.SEN = 1;          //SEN: 1 = Initiate START condition on SDA and 
                                //SCL pins. Automatically cleared by hardware. 
                                //Clock stretching is enabled for a received 
                                //address/data byte, ignoring the state of the 
                                //SSPOV bit only if the BF bit = 0 the falling 
                                //edge of SCL
                                
  SSPSTAT = 0b10000000;         //era 0x28
  SSPADD = I2cSlaveAddress;     // carica l'indirizzo dello Slave
  
  SSPIF = 0;                  // Clear the serial port interrupt flag
  BCLIF = 0;                  // Clear the bus collision interrupt flag
  BCLIE = 1;                  // Enable bus collision interrupts
  SSPIE = 1;                  // Enable serial port interrupts
  PEIE = 1;                   // Enable peripheral interrupts
  GIE = 1;                    // Enable global interrupts
  
}


//-----------------------------------------------
//MAIN - (MAIN PROGRAM)
//-----------------------------------------------

void main()
{
  INTCON  = 0b00000000;           //GIE: 0 = Disables all interrupts
                                  //PEIE: 0 = Disables all peripheral interrupts
                                  //T0IE: 0 = Disables the TMR0 interrupt
                                  //INTE: 0 = Disables the RB0/INT external interrupt
                                  //RBIE: 0 = Disables the RB port change interrupt
                                  //T0IF: 0 = TMR0 register did not overflow
                                  //INTF: 0 = The RB0/INT external interrupt did not occur
                                  //RBIF: 0 = None of the RB7:RB4 pins have changed state
  
  
  OPTION_REG = 0b11010111;        //RBPU: 1 = PORTB pull-ups are disabled
                                  //INTEDG: 1 = Interrupt on rising edge of RB0/INT pin
                                  //T0CS: 0 = Internal instruction cycle clock (CLKOUT)
                                  //T0SE: 1 = Increment on high-to-low transition on RA4/T0CKI pin
                                  //PSA: 0 = Prescaler is assigned to the Timer0 module
                                  //PS2÷PS0: 111 = TMR0-> 1:256, WDT Rate-> 1:128
  
  nRBPU = 0;                      //Enable PORTB internal pull up resistor
  
  // 0= USCITA
  // 1= INGRESSO
  
  TRISB = 0b11111111;             //PORTB as input
  TRISC0 = 0;
  TRISC1 = 1;
  TRISC7 = 0;                     //PORTC7 as output

  I2C_Slave_Init();               //Initialize as a I2C Slave 
  while(1);




Enea Ferriani
picmicro675




una ogni 10 livelli


postato il:
10.01.2018, alle ore 01:48
INTCON = 0 è superfluo, visto che cambia con I2C_Slave_Init().

Poi a me non corrisponde nRBPU = 0 , Non è una definizione valida. Anche questa superflua dato che hai già definito i bits in OPTION_REG.

Suppongo che RC0 = SSPBUF; non è corretto, non si può assegnare ad un bit il valore di un byte. Al limite prendi tutta la PORTC e quindi ripulisci i bit non interessati.

Vedi DS52053B-page 51.
[code]#define testbit(var, bit) ((var) & (1 <<(bit)))
#define setbit(var, bit) ((var) |= (1 << (bit)))
#define clrbit(var, bit) ((var) &= ~(1 << (bit)))

unsigned char temp_port;

temp_port = SSPBUF; // scrive in temp_port il buffer
if (testbit(temp_port, 0) setbit(PORTC)
else clrbit(




Anno nuovo, forum nuovo.
Mi sa che lascio.
picmicro675




una ogni 10 livelli


postato il:
10.01.2018, alle ore 01:54
Errore.
NTCON = 0 è superfluo, visto che cambia con I2C_Slave_Init().

Poi a me non corrisponde nRBPU = 0 , Non è una definizione valida. Anche questa superflua dato che hai già definito i bits in OPTION_REG.

Suppongo che RC0 = SSPBUF; non è corretto, non si può assegnare ad un bit il valore di un byte. Al limite prendi tutta la PORTC e quindi ripulisci i bit non interessati.

Vedi DS52053B-page 51.
#define testbit(var, bit) ((var) & (1 <<(bit)))
#define setbit(var, bit) ((var) |= (1 << (bit)))
#define clrbit(var, bit) ((var) &= ~(1 << (bit)))

unsigned char temp_port;

temp_port = SSPBUF; // scrive in temp_port il buffer
if (testbit(temp_port, 0) setbit(PORTC);
else clrbit(PORTC,0);

È solo uno stralcio di sorgente dove si legge e si scrive da SSBUF direttamente ai bit di PORTC. Se compili e vedi l' assembly, magari trovi che c'è un errore.

Altrimenti è probabile che vai ad influenzare RC4 e RC5 del bus I2C.



Anno nuovo, forum nuovo.
Mi sa che lascio.
e.ferriani





postato il:
10.01.2018, alle ore 06:48
INTCON E nRBPU se non li metto mi dava errore. Con le ultime modifiche vedo quanto contano...

RC0=SSPBUF credo che non vada bene infatti nel codice da cui sono partito era PORTD, tutta la porta,...ci ho provato ma non sapevo come scrivere.
Provo quello che mi hai passato, non ho mai scritto niente così. Semmai me lo faccio spiegare.
Il video è chiarificatore e ti torna con il codice, anche se è più x quanto fa il master?

Ti aggiorno.



Enea Ferriani
segui questo thread con grixFC, per questa funzione devi aver installato il software grixFC

torna su
     

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




 







 
 
indietro | homepage | torna su copyright © 2004/2024 GRIX.IT - La community dell'elettronica Amatoriale