Вы вошли на сайт, как Гость
Регистрация

Обмен данными по шине CAN

Программные примеры для микроконтроллеров PIC - MPLab IDE
(Обмен данными по шине CAN)

Рассмотренная ниже программа каждую секунду выдает в шину CAN восемь последовательных чисел в диапазоне от 0 до 255. В то же время выполняется "прослушивание" шины CAN на предмет принятых данных с их последующей передачей на ПК через USART. В программе используется внешний файл canbus.с с библиотечными функциями CAN от компании CCS.

Примечание: при компиляции проекта требуется добавить в проект следующие библиотеки: "canbus.h".

canbus.c

void can_init(void) {
   can_set_mode(CAN_OP_CONFIG); 
   can_set_baud();

   RXB0CON=0;
   RXB0CON.rxm=CAN_RX_VALID;
   RXB0CON.rxb0dben=CAN_USE_RX_DOUBLE_BUFFER;
   RXB1CON=RXB0CON;

   CIOCON.endrhi=CAN_ENABLE_DRIVE_HIGH;
   CIOCON.cancap=CAN_ENABLE_CAN_CAPTURE;

   can_set_id(&RXM0EIDL, CAN_MASK_ACCEPT_ALL, 0); 
   can_set_id(&RXF0EIDL, 0, 0); 
   can_set_id(&RXF1EIDL, 0, 0); 

   can_set_id(&RXM1EIDL, CAN_MASK_ACCEPT_ALL, 1);
   can_set_id(&RXF2EIDL, 0, 1);  
   can_set_id(&RXF3EIDL, 0, 1);  
   can_set_id(&RXF4EIDL, 0, 1);  
   can_set_id(&RXF5EIDL, 0, 1);  

   set_tris_b((*0xF93 & 0xFB ) | 0x08); 

   can_set_mode(CAN_OP_NORMAL);
}

void can_set_baud(void) {
   BRGCON1.brp=CAN_BRG_PRESCALAR;
   BRGCON1.sjw=CAN_BRG_SYNCH_JUMP_WIDTH;

   BRGCON2.prseg=CAN_BRG_PROPAGATION_TIME;
   BRGCON2.seg1ph=CAN_BRG_PHASE_SEGMENT_1;
   BRGCON2.sam=CAN_BRG_SAM;
   BRGCON2.seg2phts=CAN_BRG_SEG_2_PHASE_TS;

   BRGCON3.seg2ph=CAN_BRG_PHASE_SEGMENT_2;
   BRGCON3.wakfil=CAN_BRG_WAKE_FILTER;
}

void can_set_mode(CAN_OP_MODE mode) {
   CANCON.reqop=mode;
   while( (CANSTAT.opmode) != mode );
}



void can_set_id(int* addr, long int id, int1 ext) {
   int *ptr;

   ptr=addr;

   if (ext) {
      *ptr=make8(id,0); //0:7

      ptr--;
      *ptr=make8(id,1); //8:15

      ptr--;
      *ptr=make8((int32)id,2) & 0x03; 
      *ptr|=(make8((int32)id,2) << 3) & 0xE0;
      *ptr|=0x08;

      ptr--;
      *ptr=((make8((int32)id,2) >> 5) & 0x07 );
      *ptr|=((make8((int32)id,3) << 3) & 0xF8);
   }
   else {  
      *ptr=0;

      ptr--;
      *ptr=0;

      ptr--;
      *ptr=(make8(id,0) << 5) & 0xE0;

      ptr--;
      *ptr=(make8(id,0) >> 3) & 0x1F;
      *ptr|=(make8(id,1) << 5) & 0xE0;
   }
}

long int can_get_id(int * addr, int1 ext) {
   long int ret;
   int * ptr;

   ret=0;
   ptr=addr;

   if (ext) {
      ret=*ptr;

      ptr--;    
      ret|=((long int)*ptr << 8);

      ptr--;   
      ret|=((long int)*ptr & 0x03) << 16;
      ret|=((long int)*ptr & 0xE0) << 18;

      ptr--;  
      ret|=((long int)*ptr << 21);

   }
   else {
      ptr-=2;   
      ret=((long int)*ptr & 0xE0) >> 5;

      ptr--;    
      ret|=((long int)*ptr << 3);
   }

   return(ret);
}

int can_putd(long int id, int * data, int len, int priority, int1 ext, int1 rtr) {
   int i;
   int * txd0;
   int ret;
   txd0=&TXRXBaD0;
   if (!TXB0CON.txreq) {
      CANCON.win=CAN_WIN_TX0;
      ret=0;
   }
   else if (!TXB1CON.txreq) {
      CANCON.win=CAN_WIN_TX1;
      ret=1;
   }
   else if (!TXB2CON.txreq) {
      CANCON.win=CAN_WIN_TX2;
      ret=2;
   }
   else return(0xFF);
   TXBaCON.txpri=priority;
   can_set_id(&TXRXBaEIDL, id, ext);
   TXBaDLC=len;
   TXBaDLC.rtr=rtr;
   for (i=0; i

Примечание: при компиляции проекта требуется добавить в проект следующие библиотеки: "18F458.h", "canbus.c".

CAN.c

#use delay(clock=10000000)
#fuses HS, BROWNOUT, WRT, NOWDT, WDT1
#use fast_io(B)
#use rs232(baud=19200,parity=N,xmit=PIN_C6,rcv=PIN_C7)

int ms;
struct rx_stat rxstat;
int32 rx_id;
int in_data[8];
int rx_len;
int out_data[8];
long int tx_id = 24;
char tx_rtr = 0;
char tx_ext = 0;
int tx_len = 8;
int tx_pri = 3;

#int_timer2
void isr_timer2(void)
{
  ms++;
}

void main()
{
  int i, j;
  setup_adc_ports(NO_ANALOGS);
  setup_adc(ADC_CLOCK_DIV_2);
  setup_psp(PSP_DISABLED);
  setup_spi(FALSE);
  setup_wdt(WDT_OFF);
  setup_timer_0(RTCC_INTERNAL);
  setup_timer_1(T1_disabled);
  setup_timer_3(T3_INTERNAL | T3_DIV_BY_1);
  setup_ccp1(CCP_PWM);
  setup_ccp2(CCP_PWM);
  setup_comparator(FALSE);
  for (i=0; i<8; i++)
  {
    out_data[i] = 0;
    in_data[i] =0;
  }
  setup_timer_2(T2_DIV_BY_4, 79, 16);
  can_init();
  enable_interrupts(INT_TIMER2);
  enable_interrupts(global);
  while(1)
  {
    if (can_kbhit())
    {
      if (can_getd(rx_id, in_data, rx_len, rxstat))
      {
        printf("\r\nGot: Buff=%U ID=%LU Len=%U Ovf=%U ",
               rxstat.buffer, rx_id, rx_len, rxstat.err_ovfl);
        printf("Filt=%U RTR=%U Ext=%U Inv=%U",
               rxstat.filthit, rxstat.rtr, rxstat.ext, rxstat.inv);
        printf("\r\n    Data = ");
        for (i=0; i 500))
    {
      ms = 0;
      for (i=0; i<8; i++) out_data[i] = j++;
      i = can_putd(tx_id, out_data, tx_len, tx_pri, tx_ext, tx_rtr);
      if (i != 0xFF)
      {
        printf("\r\nPut %U: ID=%LU Len=%U ", i, tx_id, tx_len);
        printf("Pri=%U Ext=%U RTR=%U\r\n   Data = ",
               tx_pri, tx_ext, tx_rtr);
        for (i=0; i 1000)
      {
        printf("\r\n\nCOMSTAT = %02X", COMSTATUS);
        printf("\r\nTXB0CON = %02X", TXB0CONR);
        printf("\r\nTXB1CON = %02X", TXB1CONR);
        printf("\r\nTXB2CON = %02X", TXB2CONR);
        printf("\r\nRXERRCNT = %U", RXERRCNT);
        printf("\r\nTXERRCNT = %U", TXERRCNT);
        ms = 0;
      }
    }
  }
}  

Файлы проекта можно скачать здесь: