Cos'è ElectroYou | Login Iscriviti

ElectroYou - la comunità dei professionisti del mondo elettrico

I2C1 STM32

Raccolta di codici sorgenti

Moderatore: Foto UtentePaolino

0
voti

[21] Re: I2C1 STM32

Messaggioda Foto UtenteWALTERmwp » 13 mag 2015, 1:25

Per superare questo while ...
Codice: Seleziona tutto
/*wait transmission complete*/
   while(!(I2C1 ->SR1 & I2C_SR1_BTF)); //resto fermo qua
... prova a lasciare inalterato il registro CR1: non disabilitare il bit di ACK.
Fai questa verifica.
Non so se interpreto in modo corretto ma non vorrei che il bit BTF, del registro SR1, non venisse messo a 1 perché ritenuta incompleta la sequenza.
(La define "2C_SR1_BTF" vale 0x0004 ?)

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

1
voti

[22] Re: I2C1 STM32

Messaggioda Foto Utentelelerelele » 13 mag 2015, 8:56

alle96 ha scritto:Foto Utentelelerelele ti posso chiedere da che libreria hai preso quelle funzioni così me le studio?

Grazie per l'aiuto O_/


Le ho scritte io partendo dai datasheets di sensore e micro, non so quanto siano formalmente corrette ma funzionano.

Codice: Seleziona tutto
void Start(void)
{
   
    UINT16 k=I2C_TimeOut;

    SSP1CON2bits.SEN=1;
    while (k>0)
    {
    if(SSP1IF)break;
    k--;
    }
   
    SSP1IF=0;
}

Codice: Seleziona tutto
void ReStart(void)
{
    UINT16 k=I2C_TimeOut;

   SSP1CON2bits.RSEN=1;    //Ripeto il segnale di start

     while (k>0)
    {
    if(SSP1IF)break;
     k--;
     };

    SSP1IF=0;
}

Codice: Seleziona tutto
void Stop(void)
{
    UINT16 k=I2C_TimeOut;

    SSP1CON2bits.PEN=1;

    while (k>0)
    {
    if(SSP1IF)break;
    k--;
    }

    SSP1IF=0;
}
/*
//invio il byte direttamente alla porta
*/
void Invio_Byte(char Byte)
{
    UINT16 k=I2C_TimeOut;

    SSP1BUF=Byte;

    while (k>0)
    {
    if(SSP1IF)break;
    k--;
    };

    while(ACKSTAT);//verifico che slave  invia ACK

   SSP1IF=0;

}


Codice: Seleziona tutto
UINT8 Leggo_Byte(BOOL AckInviato)
{
UINT8 Byte;

SSP1CON2bits.RCEN=1;//avvio lettura byte

while (!SSP1IF);
   SSP1IF=0;

SSP1CON2bits.ACKDT=AckInviato;   //Setto che deve inviare un segnale di acknowledge
SSP1CON2bits.ACKEN=1;
while (!SSP1IF);
SSP1IF=0;

   while (!BF);
    Byte=SSP1BUF;

     return Byte;
}

Codice: Seleziona tutto
UINT16 Leggo_Byte16(void)
{

UINT16 Byte;

Byte=Leggo_Byte(0);

/*  ricevo byte 2*/
Byte<<=8;
Byte+=Leggo_Byte(1);

return Byte;

}



dacci un occhio.

saluti.
Avatar utente
Foto Utentelelerelele
4.899 3 7 9
Master
Master
 
Messaggi: 5505
Iscritto il: 8 giu 2011, 8:57
Località: Reggio Emilia

0
voti

[23] Re: I2C1 STM32

Messaggioda Foto Utentealle96 » 14 mag 2015, 16:46

Foto UtenteWALTERmwp ho fatto vari tentativi in questi giorni dunque
1 -> ho lasciato inalterato CR1 lasciando ACK abilitato e supero il ciclo while() ma ricevo sempre 0x00. Questo sia usando come indirizzo 0xD0 sia che con 0xAA che con 0xF7
2 -> ho aggiunto un altro while uguale per il secondo byte ma il risultato è sempre 0x00
3 -> come da datasheet del STM32F407 p835 dopo il primo while quindi subito dopo il primo byte ho disattivato l'ACK e avviato il comando di stop ma anche in questo caso ricevo 0x00.

per ora il codice è il seguente
Codice: Seleziona tutto
void I2C_1_ADRWR(uint8_t adr)
{
   uint16_t status;
   /*wait for line*/
   while((I2C1 ->SR2 & I2C_SR2_BUSY) == I2C_SR2_BUSY);
   /*ack enabled*/
   //I2C1 ->CR1 |= I2C_CR1_ACK;
   /*enable  & ACK*/
   I2C1 ->CR1 |= 0x0401;
   /*start event generation*/
   I2C1 ->CR1 |= I2C_CR1_START;
   /*check start bit generation*/
   while(!(I2C1 ->SR1 & 0x0001));
   status = I2C1 ->SR1;
   
   
   /*write adress*/
   I2C1 ->DR = 0xEE;
   /*wait for adress sent complete*/
   while(!(I2C1 ->SR1 & 0x0002));
   /*read status 4 clear*/
   status = I2C1 ->SR1;
   
   I2C1 ->DR = adr;
   /*wait for adress sent complete*/
   while(!(I2C1 ->SR1 & 0x0002));
   /*read status 4 clear*/
   status = I2C1 ->SR1;
   
   /*restart*/
   I2C1 ->CR1 |= I2C_CR1_START;
   /*check start bit generation*/
   while(!(I2C1 ->SR1 & 0x0001));
   status = I2C1 ->SR1;
   
   /*write adress*/
   I2C1 ->DR = 0xEF;
   /*wait for adress sent complete*/
   while(!(I2C1 ->SR1 & 0x0002));
   /*read status 4 clear*/
   status = I2C1 ->SR1;
   
   /*read data*/
   
   /*wait transmission complete*/
   while(!(I2C1 ->SR1 & I2C_SR1_BTF));
   id <<= I2C1 ->DR;
   /*resetto cr1 alle condizioni iniziali*/
   I2C1 ->CR1 = 0x0001;
   /*stop request*/
   I2C1 ->CR1 |= 0x0200;
   while(!(I2C1 ->SR1 & I2C_SR1_BTF));
   
   id |= I2C1 ->DR; //arrivo qua ma ricevo 0x00
}

void I2C_1_Init()
{
   /*i2c1 set for sm mode. conn not enabled CR1 for start/stop/enable*/
   /*I2C1 reset*/
   RCC ->APB1RSTR |= RCC_APB1RSTR_I2C1RST;
   RCC ->APB1RSTR &= 0x0000;
   /*clock enabler*/
   RCC ->APB1ENR |= RCC_APB1ENR_I2C1EN;
   /*4mhz for 100KHz speed*/
   I2C1 ->CR2 |= I2C_CR2_FREQ_3;
   /*interrupt and buffer interrupt enabled*/
   I2C1 ->CR2 |= I2C_CR2_ITEVTEN | I2C_CR2_ITBUFEN;
   /*reset CCR*/
   I2C1 ->CCR &= 0x0000;
   /*CCR register speed*/
   I2C1 ->CCR |= 0x0014;
   /*TRISE*/
   I2C1 ->TRISE |= 0x0005;
}


Domani porto a scuola la scheda e tutto e provo a vedere con l'oscilloscopio se si riceve qualcosa e se si invia qualcosa (cosa credo molto probabile dato che tutti i bit vengono settati)

Purtroppo sul motivo che io riceva sempre 0x00 non ho idee.

Foto Utentelelerelele le sto leggendo proprio ora, sono scritte per i PIC?

Grazie dell'aiuto O_/
Avatar utente
Foto Utentealle96
15 4
 
Messaggi: 47
Iscritto il: 21 feb 2012, 16:21

0
voti

[24] Re: I2C1 STM32

Messaggioda Foto Utentelelerelele » 14 mag 2015, 17:14

alle96 ha scritto:Foto Utentelelerelele le sto leggendo proprio ora, sono scritte per i PIC?


le ho scritte con mplabx e compilate con XC8, applicate ad un PIC, come ti ho scitto prima noon conosco il tuo processore.

hai provato ad inserire come pullup due led, in mancanza di oscilloscopio è utile, vedi se il bus parte libero (livello alto) e poi si inviano i dati (livello basso).
Avatar utente
Foto Utentelelerelele
4.899 3 7 9
Master
Master
 
Messaggi: 5505
Iscritto il: 8 giu 2011, 8:57
Località: Reggio Emilia

0
voti

[25] Re: I2C1 STM32

Messaggioda Foto UtenteWALTERmwp » 14 mag 2015, 18:24

alle96 ha scritto:(...) ho lasciato inalterato CR1 lasciando ACK abilitato e supero il ciclo while() (...)
bene, un altro passo in avanti.
Foto Utentealle96, considera che il sensore ti deve inviare due byte e che, comunque, dopo la ricezione del secondo, in qualità di master, non devi inviare lo ACK (se richiedi il contenuto di un indirizzo di E2PROM lo slave ti risponde con il contenuto di due byte(s) ).
Quindi, subito dopo avere acquisito il secondo byte, devi eseguire l'istruzione
Codice: Seleziona tutto
I2C1 ->CR1 &= ~I2C_CR1_ACK;
che "abbiamo" tolto nel codice del Post [17] ma, solo per poterla posticipare; altrimenti il master genera un altro ACK che invece non deve.
Poi, questo shift a sinistra
Codice: Seleziona tutto
id <<= I2C1 ->DR;
quanti bit(s) prevedi intenzionalmente di spostare ?

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

[26] Re: I2C1 STM32

Messaggioda Foto Utentealle96 » 14 mag 2015, 18:36

Foto UtenteWALTERmwp ahahahaha scusa un errore di distrazione, intendevo
Codice: Seleziona tutto
id = I2C1 ->DR << 8;


Ho cambiato il codice come indicato da te se ti sembra giusto lo carico sulla scheda per domani così testo con l'oscilloscopio
Codice: Seleziona tutto
void I2C_1_ADRWR(uint8_t adr)
{
   uint16_t status;
   /*wait for line*/
   while((I2C1 ->SR2 & I2C_SR2_BUSY) == I2C_SR2_BUSY);
   /*ack enabled*/
   //I2C1 ->CR1 |= I2C_CR1_ACK;
   /*enable  & ACK*/
   I2C1 ->CR1 |= 0x0401;
   /*start event generation*/
   I2C1 ->CR1 |= I2C_CR1_START;
   /*check start bit generation*/
   while(!(I2C1 ->SR1 & 0x0001));
   status = I2C1 ->SR1;
   
   
   /*write adress*/
   I2C1 ->DR = 0xEE;
   /*wait for adress sent complete*/
   while(!(I2C1 ->SR1 & 0x0002));
   /*read status 4 clear*/
   status = I2C1 ->SR1;
   
   I2C1 ->DR = adr;
   /*wait for adress sent complete*/
   while(!(I2C1 ->SR1 & 0x0002));
   /*read status 4 clear*/
   status = I2C1 ->SR1;
   
   /*restart*/
   I2C1 ->CR1 |= I2C_CR1_START;
   /*check start bit generation*/
   while(!(I2C1 ->SR1 & 0x0001));
   status = I2C1 ->SR1;
   
   /*write adress*/
   I2C1 ->DR = 0xEF;
   /*wait for adress sent complete*/
   while(!(I2C1 ->SR1 & 0x0002));
   /*read status 4 clear*/
   status = I2C1 ->SR1;
   
   /*read data*/
   
   /*wait transmission complete*/
   while(!(I2C1 ->SR1 & I2C_SR1_BTF));
   id = I2C1 ->DR << 8;
   /*stop request*/
   I2C1 ->CR1 |= 0x0200;
   while(!(I2C1 ->SR1 & I2C_SR1_BTF));
   I2C1 ->CR1 &= ~I2C_CR1_ACK;
   
   id |= I2C1 ->DR; //arrivo qua ma ricevo 0x00
}
Avatar utente
Foto Utentealle96
15 4
 
Messaggi: 47
Iscritto il: 21 feb 2012, 16:21

0
voti

[27] Re: I2C1 STM32

Messaggioda Foto UtenteWALTERmwp » 14 mag 2015, 23:44

Visto l'errore di sintassi, presente nel codice del Post, non so poi cosa effettivamente tu abbia compilato (ti avrebbe dato un errore) e, eventualmente, caricato sul microcontrollore.

Comunque, mi permetto di darti un suggerimento: ri-leggi (o leggi), se ne hai tempo, il datasheet dello ST e, in particolare, la gestione dei registri SR1 e CR1.

Affermando che ricevi "zero" ma, non essendo nelle condizioni di stabilire l'affidabilità di questa affermazione valuterei, se possibile (non l'ho verificato, eventualmente fallo tu), l'inizializzazione del contenuto del registro DR con un valore significativo in modo tale da stabilire, almeno, l'avvenuta variazione a seguito di una sessione di trasmissione.

Qui
Codice: Seleziona tutto
I2C1 ->DR = adr;
, per quanto sopra, avrei preferito vedere "scalpellata" la costante in esadecimale, al posto del parametro.

Facci sapere e buon lavoro(studio).

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

Precedente

Torna a Firmware e programmazione

Chi c’è in linea

Visitano il forum: Nessuno e 7 ospiti