Advertisement
Guest User

Eddy_Em

a guest
Jun 28th, 2011
571
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 9.95 KB | None | 0 0
  1. #include <pic18f258.h>
  2.  
  3. //word at 0x2007 CONFIG = 0x3F72; // для WDT: 0x3F76
  4. code char at __CONFIG1H _conf1  = _OSC_HS_1H;
  5. code char at __CONFIG2H _conf3  = _WDT_OFF_2H;
  6.  
  7. unsigned char mC_addr;
  8.  
  9. unsigned char LED = 1;
  10.  
  11. #define BIN(x) \
  12.     ( ((0x##x##L & 0x00000001L) ? 0x01 : 0) \
  13.     | ((0x##x##L & 0x00000010L) ? 0x02 : 0) \
  14.     | ((0x##x##L & 0x00000100L) ? 0x04 : 0) \
  15.     | ((0x##x##L & 0x00001000L) ? 0x08 : 0) \
  16.     | ((0x##x##L & 0x00010000L) ? 0x10 : 0) \
  17.     | ((0x##x##L & 0x00100000L) ? 0x20 : 0) \
  18.     | ((0x##x##L & 0x01000000L) ? 0x40 : 0) \
  19.     | ((0x##x##L & 0x10000000L) ? 0x80 : 0))
  20.  
  21. enum CAN_OP_MODE{
  22.     CAN_OP_MODE_BITS    = BIN(11100000),
  23.     CAN_OP_MODE_NORMAL  = BIN(00000000),
  24.     CAN_OP_MODE_SLEEP   = BIN(00100000),
  25.     CAN_OP_MODE_LOOP    = BIN(01000000),
  26.     CAN_OP_MODE_LISTEN  = BIN(01100000),
  27.     CAN_OP_MODE_CONFIG  = BIN(10000000)
  28. };
  29.  
  30. void CANSetOperationMode(enum CAN_OP_MODE mode){
  31.     CANCON = mode;
  32.     while( (CANSTAT & CAN_OP_MODE_BITS) != mode );
  33. }
  34.  
  35. void init(){ // инициализация
  36. // настройка портов:
  37. //  ADCON1: | ADFM | N/A | N/A | N/A | PCFG3 | PCFG2 | PCFG1 | PCFG0 |
  38.     ADCON1 = 0x06; // Аналогово/цифровой порт работает в полностью цифровом режиме
  39.     TRISA = 0; // все биты как выходы
  40.     INTCON = 0; // отключить все прерывания
  41. //  PIE1: | PSPIE | ADIE | RCIE | TXIE | SSPIE | CCP1IE | TMR2IE | TMR1IE |
  42.     PIE1 = 1; // enable tmr1 int
  43. //  PIE2:
  44.     PIE2 = 0; // disable other int.s
  45. //  INTCON: | GIE | PEIE | T0IE | INTE | RBIE | T0IF | INTF | RBIF |
  46.     INTCON = 0xC0; // (1100000) - включить глобальные прерывания, прерывания по периферии
  47.     PORTC = 0; // без напряжения
  48.     PORTA = LED; // 6-ти битный аналогово/цифровой порт (0..5 биты)
  49. // получение адреса
  50.     mC_addr = 1; // физический адрес устройства
  51.     //mC_addr &= 0xE0; // выделение физического адреса
  52.     TMR1H = 0; TMR1L = 0;  // установить счетчики
  53. // T1CON: | - | - | T1CPS1 | T1CPS0 | T1OSCEN | T1SYNC | TMR1CS | TMR1ON |
  54.     T1CON = 0x31; // (00110001) - включить таймер 1, предделитель на 1/8 (250 кГц)
  55. /*
  56.  ************************ НАСТРОЙКА CAN-ИНТЕРФЕЙСА ************************
  57.  */
  58. /*  CANCON: | REQOP2..0 | ABAT | WIN2..0 | - |
  59.  *      REQOP == 1xx config; 011 listen only; 010 loopback; 001 disable; 000 normal
  60.  *      ABAT == 1 прервать отправку, 0 normal
  61.  *      WIN - выбор буфера (101 прием1, 100 передача0, 011 передача1, 010 передача 2, остальное - прием0
  62.  */    
  63.     CANSetOperationMode(CAN_OP_MODE_CONFIG);
  64.     TRISB = 0x80;
  65. //  PIE3: | IRXIE | WAKIE | ERRIE | TXB2IE | TXB1IE | TXB0IE | RXB1IE | RXB0IE |
  66.     PIE3 = 1;
  67. //  IPR3 - флаги приоритета (по аналогии с PIE3)
  68.     IPR3 = 1;
  69. /*
  70.  *  BRGCON1 - скорость
  71.  *  BRGCON1: | SJW1..0 | BRP5..0 |
  72.  *      SJW -  Synchronized Jump Width bits ( Synchronization Jump Width Time = (SJW + 1)*T_Q )
  73.  *      BRP - множитель ( T_Q = 2*(BRP+1)/Fosc )
  74.  */
  75.     BRGCON1 = 1; // 250к
  76. /*
  77.  *  BRGCON2: | SEG2PHTS | SAM | SEG1PH2 | SEG1PH1 | SEG1PH0 | PRSEG2 | PRSEG1 | PRSEG0
  78.  *      SEGnPH -  Phase Segment Time Select bits
  79.  */
  80.     BRGCON2 = BIN(00010000); // SEG1PH = 2(3штуки), PRSEG = 0(1штука)
  81. /*
  82.  *  BRGCON3: | N/A | WAKFIL | N/A | N/A | N/A | SEG2PH2 | SEG2PH1 | SEG2PH0 |
  83.  *      WAKFIL - использовать ли фильтр для wakeup
  84.  */
  85.     BRGCON3 = 0x02; // SEG2PH = 2(3 штуки)
  86. /*
  87.  *  RXB0CON - контроль приемного буфера
  88.  *  RXB0CON: | RXFUL | RXM1 | RXM0 | N/A | RXRTRRO | RXB0DBEN | JTOFF | FILHIT0 |
  89.  *          RXFUL == 1 - получено сообщение (обнулять вручную после считывания)
  90.  *          RXM = 01 - обычные сообщения со стандартным ID'ом
  91.  *          RXRTRRO - (readonly) - запрос на трансфер
  92.  *          RXB0DBEN == 1 - двойная буферизация (после записи в 0й буфер идет запись в 1й)
  93.  *          JTOFF - readonly-копия RXB0DBEN
  94.  *          FILHIT0 - номер фильтра (RXF0 или RXF1)
  95.  */
  96.     RXB0CON = BIN(00100000);
  97. /*
  98.  *  CIOCON: | N/A | N/A | ENDRHI | CANCAP | N/A.. |
  99.  *      ENDRHI: Enable Drive High bit
  100.  *          1 = CANTX pin will drive VDD when recessive
  101.  *          0 = CANTX pin will tri-state when recessive
  102.  *      CANCAP: CAN Message Receive Capture Enable bit
  103.  */
  104.     //CIOCON = 0x20;
  105. //  RXFnSIDH[L] - фильтр по идентификатору
  106.     RXF0SIDH = 0;
  107.     RXF0SIDL = 0x20; // ид = 1
  108. //  RXMnSIDH[L] - маска фильтра по идентификатору
  109.     RXM0SIDH = 0xff; // принимаем только адресованные нам сообщения
  110.     RXM0SIDL = 0xe0;
  111. /*
  112.  *  TXBnSIDH[L] - два байта стандартного идентификатора контроллера
  113.  *  EXIDE должен быть = 0, чтобы идентификатор был 2х, а не 4х-байтным
  114.  *  TXBnSIDH: | SID10 .|. SID3 |
  115.  *  TXBnSIDL: | SID2 | SID1 | SID0 | N/A | EXIDE | N/A | EID17 | EID16 |   
  116.  */
  117.     TXB0SIDH = 0;
  118.     TXB0SIDL = 0x20;
  119. /*
  120.  *  TXBnDLC - длина передачи
  121.  *  TXBnDLC: | N/A | TXRTR | N/A | N/A | DLC3 .. DLC0 |
  122.  *  Для восьмибайтной посылки DLC = 1000, TXRTR = 0?
  123.  */
  124.     //TXB0DLC = 0x01; // однобайтные посылки
  125.     CANSetOperationMode(CAN_OP_MODE_NORMAL);
  126. /*
  127.  ************************ конец настройки CAN-ИНТЕРФЕЙСА ************
  128.  */
  129. }
  130.  
  131. void CANsend(unsigned char byte){
  132. /*
  133.  *  TXBnCON - контрольные регистры n-го буфера передачи
  134.  *  TXBnCON: | N/A | TXABT | TXLARB | TXERR | TXREQ | N/A | TXPRI1 | TXPRI0 |
  135.  *      если биты 6-4 == 1 - ошибка во время передачи
  136.  *      TXREQ = 1 - запрос на отсылку сообщения (если он == 1 и его обнулить, сообщение прервется)
  137.  *      TXPRI - приоритет (чем больше, тем выше)
  138.  */
  139.     while(TXB0CONbits.TXREQ); // если была заявка на отправку - ждем
  140.     CANCON &= BIN(11110001);
  141.     CANCON |= BIN(00001000); // данные - из буфера 0
  142.     TXB0CON |= 1;
  143.     // TXBnDm - отсылаемые данные
  144.     TXB0D0 = byte; // всего 8 буферов TXBn0 .. TXBn7
  145.     TXB0DLC = 1; // один байт
  146.     TXB0CON |= 8; // TXREQ0 = 1;
  147.     CANCON &= BIN(11110001);
  148.     // TXERRCNT - счетчик ошибок передачи
  149.     // после успешной передачи TXREQ0 сброшен, TXBUFE=1 ; иначе - устанавливается код ошибки TXERR
  150.     // если передача успешна и TXIE=1, генерируется прерывание
  151. }
  152.  
  153. void CANreceive(){
  154.     unsigned char byte;
  155. /*  RXB1CON отличается битами 0..3:
  156.  *  RXB1CON: ...| FILHIT2..0 |
  157.  *      FILHIT - номер принимающего фильтра (от 0 до 5)
  158.  */
  159.  
  160. /*  RXBnSIDH[L] - идентификатор принятого сообщения
  161.  *  SIDH аналогичен TXBnSIDH,
  162.  *  SIDL.4 - SRR, при EXID==0 является копией  RXRTRRO (RXnBCON.3)
  163.  */
  164.     if(RXB0CONbits.RXFUL){
  165.         // RXBuffer0 is full.
  166.         CANCON &= BIN(11110001);
  167.         // Clear the received flag.
  168.         PIR3bits.RX0IF = 0;
  169.         // forget any previous overflow
  170.         COMSTATbits.RXB0OVFL = 0;
  171.         /*if(RXB0CONbits.RX0DBEN){
  172.             *MsgFlags |= RXB0CON & CAN_RX_FILTER_BITS;
  173.             *MsgFlags &= 0x01;
  174.         }*/
  175.     }else if(RXB1CONbits.RXFUL){
  176.         // RXBuffer1 is full
  177.         CANCON &= BIN(11110001);
  178.         CANCON |= BIN(00001010);
  179.         // Clear the received flag.
  180.         PIR3bits.RX1IF = 0;
  181.         // and forget any previous overflow
  182.         COMSTATbits.RXB1OVFL = 0;
  183.         //*MsgFlags |= RXB1CON & CAN_RX_FILTER_BITS;
  184.         //if ( *MsgFlags < 0x02 )
  185.         //*MsgFlags |= CAN_RX_DBL_BUFFERED;
  186.     }
  187. //  RXBnDLC - длина сообщения, аналогично TXBnDLC
  188.     PORTA = RXB0DLC & BIN(00001111);
  189. //  RXERRCNT - счетчик ошибок
  190. //  RXBnDm - принятые данные
  191.     // всего 8 буферов RXBn0 .. RXBn7
  192.     byte = RXB0D0;
  193.     // Restore default RXB0 mapping.
  194.     CANCON &= BIN(11110001);
  195.     // Clear any previous invalid message bit flag
  196.     PIR3bits.IVRF = 0;
  197.     RXB0CONbits.RXFUL = 0;
  198.     RXB1CONbits.RXFUL = 0;
  199.     CANsend(byte);
  200. }
  201.  
  202. void timer1int(){
  203.     T1CON = 0; // выключить таймер
  204.     PORTA = LED;
  205.     LED <<= 1;
  206.     if(LED > 0x20) LED = 1;
  207.     CANsend(LED);
  208.     PIR1bits.TMR1IF = 0; // сбросить флаг прерывания
  209.     PIE1bits.TMR1IE = 1;
  210.     TMR1H = 0x30; TMR1L = 0xD4;  // установить счетчики, 0.1с
  211. // T1CON: | - | - | T1CPS1 | T1CPS0 | T1OSCEN | T1SYNC | TMR1CS | TMR1ON |
  212.     T1CON = 0x31; // (00110001) - включить таймер 1, предделитель на 1/8 (125 кГц)
  213. }
  214.  
  215. void  on_interrupt() __interrupt 1{ // обработка прерываний
  216.     // CANSTAT: OPMODEx3  N/A  ICODEx3  N/A
  217.     // ICODE - код прерывания
  218.     unsigned char icode = CANSTAT & 0x0E; // выделяем ICODE
  219.     if(PIR1bits.TMR1IF == 1) // поступило прерывание от таймера
  220.         timer1int(); // обработать прерывание
  221.     if(!PIR3) return; // не было CAN-прерывания
  222.     T1CON = 0; // выключить таймер
  223.     icode >>= 1; // сдвигаем
  224.     switch(icode){
  225.         case 7: break; // Wake up on
  226.         case 5:        // RXB1
  227.         case 6: CANreceive(); break; // RXB0
  228.         case 4: break; // TXB0
  229.         case 3: break; // TXB1
  230.         case 2: break; // TXB2
  231.         case 1: break; // ERR
  232.         case 0: break; // no interrupt
  233.     }
  234.     // PIR3 - флаги прерываний шины
  235.     // PIR3: | IRXIF | WAKIF | ERRIF | TXB2IF | TXB1IF | TXB0IF | RXB1IF | RXB0IF |
  236.     PIR3 = 0;
  237.     T1CON = 0x31;
  238.     // COMSTAT - ошибки шины
  239.     // COMSTAT: | RXB0OVFL | RXB1OVFL | TXBO | TXBP | RXBP | TXWARN | RXWARN | EWARN |
  240. }
  241.  
  242. void main(){ // основной цикл
  243.     init();
  244.     while(1){};//CLRWDT};
  245. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement