Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <pic18f258.h>
- //word at 0x2007 CONFIG = 0x3F72; // для WDT: 0x3F76
- code char at __CONFIG1H _conf1 = _OSC_HS_1H;
- code char at __CONFIG2H _conf3 = _WDT_OFF_2H;
- unsigned char mC_addr;
- unsigned char LED = 1;
- #define BIN(x) \
- ( ((0x##x##L & 0x00000001L) ? 0x01 : 0) \
- | ((0x##x##L & 0x00000010L) ? 0x02 : 0) \
- | ((0x##x##L & 0x00000100L) ? 0x04 : 0) \
- | ((0x##x##L & 0x00001000L) ? 0x08 : 0) \
- | ((0x##x##L & 0x00010000L) ? 0x10 : 0) \
- | ((0x##x##L & 0x00100000L) ? 0x20 : 0) \
- | ((0x##x##L & 0x01000000L) ? 0x40 : 0) \
- | ((0x##x##L & 0x10000000L) ? 0x80 : 0))
- enum CAN_OP_MODE{
- CAN_OP_MODE_BITS = BIN(11100000),
- CAN_OP_MODE_NORMAL = BIN(00000000),
- CAN_OP_MODE_SLEEP = BIN(00100000),
- CAN_OP_MODE_LOOP = BIN(01000000),
- CAN_OP_MODE_LISTEN = BIN(01100000),
- CAN_OP_MODE_CONFIG = BIN(10000000)
- };
- void CANSetOperationMode(enum CAN_OP_MODE mode){
- CANCON = mode;
- while( (CANSTAT & CAN_OP_MODE_BITS) != mode );
- }
- void init(){ // инициализация
- // настройка портов:
- // ADCON1: | ADFM | N/A | N/A | N/A | PCFG3 | PCFG2 | PCFG1 | PCFG0 |
- ADCON1 = 0x06; // Аналогово/цифровой порт работает в полностью цифровом режиме
- TRISA = 0; // все биты как выходы
- INTCON = 0; // отключить все прерывания
- // PIE1: | PSPIE | ADIE | RCIE | TXIE | SSPIE | CCP1IE | TMR2IE | TMR1IE |
- PIE1 = 1; // enable tmr1 int
- // PIE2:
- PIE2 = 0; // disable other int.s
- // INTCON: | GIE | PEIE | T0IE | INTE | RBIE | T0IF | INTF | RBIF |
- INTCON = 0xC0; // (1100000) - включить глобальные прерывания, прерывания по периферии
- PORTC = 0; // без напряжения
- PORTA = LED; // 6-ти битный аналогово/цифровой порт (0..5 биты)
- // получение адреса
- mC_addr = 1; // физический адрес устройства
- //mC_addr &= 0xE0; // выделение физического адреса
- TMR1H = 0; TMR1L = 0; // установить счетчики
- // T1CON: | - | - | T1CPS1 | T1CPS0 | T1OSCEN | T1SYNC | TMR1CS | TMR1ON |
- T1CON = 0x31; // (00110001) - включить таймер 1, предделитель на 1/8 (250 кГц)
- /*
- ************************ НАСТРОЙКА CAN-ИНТЕРФЕЙСА ************************
- */
- /* CANCON: | REQOP2..0 | ABAT | WIN2..0 | - |
- * REQOP == 1xx config; 011 listen only; 010 loopback; 001 disable; 000 normal
- * ABAT == 1 прервать отправку, 0 normal
- * WIN - выбор буфера (101 прием1, 100 передача0, 011 передача1, 010 передача 2, остальное - прием0
- */
- CANSetOperationMode(CAN_OP_MODE_CONFIG);
- TRISB = 0x80;
- // PIE3: | IRXIE | WAKIE | ERRIE | TXB2IE | TXB1IE | TXB0IE | RXB1IE | RXB0IE |
- PIE3 = 1;
- // IPR3 - флаги приоритета (по аналогии с PIE3)
- IPR3 = 1;
- /*
- * BRGCON1 - скорость
- * BRGCON1: | SJW1..0 | BRP5..0 |
- * SJW - Synchronized Jump Width bits ( Synchronization Jump Width Time = (SJW + 1)*T_Q )
- * BRP - множитель ( T_Q = 2*(BRP+1)/Fosc )
- */
- BRGCON1 = 1; // 250к
- /*
- * BRGCON2: | SEG2PHTS | SAM | SEG1PH2 | SEG1PH1 | SEG1PH0 | PRSEG2 | PRSEG1 | PRSEG0
- * SEGnPH - Phase Segment Time Select bits
- */
- BRGCON2 = BIN(00010000); // SEG1PH = 2(3штуки), PRSEG = 0(1штука)
- /*
- * BRGCON3: | N/A | WAKFIL | N/A | N/A | N/A | SEG2PH2 | SEG2PH1 | SEG2PH0 |
- * WAKFIL - использовать ли фильтр для wakeup
- */
- BRGCON3 = 0x02; // SEG2PH = 2(3 штуки)
- /*
- * RXB0CON - контроль приемного буфера
- * RXB0CON: | RXFUL | RXM1 | RXM0 | N/A | RXRTRRO | RXB0DBEN | JTOFF | FILHIT0 |
- * RXFUL == 1 - получено сообщение (обнулять вручную после считывания)
- * RXM = 01 - обычные сообщения со стандартным ID'ом
- * RXRTRRO - (readonly) - запрос на трансфер
- * RXB0DBEN == 1 - двойная буферизация (после записи в 0й буфер идет запись в 1й)
- * JTOFF - readonly-копия RXB0DBEN
- * FILHIT0 - номер фильтра (RXF0 или RXF1)
- */
- RXB0CON = BIN(00100000);
- /*
- * CIOCON: | N/A | N/A | ENDRHI | CANCAP | N/A.. |
- * ENDRHI: Enable Drive High bit
- * 1 = CANTX pin will drive VDD when recessive
- * 0 = CANTX pin will tri-state when recessive
- * CANCAP: CAN Message Receive Capture Enable bit
- */
- //CIOCON = 0x20;
- // RXFnSIDH[L] - фильтр по идентификатору
- RXF0SIDH = 0;
- RXF0SIDL = 0x20; // ид = 1
- // RXMnSIDH[L] - маска фильтра по идентификатору
- RXM0SIDH = 0xff; // принимаем только адресованные нам сообщения
- RXM0SIDL = 0xe0;
- /*
- * TXBnSIDH[L] - два байта стандартного идентификатора контроллера
- * EXIDE должен быть = 0, чтобы идентификатор был 2х, а не 4х-байтным
- * TXBnSIDH: | SID10 .|. SID3 |
- * TXBnSIDL: | SID2 | SID1 | SID0 | N/A | EXIDE | N/A | EID17 | EID16 |
- */
- TXB0SIDH = 0;
- TXB0SIDL = 0x20;
- /*
- * TXBnDLC - длина передачи
- * TXBnDLC: | N/A | TXRTR | N/A | N/A | DLC3 .. DLC0 |
- * Для восьмибайтной посылки DLC = 1000, TXRTR = 0?
- */
- //TXB0DLC = 0x01; // однобайтные посылки
- CANSetOperationMode(CAN_OP_MODE_NORMAL);
- /*
- ************************ конец настройки CAN-ИНТЕРФЕЙСА ************
- */
- }
- void CANsend(unsigned char byte){
- /*
- * TXBnCON - контрольные регистры n-го буфера передачи
- * TXBnCON: | N/A | TXABT | TXLARB | TXERR | TXREQ | N/A | TXPRI1 | TXPRI0 |
- * если биты 6-4 == 1 - ошибка во время передачи
- * TXREQ = 1 - запрос на отсылку сообщения (если он == 1 и его обнулить, сообщение прервется)
- * TXPRI - приоритет (чем больше, тем выше)
- */
- while(TXB0CONbits.TXREQ); // если была заявка на отправку - ждем
- CANCON &= BIN(11110001);
- CANCON |= BIN(00001000); // данные - из буфера 0
- TXB0CON |= 1;
- // TXBnDm - отсылаемые данные
- TXB0D0 = byte; // всего 8 буферов TXBn0 .. TXBn7
- TXB0DLC = 1; // один байт
- TXB0CON |= 8; // TXREQ0 = 1;
- CANCON &= BIN(11110001);
- // TXERRCNT - счетчик ошибок передачи
- // после успешной передачи TXREQ0 сброшен, TXBUFE=1 ; иначе - устанавливается код ошибки TXERR
- // если передача успешна и TXIE=1, генерируется прерывание
- }
- void CANreceive(){
- unsigned char byte;
- /* RXB1CON отличается битами 0..3:
- * RXB1CON: ...| FILHIT2..0 |
- * FILHIT - номер принимающего фильтра (от 0 до 5)
- */
- /* RXBnSIDH[L] - идентификатор принятого сообщения
- * SIDH аналогичен TXBnSIDH,
- * SIDL.4 - SRR, при EXID==0 является копией RXRTRRO (RXnBCON.3)
- */
- if(RXB0CONbits.RXFUL){
- // RXBuffer0 is full.
- CANCON &= BIN(11110001);
- // Clear the received flag.
- PIR3bits.RX0IF = 0;
- // forget any previous overflow
- COMSTATbits.RXB0OVFL = 0;
- /*if(RXB0CONbits.RX0DBEN){
- *MsgFlags |= RXB0CON & CAN_RX_FILTER_BITS;
- *MsgFlags &= 0x01;
- }*/
- }else if(RXB1CONbits.RXFUL){
- // RXBuffer1 is full
- CANCON &= BIN(11110001);
- CANCON |= BIN(00001010);
- // Clear the received flag.
- PIR3bits.RX1IF = 0;
- // and forget any previous overflow
- COMSTATbits.RXB1OVFL = 0;
- //*MsgFlags |= RXB1CON & CAN_RX_FILTER_BITS;
- //if ( *MsgFlags < 0x02 )
- //*MsgFlags |= CAN_RX_DBL_BUFFERED;
- }
- // RXBnDLC - длина сообщения, аналогично TXBnDLC
- PORTA = RXB0DLC & BIN(00001111);
- // RXERRCNT - счетчик ошибок
- // RXBnDm - принятые данные
- // всего 8 буферов RXBn0 .. RXBn7
- byte = RXB0D0;
- // Restore default RXB0 mapping.
- CANCON &= BIN(11110001);
- // Clear any previous invalid message bit flag
- PIR3bits.IVRF = 0;
- RXB0CONbits.RXFUL = 0;
- RXB1CONbits.RXFUL = 0;
- CANsend(byte);
- }
- void timer1int(){
- T1CON = 0; // выключить таймер
- PORTA = LED;
- LED <<= 1;
- if(LED > 0x20) LED = 1;
- CANsend(LED);
- PIR1bits.TMR1IF = 0; // сбросить флаг прерывания
- PIE1bits.TMR1IE = 1;
- TMR1H = 0x30; TMR1L = 0xD4; // установить счетчики, 0.1с
- // T1CON: | - | - | T1CPS1 | T1CPS0 | T1OSCEN | T1SYNC | TMR1CS | TMR1ON |
- T1CON = 0x31; // (00110001) - включить таймер 1, предделитель на 1/8 (125 кГц)
- }
- void on_interrupt() __interrupt 1{ // обработка прерываний
- // CANSTAT: OPMODEx3 N/A ICODEx3 N/A
- // ICODE - код прерывания
- unsigned char icode = CANSTAT & 0x0E; // выделяем ICODE
- if(PIR1bits.TMR1IF == 1) // поступило прерывание от таймера
- timer1int(); // обработать прерывание
- if(!PIR3) return; // не было CAN-прерывания
- T1CON = 0; // выключить таймер
- icode >>= 1; // сдвигаем
- switch(icode){
- case 7: break; // Wake up on
- case 5: // RXB1
- case 6: CANreceive(); break; // RXB0
- case 4: break; // TXB0
- case 3: break; // TXB1
- case 2: break; // TXB2
- case 1: break; // ERR
- case 0: break; // no interrupt
- }
- // PIR3 - флаги прерываний шины
- // PIR3: | IRXIF | WAKIF | ERRIF | TXB2IF | TXB1IF | TXB0IF | RXB1IF | RXB0IF |
- PIR3 = 0;
- T1CON = 0x31;
- // COMSTAT - ошибки шины
- // COMSTAT: | RXB0OVFL | RXB1OVFL | TXBO | TXBP | RXBP | TXWARN | RXWARN | EWARN |
- }
- void main(){ // основной цикл
- init();
- while(1){};//CLRWDT};
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement