Пятница, Сентябрь 18, 2020

Слушаем EDC16C39 canbus 500kbps 11bit ID

#include<p18cxxx.h>
#include<delays.h>
#include<xlcd.h>
#include<usart.h>
#pragma config OSC=HS
#pragma config WDT=OFF
#pragma config LVP=OFF
#pragma config MCLRE=OFF
#pragma config BOREN=OFF
#pragma config PBADEN=OFF
#define DELAY 100
//*******************??????????**************************************
#pragma udata
char addr_1st=0;
char RxIn=0;
char RxBuf[17]={0x89,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
char asc[17]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
char no_recive[]="RXFUL";
char CanRxBuf[16]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
//**********************************************************
#pragma code
void MyHighInt(void);
void MyLowInt(void);
#pragma interrupt MyHighInt
#pragma code high_vector=0x08
void high_vector(void){
    _asm GOTO MyHighInt _endasm
}
#pragma interrupt MyLowInt
#pragma code low_vector=0x18
void low_vector(void){
    _asm GOTO MyLowInt _endasm
}
//*******************************************************************
#pragma code
void DelayFor18TCY(void)
{
    Delay10TCYx(60);
}
void DelayPORXLCD(void)
{
    Delay1KTCYx(200);
}
void DelayXLCD(void)
{
    Delay1KTCYx(70);
}
void  ClrLCD(char addr);
void  StrToLCD(char* str,char addr,char delay);
char* HexToASCII(char *sour,char *dest,int len);
void  InitCAN(void);
void  TxCan(char TxByte);
void  RxCan(void);
//******************Главная функция***************************************
void main(void)
{
    ADCON1=0;
    ADCON1=0x0f;
    OpenXLCD(FOUR_BIT & LINES_5X7);
    while(BusyXLCD());
    WriteCmdXLCD(CURSOR_OFF&BLINK_OFF);
    InitCAN();
    while(1)
    {
        RxCan(); 
    }
}
//????? ??????
void  RxCan(void){
    int i;
    if(!RXB0CONbits.RXFUL){           //проверим есть что нить в буфере RXB0
        StrToLCD(no_recive,0x8b,1);   //если нет,то выведем на экран
        for(i=0;i<16;i++)             //почистим буфер
            CanRxBuf[i]=0;
        return;
    }
//Для приёма сообщений будем использовать только один буфер, RXB0.
//Из буфера сборки сообщения MAB готовое сообщение поступает в приёмный буфер и генерируется
//соответствующее прерывание. Чтобы прочитать сообщение из приёмного буфера, нужно выполнить
//следующие действия:
//1) Извлечь идентификатор сообщения из следующих регистров:
//RXB0SIDH ? содержит старший байт стандартной части идентификатора.
    CanRxBuf[0]=RXB0SIDH;
//RXB0SIDL ? содержит младшие три бита стандартной части идентификатора, флаг удалённого
//запроса для стандартных сообщений (в расширенном сообщении он всегда равен нулю ? см. описание
//регистров CAN), бит типа сообщения (так как принимаем только расширенные сообщения, этот бит
//будет установлен в единицу), а также два старших бита расширенного идентификатора.
    CanRxBuf[1]=RXB0SIDL;
//RXB0EIDH ? содержит старший байт расширенной части идентификатора.
    CanRxBuf[2]=RXB0EIDH;
//RXB0EIDL ? содержит младший байт расширенной части идентификатора.
    CanRxBuf[3]=RXB0EIDL;
//2) Из регистра RXB0DLC считать длину данных.
    CanRxBuf[4]=RXB0DLC;
//3) Извлечь данные из следующих регистров:
//RXB0Dm ? m байтов данных (от 0 до 8 байт).
    CanRxBuf[5]=RXB0D0;
    CanRxBuf[6]=RXB0D1;
    CanRxBuf[7]=RXB0D2;
    CanRxBuf[8]=RXB0D3;
    CanRxBuf[9]=RXB0D4;
    CanRxBuf[10]=RXB0D5;
    CanRxBuf[11]=RXB0D6;
    CanRxBuf[12]=RXB0D7;
//преобразуем и на LCD
    HexToASCII(CanRxBuf,asc,5);
    StrToLCD(asc,0x80,200);
    HexToASCII(CanRxBuf+5,asc,8);
    StrToLCD(asc,0xc0,200);
//4) сбросить бит RXFUL в регистре RXB0CON, освобождая буфер для приёма нового сообщения.
    RXB0CONbits.RXFUL=0;
}
//**************************************************************************************************
//Включение и настройка модуля CAN
//Для включения модуля CAN в работу необходимо выполнить следующие действия:
void  InitCAN(void){
//1) настроить выводы RB2 и RB3 порта PORTB как порты ввода-вывода модуля CAN установкой бита
//TRISB<3> в единицу (линия RX), а бита TRISB<2> в ноль (линия TX).
    TRISBbits.TRISB3=1;
    TRISBbits.TRISB2=0;
//2) в регистре CANCON установить биты REQOP2:REQOP0 в '100' (режим настройки), затем ждать,
//пока не установится этот режим, проверяя биты OPMODE2:OPMODE0 в регистре CANSTAT. Как
//только эти биты примут значение '100', значит, режим установился и можно перейти к следующему шагу.
    CANCON=0x80;
    while ((CANSTAT & 0xE0) != 0x80);
//3) произвести настройку приёмных фильтров и масок, настройку прерываний (если они
//используются)*. Так как фильтры использоваться не будут, устанавливаем в ноль значения всех
//регистров масок:
//RXMnSIDH ? регистры масок, содержащие критерий для старших битов стандартного
//идентификатора.
//RXMnSIDL - регистры масок, содержащие критерий для младших битов стандартного
//идентификатора и старших битов расширенного идентификатора, а также флага
//стандартный/расширенный идентификатор (флаг типа сообщения).
//RXMnEIDH - регистры масок, содержащие критерий для средних битов расширенного
//идентификатора.
//RXMnEIDL - регистры масок, содержащие критерий для младших битов расширенного
//идентификатора.
    RXM0SIDH=0x00;
    RXM0SIDL=0x00;
    RXM1SIDH=0x00;
    RXM1SIDL=0x00;
    RXM0EIDH=0x00;
    RXM0EIDL=0x00;
    RXM1EIDH=0x00;
    RXM1EIDL=0x00;
//4) произвести настройку приёмных буферов. Так как в нашем случае используется только один
//приёмный буфер, нужно настроить его для работы в режиме приёма всех действительных расширенных
//сообщений установкой в '10' битов RXM1:RXM0 регистра RXB0CON и запретить дублирование буфера
//сбросом бита RX0DBEN регистра RXB0CON.
//    RXB0CONbits.RXM0=0;
//    RXB0CONbits.RXM1=1;
//    RXB0CONbits.RXB0DBEN=0;
//Кроме режимов работы модуля CAN дополнительно можно задать режимы приёма сообщений. Они
//задаются с помощью битов RXM1:RXM0 управляющих регистров приёмных буферов (RXBnCON).
//Возможны следующие режимы:
//1) приём всех безошибочных сообщений (RXM1:RXM0 = '00') ? принимаются все сообщения, не
//содержащие ошибок, независимо от типа сообщения.
//2) приём безошибочных сообщений только со стандартным идентификатором (RXM1:RXM0 ='01').
//3) приём безошибочных сообщений только с расширенным идентификатором (RXM1:RXM0 = '10').
//4) приём сообщений с ошибками* (RXM1:RXM0 = '11') ? в этом случае в приёмный буфер
//копируются все сообщения, в том числе и сообщения с ошибками, независимо от типа идентификатора.
//Этот режим следует использовать только при тестировании системы.
//Прикол в том ,что если включить в CANCON нормальный режим работы (REQOP2:REQOP0 = '000')
//то при таких настройках(RXM1:RXM0 = '11'),MPC2551 будет принимать по TXD и отправлять
//на PIC18F2480 данные по RXD.Если поднять первую ногу TXD MCP2551,то передача байтов не проходит.
//Если замыкать пинцетом отпаянную ногу TXD,то данные проходят.
    RXB0CONbits.RXM0=1;
    RXB0CONbits.RXM1=0;
    RXB0CONbits.RXB0DBEN=0;
//5) произвести настройку скорости передачи. Для этого необходимо рассчитать значения сегментов
//времени и ширины фазового перехода и занести в регистры BRGCON1, BRGCON2, BGRCON3. Более
//подробно процесс настройки скорости передачи описывается ниже.
/*
//20MHz 50kbps
    BRGCON1=0x18;
    BRGCON2=0x90;
    BRGCON3=0x02;
    */
/*
//20MHz 100kbps
    BRGCON1=0x09;
    BRGCON2=0xa0;
    BRGCON3=0x02;
*/
    /*
//20MHz 150kbps
    BRGCON1=0x02;
    BRGCON2=0xbc;
    BRGCON3=0x07;
*/
 /*
//20MHz 250kbps
    BRGCON1=0x04;
    BRGCON2=0x90;
    BRGCON3=0x02;
*/
//20MHz 500kbps
    BRGCON1=0x00;
    BRGCON2=0xba;
    BRGCON3=0x07;
//6) настроить регистр CIOCON ? установить бит ENDRHI, чтобы притянуть вывод TX к питанию в
//рецессивном состоянии, и сбросить бит CANCAP, чтобы отключить режим захвата CAN с помощью
//модуля CCP1 (этот режим используется для реализации временно?й метки, которую в нашем простом
//примере использовать не будем).
    CIOCONbits.ENDRHI=1;
    CIOCONbits.CANCAP=0;
//7) установить нормальный режим работы (REQOP2:REQOP0 = '000') и дождаться, пока этот режим
//установится (OPMODE2:OPMODE0 = '000').
    CANCON=0b00000000;
    while ((CANSTAT & 0b11100000) != 0b00000000);
//4) режим петли (loopback) (REQOP2:REQOP0 = '010') - позволяет осуществить передачу сообщения
//по внутренним цепям модуля от передающего буфера в приёмный буфер без выдачи сообщения на
//шину CAN. Этот режим можно использовать при разработке и тестировании системы. В этом режиме
//бит ACK игнорируется, и устройство будет признавать входящие сообщения от самого себя, как если
//бы они поступали от других узлов. При этом сообщения с шины не принимаются и на шину не
//передаются, включая флаги ошибок и сигналы подтверждения.
 //   CANCON=0b01000000;
  //  while ((CANSTAT & 0b11100000) != 0b01000000);
//Далее модуль функционирует в нормальном режиме, то есть можно принимать и передавать
//сообщения.
}
//*******************???????? ???? ?? ?????????? ?? Rx**************
void MyHighInt(void){
}
//******************************************************************
void MyLowInt(void){
}
char* HexToASCII(char *sour,char *dest,int len)
{
    int i;
    char tmp;
    int j=0;
    for(i=0;i<len;i++){
        tmp=((sour[i]>>4)&0x0f);
        if(tmp<=9){
            dest[j]=tmp+0x30;
        }
        else if(tmp>=0x0A && tmp<=0x0F){
            dest[j]=tmp+0x37;
        }
        j++;
        tmp=sour[i];
        tmp=tmp &= 0x0f;
        if(tmp<=9){
            dest[j]=tmp+0x30;
        }
        else if(tmp>=0x0A && tmp<=0x0F){
            dest[j]=tmp+0x37;
        }
        j++;
    }
    dest[j]=0;
    return dest;
}
void ClrLCD(char addr){
    int i;
    while(BusyXLCD());
    SetDDRamAddr(addr);
    for(i=0;i<16;i++){
        while(BusyXLCD());
        WriteDataXLCD(' ');
    }
}
void  StrToLCD(char* str,char addr,char delay){
    //ClrLCD(addr);
    while(BusyXLCD());
    SetDDRamAddr(addr);
    putsXLCD(str);
   // Delay10KTCYx(delay);
}
Back to Top