Cos'è ElectroYou | Login Iscriviti

ElectroYou - la comunità dei professionisti del mondo elettrico

Ricerca personalizzata

CPT112 e PIC16F1823

Raccolta di codici sorgenti

Moderatore: Foto UtentePaolino

0
voti

[1] CPT112 e PIC16F1823

Messaggioda Foto UtenteMatts » 6 ott 2017, 8:39

Buongiorno a tutti,

Sto avendo alcuni problemi nel gestire la comunicazione I2C tra questi due oggetti, con il PIC come master ed il CPT come slave. La comunicazione dovrebbe essere:

-Invio dell'address del CPT112
-Ricezione di 3 byte di dati
-Chiusura della comunicazione

L'inizio della comunicazione viene richiesta dal CPT settando un pin a livello logico basso. Ho scritto un programma e funziona ma ad una velocità di clock troppo bassa che non mi consente una corretta gestione del PWM delle luci ad esso collegate.

Il programma è il seguente

Codice: Seleziona tutto
#include <xc.h>
#include <pic16f1823.h>
#include "set.h"

/*STRUCTURE*/
typedef struct MyStruct{
    unsigned char Packet_Counter;
    unsigned char Descriptor1;
    unsigned char Descriptor2;
}CPT112_Data;

/*DEFINE*/
#define Slave_Address 0x09

__CONFIG (
FOSC_INTOSC // INTOSC oscillator: I/O function on CLKIN pin
& WDTE_OFF // WDT disabled
& PWRTE_OFF // PWRT disabled
& MCLRE_ON // MCLR/VPP pin function is MCLR
//& MCLRE_OFF // MCLR/VPP pin function is Input
& CP_OFF // Program memory code protection is disabled
& CPD_OFF // Data memory code protection is disabled
& BOREN_OFF // Brown-out Reset disabled
& CLKOUTEN_OFF // CLKOUT function is disabled. I/O or oscillator function on the CLKOUT pin
& IESO_OFF // Internal/External Switchover mode is disabled
& FCMEN_OFF // Fail-Safe Clock Monitor is disabled
);

// Config Register: CONFIG2
__CONFIG (
WRT_OFF // Write protection off
//& PLLEN_OFF // 4x PLL disabled
& PLLEN_ON // 4x PLL enabled
& STVREN_ON // Stack Overflow or Underflow will cause a Reset
//& BORV_25 // Brown-out Reset Voltage (VBOR) set to 2.5 V
& LVP_OFF // High-voltage on MCLR/VPP must be used for programming
);

/*PROTOTYPES*/
void I2C_Conf();
void Start();
void Stop();
void Restart();
void ACK_S();
void NACK_S();
bit Write_byte(unsigned char bb);
unsigned char Read_byte(unsigned char ack);
void I2C_Wait();
CPT112_Data Read_CPT();

/*GLOAB VARIABLES*/
unsigned char END = 0;

void main(void) {
   
    unsigned char i;
    unsigned char PWM = 0;
    unsigned char addr_send;
   
    CPT112_Data Sensor;
   
    /*set 32MHz osc*/
    //OSCCON = 0xF0; //settato in questo modo non funziona
    /*wait for pll*/
    //while( !OSCSTATbits.PLLR );
   
    I2C_Conf();
   
    ANSELA = 0x00;
    ANSELC = 0x00;
   
    TRISCbits.TRISC2 = 1; //interrupt
    TRISCbits.TRISC3 = 0; //PWM output
   
    while(1){
       
        for(i = 0; i < PWM; i++){
            LATCbits.LATC3 = 1;
        }
        for(i = 0; i < (100-PWM); i++){
            LATCbits.LATC3 = 0;
        }
       
        /*active low*/
        if(!PORTCbits.RC2){
            Sensor = Read_CPT();
        }
       
    }
}


void I2C_Conf(){
   
    TRISC0=1;              // set SCL and SDA pins as inputs 16LF1823
   TRISC1=1;

   SSPCON1 = 0b00101000;    // I2C enabled, Master mode
   SSPCON2 = 0x00;

    SSPADD = 0x27;          // 100Khz 32MHz
   SSPSTAT = 0b10000000;    // Slew rate disabled
}

void Start(){
   
    //I2C_Wait();
    SSP1CON2bits.SEN = 1;
    while(SSP1CON2bits.SEN);
}

void Stop(){
   
    //I2C_Wait();
    SSP1CON2bits.PEN = 1;
    while(SSPCON2bits.PEN);
}

void Restart(){
   
    //I2C_Wait();
    SSP1CON2bits.RSEN = 1;
    while(SSPCON2bits.RSEN);
}

void ACK_S(){
   
    SSPCON2bits.ACKDT = 0;
    SSPCON2bits.ACKEN = 1;
   
    //while(SSPCON2bits.ACKEN);
}

void NACK_S(){

    SSPCON2bits.ACKDT = 1;
    SSPCON2bits.ACKEN = 1;
   
    //while(SSPCON2bits.ACKEN);
}

bit Write_byte(unsigned char bb){
   
    SSPBUF = bb;
    while(SSPSTATbits.BF);
    //I2C_Wait();
    return (~SSPCON2bits.ACKSTAT);
}

unsigned char Read_byte(unsigned char ack){
   
    unsigned char temp;
   
    //I2C_Wait();
    RCEN = 1;
    while(!SSP1STATbits.BF);
    //I2C_Wait();
    temp = SSPBUF;
    SSP1STATbits.BF = 0;
    //I2C_Wait();
    SSP1CON2bits.ACKEN = 1;
    while(SSP1CON2bits.ACKEN);
   
    return temp;
}

void I2C_Wait(){
   
    while (!END && (( SSPCON2 & 0x1F ) || ( SSPSTAT & 0x04 )));
}

CPT112_Data Read_CPT(){
   
    unsigned char addr_send;
    unsigned int counter;
   
    CPT112_Data My_Read;
   
    END = 0;
    //T2CONbits.TMR2ON = 1;
   
    addr_send = (Slave_Address << 1) | 1;
   
    /*i2c seq*/
    //Start();
    //I2C_Wait();
    Start();
   
    SSP1BUF = addr_send;
   
    while(SSPSTATbits.R_nW);

    while(SSPCON2bits.ACKSTAT);
   
    My_Read.Packet_Counter = Read_byte(1);
    My_Read.Descriptor1 = Read_byte(1);
    My_Read.Descriptor2 = Read_byte(1);
   
    Stop();
    //T2CONbits.TMR2ON = 0;
   
    return(My_Read);
}

void Timer0_Init(){
   
    CPSCON0bits.T0XCS = 0;
    /*internal clock source*/
    OPTION_REGbits.TMR0CS = 0;
    /*L to H*/
    OPTION_REGbits.TMR0SE = 0;
    /*PSPA ON*/
    OPTION_REGbits.PSA = 0;
    /*256 psa*/
    OPTION_REGbits.PS = 0b011;
}

void Timer2_Init(){
   
    T2CONbits.TMR2ON = 0; //off
    T2CONbits.T2OUTPS = 0x00;
    T2CONbits.T2CKPS = 0b11;
   
    PIE1bits.TMR2IE = 1;
    PIR1bits.TMR2IF = 0;
}


La parte che setta i bit tramite il __CONFIG mi è stata fatta da un conoscente vario tempo fa e con QUELLA configurazione sembra funzionare. Ricevo i dati corretti. Impostando invece il clock a 32MHz non funziona nulla.

La frequenza che vorrei ottenere nella comunicazione è di 100KHz e da come viene segnato dal datasheet del PIC stesso ad una frequenza di 32MHz dovrei impostare il valore di SSPADD a 0x4F mentre a 16MHz (i 4MHz interni fatti dal mio conoscente) a 0x27.

Non riesco proprio a capire dove sbaglio, se qualcuno potesse darmi una mano sarebbe molto apprezzato. Grazie mille O_/
Avatar utente
Foto UtenteMatts
0 2
 
Messaggi: 18
Iscritto il: 29 gen 2014, 17:55

0
voti

[2] Re: CPT112 e PIC16F1823

Messaggioda Foto Utenteluxinterior » 6 ott 2017, 19:17

Mi spiace di PIC non so nulla posso solo suggerirti quello che farei io quando si parla di clock
Configura un pin in output e commutalo a una detereminata frequenza (quella che ti viene più facile)
Verifica che la frequenza sul pin di output è proprio quella che ti aspetti.
Spesso con le diverse configurazioni nei registri del clock si rischia di fare confusione, o semplicemente sbaglaire un prescaler.
Avatar utente
Foto Utenteluxinterior
1.470 1 4 8
Expert EY
Expert EY
 
Messaggi: 726
Iscritto il: 6 gen 2016, 16:48


Torna a Firmware e programmazione

Chi c’è in linea

Visitano il forum: Nessuno e 3 ospiti