Autor Tema: Ayuda I2C en pic18F4550 y Arduino UNO  (Leído 102 veces)

0 Usuarios y 1 Visitante están viendo este tema.

Desconectado joro

  • PIC10
  • *
  • Mensajes: 2
Ayuda I2C en pic18F4550 y Arduino UNO
« en: 28 de Mayo de 2020, 15:06:23 »
Hola, para practicar en casa decidí aprender sobre la comunicación I2C. Me leí el datasheet del pic18f4550 y del atmega328 del arduino. Claro que existen librerías que me ayudarían pero en esta ocasión decidí trabajar sin las librerías y manipular los registros, habilitar las interurpciones, etc. para ver si realmente entendí del tema (ya luego para proyectos me apoyaría en librerías).

Entonces, en mi código pienso usar al arduino como maestro y el pic18f4550 como esclavo, además que solo pienso realizar transmisión de datos. Tengo en el arduino conectado un display 7 segmentos que me muestra en qué estado de la comunicación I2C se encuentra (ej: si me sale '2' es porque se realizó el START) y un boton que empezaría con la comunicación. En el lado del esclavo, tengo 3 pins conectados a leds, 1 indica cuando el pic está prendido (y si se apaga luego es porque ocurrió una interrupción del I2C), y los otros 2 varían según el dato recibido del arduino (para confirmar si el dato llegó).

El problema: por parte del arduino, solo llega hasta el START, en la siguiente interrupción luego del START, el TWSR (status register) se carga con puros 1, y dicho valor no existe entre todos los estados posibles por lo que se va al  'default' y muestra el #9 en el display. Por parte del pic18F4550, ni ocurre la interrupción (ya que se apagaría el led1) del I2C.

Por último, en el pic18f4550 lo programe en assembler, los pull up resistors son de 4.7k, scl está a 100Khz (o eso es lo que intento colocar) y el clock del pic18f4550 está a 16Mhz (usando PLL)
« Última modificación: 28 de Mayo de 2020, 17:12:13 por joro »

Desconectado joro

  • PIC10
  • *
  • Mensajes: 2
Re:Ayuda I2C en pic18F4550 y Arduino UNO
« Respuesta #1 en: 28 de Mayo de 2020, 15:10:12 »
(primera vez en el foro, sigo probando cómo mostrar el código)
código arduino uno, maestro I2C:

Código: [Seleccionar]
void Preparar_I2C();
volatile byte dato_envio = 0x01;
byte aux = 0x00;

#define num_0 0x40
#define num_1 0x79
#define num_2 0x24
#define num_3 0x30
#define num_4 0x19
#define num_5 0x12
#define num_6 0x02
#define num_7 0x78
#define num_8 0x00
#define num_9 0x18

void setup() {
  Preparar_I2C();
  pinMode(8,INPUT);
  DDRD = 0xFF;        //configuro puertos 0-7
  PORTD = num_0;   //asigno valor a esos puertos
}

void loop() {
  if (digitalRead(8)==HIGH && aux==0x00 ){
    TWCR = 0xE5;  //START I2C
    aux = 0x10;
    PORTD = num_1;
  }
  //PORTD = TWSR >> 3;
}

ISR(TWI_vect) { 
  byte Estado = TWSR & 0xFC;  //enmascaro
 
  //SOLO CASO TRANSMISION DE DATOS
  switch (Estado){
    case 0x08:  //START
      TWDR = 0x1E;    //cargar ADDRESS + W/R (W=0)
      TWCR &= 0xDF;   //Limpio START bit
      PORTD = num_2;
      break;
    case 0x10:  //REPEATED START
      TWDR = 0x1E;
      TWCR &= 0xDF;
      PORTD = num_3;
      break;
    case 0x18:  //SLA+W llegó
      TWDR = dato_envio;     //DATO A ENVIAR
      PORTD = num_4;
      break;
    case 0x20:  //SLA+W no llegó
      TWCR |= 0x10;       //genero STOP
      PORTD = num_5;
      break;
    case 0x28:  //Dato llegó
      TWCR |= 0x10;
      PORTD = num_6;
      break;
    case 0x30:  //Dato no llegó
      TWCR |= 0x10;
      PORTD = num_7;
      break;
    case 0x38:  //Arbitraje perdido SLA+W o Dato
      TWCR |= 0x10;
      PORTD = num_8;
      break;
    default:
      TWCR |= 0x10;
      PORTD = num_9;
      break;
  }
  TWCR |= 0x80;   //Seteo Int Flag
}

void Preparar_I2C() {
  SREG |= 0x80;       //Me aseguro (Ya estaba predeterminadamente)
  TWCR = 0x45;        //habilito I2C, ACK e INT
  //SCL = 100Khz (máximo 400Khz)
  TWBR = 0x48; //72
  TWSR = 0x00;
}

Código pic18f4550 assember, esclavo:
Código: [Seleccionar]
    list p=18f4550   ;modelo de microcontrolador
    #include<p18f4550.inc>   ;Libreria de modelo de registros
   
    CONFIG FOSC = XTPLL_XT   ; Oscilator + PLL enabled
    CONFIG PLLDIV = 1
    CONFIG CPUDIV = OSC4_PLL6   ; OSC = 16Mhz
    CONFIG  PWRT = ON             ; Power-up Timer Enable bit (PWRT enabled)
    CONFIG  BOR = OFF             ; Brown-out Reset Enable bits (Brown-out Reset disabled in hardware and software)
    CONFIG  WDT = OFF             ; Watchdog Timer Enable bit (WDT disabled (control is placed on the SWDTEN bit))
    CONFIG  PBADEN = OFF          ; PORTB A/D Enable bit (PORTB<4:0> pins are configured as digital I/O on Reset)
    CONFIG  LVP = OFF             ; Single-Supply ICSP Enable bit (Single-Supply ICSP disabled)
    CONFIG  CCP2MX = ON           ; CCP2 MUX bit (CCP2 input/output is multiplexed with RC1)
    CONFIG  MCLRE = ON            ; MCLR Pin Enable bit (MCLR pin enabled; RE3 input pin disabled)
   
    dato_leido EQU 0x60
    dato_escrito1 EQU 0x61
    dato_escrito2 EQU 0x62
   
    org 0x0000 ;Vector de RESET
    goto configuro
   
    org 0x008
    goto Interrupt
   
    org 0x0020
configuro:
    movlw 0x03     ;SDA y SCL como INPUT
    movwf TRISB     ;pin2 -> indicador de pic corriendo
    bcf TRISD,0     ;muestra el dato recibido por arduino
    bcf TRISD,1
   
    movlw 0x01    
    movwf dato_escrito1
    movlw 0x02
    movwf dato_escrito2     ;revelará si D/A indica el byte actual leido o el anterior
   
    movlw 0xC0
    movwf INTCON    ;General Interrupt y Peripherical
    movlw 0x08
    movwf PIE1     ;habilitar I2C interrupt
    bcf PIR1,3     ;limpio flag
    movlw 0x80
    movwf SSPCON2   ;habilitar general call y SEN = 0
    movlw 0x1E
    movwf SSPADD    ;asigno ADDRESS como esclavo
    movlw 0x36
    movwf SSPCON1   ;habilitar I2C y modo esclavo (sin INT en S y P)
   
    bsf LATB,2
    clrf LATD
   
main:
    movf dato_leido,0
    movwf LATD
    goto main
   
Interrupt:
    bcf LATB,2 ;indica si hubo interrupción
    btfsc SSPSTAT,2     ;Chekeo R/W (R=0)
    goto Estado_T
    goto Estado_R

Estado_T:
    btfsc SSPSTAT,5
    movf dato_escrito2,0     ;si D/A=1 -> cargar dato2
    btfss SSPSTAT,5
    movf dato_escrito1,0     ;si D/A=0 -> cargar dato1
    movwf SSPBUF
    bsf SSPCON1,4     ;CKP=1 -> continuar SCL
    bcf PIR1,3     ;bajar flag
    retfie
   
Estado_R:
    movf SSPBUF,0    
    btfsc SSPSTAT,5     ;chekeo D/A (0: anterior byte fue direccion)
    movwf dato_leido     ;dato recibido y guardado en registro
    clrf SSPBUF     ;limpiar SSPBUF y bajar flag
    bcf PIR1,3
    retfie

    end