1 votos

CAN no transmite datos de temperatura

He estado trabajando en un proyecto de bus CAN. Es un proyecto del libro Proyectos de microcontroladores avanzados por Dogan. Se trata de un proyecto de bus CAN de sensor de temperatura. Como sabes, el proyecto no puede ser simulado porque MCP2551 no está disponible en Proteus, así que lo implementé en`` hardware según el esquema del libro.

Enter image description here

Implementé el circuito en dos breadboards utilizando un bus CAN de pares trenzados. Utilicé el PIC18F458 con su módulo CAN incorporado. La longitud del bus es inferior a 500 cm. Cuando lo probé, sólo mostraba el mensaje de bienvenida en el LCD.Probé el código para la transmisión de caracteres. Funcionó pero para la temperatura no muestra datos.

Aquí está el código del nodo colector.

//unsigned char Can_Init_Flags, Can_Send_Flags,dt,len, Can_Rcv_Flags;
unsigned short init_flag, send_flag,len, read_flag;volatile int dt;
char SJW, BRP, Phase_Seg1, Phase_Seg2, Prop_Seg, txt[4];
long id, mask;
int bitvalue;
float vout, temperature; int flag;

#define d portb.b0

void adc_setting()
{
  adcon0 = 0x00;
  adcon1 = 0x80;
  intcon = 0xc0;
  pie1.adie = 1;
  pir1.adif = 0;
}

void interrupt()
{
  if (pir1.adif)
  {
    pir1.adif = 0;
    adcon0.adon = 0;
    flag = 1;
    adcon0.adon = 1;
    adcon0.go_done = 1;
  }
}

void main()
{
  //Portc=0x08;
  TRISA = 0xFF; // PORTA are inputs
  //TRISB = 0x08; // RB2 is output, RB3 is input
  //
  // Configure A/D converter
  //
  //ADC_Init();
  adc_setting();
  adcon0.adon = 1;
  adcon0.go_done = 1;

  //ADCON1 = 0x80;
  //
  // CAN BUS Timing Parameters
  //
  SJW = 1;
  BRP = 1;
  Phase_Seg1 = 6;
  Phase_Seg2 = 7;
  BRP = 1;
  Prop_Seg = 6;

  init_flag= _CAN_CONFIG_SAMPLE_THRICE &
             _CAN_CONFIG_PHSEG2_PRG_ON &
             _CAN_CONFIG_STD_MSG &
             _CAN_CONFIG_DBL_BUFFER_ON &
             _CAN_CONFIG_VALID_XTD_MSG &
             _CAN_CONFIG_LINE_FILTER_OFF;
              send_flag  = _CAN_TX_PRIORITY_0 &
              _CAN_TX_XTD_FRAME &
              _CAN_TX_NO_RTR_FRAME;
               read_flag=0;

     //
     // Initialise CAN module
     //
  CANInitialize(SJW, BRP, Phase_Seg1, Phase_Seg2, Prop_Seg,init_flag );
  //
  // Set CAN CONFIG mode
  //
  CANSetOperationMode(_CAN_MODE_CONFIG,0xFF);
  mask = -1;
  //
  // Set all MASK1 bits to 1's
  //
  CANSetMask(_CAN_MASK_B1, mask, _CAN_CONFIG_XTD_MSG);
  //
  // Set all MASK2 bits to 1's
  //
  CANSetMask(_CAN_MASK_B2, mask, _CAN_CONFIG_XTD_MSG);
  //
  // Set id of filter B1_F1 to 500
  //
  CANSetFilter(_CAN_FILTER_B1_F1,500,_CAN_CONFIG_XTD_MSG);
  //
  // Set CAN module to NORMAL mode
  //
  CANSetOperationMode(_CAN_MODE_NORMAL, 0xFF);

  // Program loop. Read the temperature from analog temperature sensor

  while(1) // Endless loop
  {
    //
    // Wait until a request is received
    //
    dt = 0;
    while (!dt) dt = CANRead (&id, i, &len, read_flag);
    if (id == 500 && i[0]=='T')
    {
      if (flag==1)
      {
        bitvalue = (adresh<<8)+adresl;
        vout = bitvalue * 0.00488;
        temperature = vout / 0.0100;

        i[0] = temperature;
        id = 3; // Identifier
        CANWrite (id, i, 1, send_flag); // send temperature
      }
    }
  }
}

Y aquí está el código del nodo de visualización

float temperature; unsigned char i[8];

unsigned short init_flag, send_flag, dt, len, read_flag;

char SJW, BRP, Phase_Seg1, Phase_Seg2, Prop_Seg, txt[4];

long id, mask;

sbit LCD_RS at RC4_bit;

sbit LCD_EN at RC5_bit;

sbit LCD_D4 at RC0_bit;

sbit LCD_D5 at RC1_bit;

sbit LCD_D6 at RC2_bit;

sbit LCD_D7 at RC3_bit;

sbit LCD_RS_Direction at TRISC4_bit;

sbit LCD_EN_Direction at TRISC5_bit;

sbit LCD_D4_Direction at TRISC0_bit;

sbit LCD_D5_Direction at TRISC1_bit;

sbit LCD_D6_Direction at TRISC2_bit;

sbit LCD_D7_Direction at TRISC3_bit;

// End LCD module connections

void main()
{
    TRISC = 0; // PORTC are outputs (LCD)

    //TRISB = 0x08; // RB2 is output, RB3 is input

    //
    // CAN BUS Parameters

    SJW = 1;

    BRP = 1;

    Phase_Seg1 = 6;

    Phase_Seg2 = 7;

    Prop_Seg = 6;

    Init_Flags = _CAN_CONFIG_SAMPLE_THRICE &
                     _CAN_CONFIG_PHSEG2_PRG_ON &
                     _CAN_CONFIG_STD_MSG &
                     _CAN_CONFIG_DBL_BUFFER_ON &
                     _CAN_CONFIG_VALID_XTD_MSG &
                     _CAN_CONFIG_LINE_FILTER_OFF;
    Send_Flags = _CAN_TX_PRIORITY_0 &
                     _CAN_TX_XTD_FRAME &
                     _CAN_TX_NO_RTR_FRAME;

    Can_Rcv_Flags = 0;

    //
    //
    // Initialize CAN module
    //
    //

    CANInitialize(SJW, BRP, Phase_Seg1, Phase_Seg2, Prop_Seg, init_flag);

    // Set CAN CONFIG mode
    //

    CANSetOperationMode(_CAN_MODE_CONFIG, 0xFF);

    mask = -1;

    // Set all MASK1 bits to 1's

    CANSetMask(_CAN_MASK_B1, mask, _CAN_CONFIG_XTD_MSG);

    // Set all MASK2 bits to 1's
    //

    CANSetMask(_CAN_MASK_B2, mask, _CAN_CONFIG_XTD_MSG);

    //
    // Set id of filter B2_F3 to 3

    //

    CANSetFilter(_CAN_FILTER_B2_F3, 3, _CAN_CONFIG_XTD_MSG);

    //
    // Set CAN module to NORMAL mode
    //

    CANSetOperationMode(_CAN_MODE_NORMAL, 0xFF);

    // Configure LCD

    Lcd_init(); // LCD is connected to PORTC

    Lcd_Out(1,1,"CAN BUS"); // Display heading on LCD

    Delay_ms(1000); // Wait for 2 seconds

    //
    // Program loop. Read the temperature from Node:COLLECTOR and display

    // on the LCD continuously
    //
    while(1) // Endless loop
    {
        Lcd_Out(1,1,"Temp = "); // Display "Temp = "
        //
        // Send a message to Node:COLLECTOR and ask for data
        //
        i[0] = 'T'; // Data to be sent
        id = 500; // Identifier
        CANWrite(id, i, 1, send_flag); // Send 'T'
        //
        // Get temperature from node:COLLECT
        //
        dt = 0;
        while(!dt)
            dt = CANRead(&id, i, &len, &read_flag);

        if(id == 3)
        {
            temperature = i[0];
            ByteToStr(temperature,txt); // Convert to string
            Lcd_Out(1, 8, txt); // Output to LCD
            Delay_ms(1000); // Wait 1 second
        }
    }
}

La temperatura no se muestra en absoluto. He intentado cambiar el código varias veces, pero el problema sigue siendo el mismo. He comprobado el pin tx del nodo colector en un osciloscopio digital. No mostró nada. No está transmitiendo ningún dato. ¿Por qué no transmite ningún dato?

¿Hay algún problema con mi código? ¿Debo eliminar la condición de solicitud en el nodo de transmisión y simplemente escribir datos en el segundo nodo y desactivar el filtro?

1voto

RelaXNow Puntos 1164

He implementado el circuito en dos prototipos utilizando un bus CAN de pares trenzados.

Todavía tienes que unir las tierras de ambos microcontroladores. CAN tolera cierta variación de modo común de las líneas del bus, pero no pueden estar flotando arbitrariamente. Dicho de otro modo, tienes que conectar los dos nodos con tres cables, el par trenzado para las líneas CANH y CANL, y un cable de tierra.

1voto

Neil Foley Puntos 1313

Este código no tiene ningún sentido:

    dt = 0;

    while(!dt);

        dt = CANRead(&id, b, &len, &Can_Rcv_Flags);

        if(id == 3)
        {
            temperature = b[0];

            ByteToStr(temperature,txt); // Convert to string

            Lcd_Out(1, 8, txt); // Output to LCD

            Delay_ms(1000); // Wait 1 second
        }
    }

Creo que estáis engañados por vuestra propia indención. El último corchete de arriba pertenece a la for(;;) - porque el bucle while no tiene llaves, sólo tiene un vacío ; declaración nula y sin cuerpo de bucle.

Así que las líneas dt = 0; while(!dt); son inútiles, porque dt es siempre cero en este punto.

Probablemente querías escribir

while(!dt)
{
  dt = CANRead(&id, b, &len, &Can_Rcv_Flags);
}

Esta sería la razón por la que debería usar siempre llaves después de cada declaración de control o bucle en su código, y nunca colocar punto y coma en la misma línea que uno. Los buenos compiladores advierten de estos puntos y comas.


De lo contrario, si esto fue intencional a pesar de la extraña sangría y dt es una variable compartida con un ISR, su código sigue siendo incorrecto porque dt no fue declarado como volatile y el compilador puede optimizarlo incorrectamente. Vea esto:

http://www.embedded.com/electronics-blogs/cole-bin/4418638/When-to-use---and-not-use---the-volatile-keyword

0voto

epsilon Puntos 1165

Mi opinión es que uno de estos mensajes no se recibe correctamente. El filtrado de mensajes aquí es importante: has configurado el filtro de recepción para que los dos mensajes que estás enviando sean de tipo extendido (id de 29 bits). ¿Puede verificar que envía los mensajes como tramas extendidas y que los módulos CAN se inicializan con las tramas extendidas activadas? Tu código no es completamente autoexplicativo al respecto.

Los mensajes estándar y los extendidos en el bus CAN son completamente diferentes. Si envía un mensaje estándar con un id de 5 y ha configurado el filtro de recepción para recibir mensajes extendidos con un id de 5, no recibirá nada.

i-Ciencias.com

I-Ciencias es una comunidad de estudiantes y amantes de la ciencia en la que puedes resolver tus problemas y dudas.
Puedes consultar las preguntas de otros usuarios, hacer tus propias preguntas o resolver las de los demás.

Powered by:

X