Yoshi Mimura
/
CAN_MONITOR
A very simple vehicle (Toyota Prius ZVW30) CAN message monitor program with CAN_id filtering.
main.cpp@0:fe1f886dff76, 2012-03-21 (annotated)
- Committer:
- ym1784
- Date:
- Wed Mar 21 01:53:16 2012 +0000
- Revision:
- 0:fe1f886dff76
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
ym1784 | 0:fe1f886dff76 | 1 | // CAN_MONITOR with filtering 2012/03/21 ym1784 |
ym1784 | 0:fe1f886dff76 | 2 | |
ym1784 | 0:fe1f886dff76 | 3 | #include "mbed.h" |
ym1784 | 0:fe1f886dff76 | 4 | #include "CAN.h" |
ym1784 | 0:fe1f886dff76 | 5 | |
ym1784 | 0:fe1f886dff76 | 6 | Serial pc(USBTX, USBRX); // tx, rx |
ym1784 | 0:fe1f886dff76 | 7 | DigitalOut led2(LED2); |
ym1784 | 0:fe1f886dff76 | 8 | |
ym1784 | 0:fe1f886dff76 | 9 | // CAN2 on mbed pins 29(CAN_TXD) and 30(CAN_RXD) using MCP2551. |
ym1784 | 0:fe1f886dff76 | 10 | CAN can2(p30, p29); |
ym1784 | 0:fe1f886dff76 | 11 | |
ym1784 | 0:fe1f886dff76 | 12 | /*-------------------------------------------- |
ym1784 | 0:fe1f886dff76 | 13 | setup acceptance filter for CAN controller 2 |
ym1784 | 0:fe1f886dff76 | 14 | original http://www.dragonwake.com/download/LPC1768/Example/CAN/CAN.c |
ym1784 | 0:fe1f886dff76 | 15 | simplified for CAN2 interface and std id (11 bit) only |
ym1784 | 0:fe1f886dff76 | 16 | *--------------------------------------------*/ |
ym1784 | 0:fe1f886dff76 | 17 | void CAN2_wrFilter (uint32_t id) { |
ym1784 | 0:fe1f886dff76 | 18 | static int CAN_std_cnt = 0; |
ym1784 | 0:fe1f886dff76 | 19 | uint32_t buf0, buf1; |
ym1784 | 0:fe1f886dff76 | 20 | int cnt1, cnt2, bound1; |
ym1784 | 0:fe1f886dff76 | 21 | |
ym1784 | 0:fe1f886dff76 | 22 | /* Acceptance Filter Memory full */ |
ym1784 | 0:fe1f886dff76 | 23 | if (((CAN_std_cnt + 1) >> 1) >= 512) |
ym1784 | 0:fe1f886dff76 | 24 | return; /* error: objects full */ |
ym1784 | 0:fe1f886dff76 | 25 | |
ym1784 | 0:fe1f886dff76 | 26 | /* Setup Acceptance Filter Configuration |
ym1784 | 0:fe1f886dff76 | 27 | Acceptance Filter Mode Register = Off */ |
ym1784 | 0:fe1f886dff76 | 28 | LPC_CANAF->AFMR = 0x00000001; |
ym1784 | 0:fe1f886dff76 | 29 | |
ym1784 | 0:fe1f886dff76 | 30 | id |= 1 << 13; /* Add controller number(2) */ |
ym1784 | 0:fe1f886dff76 | 31 | id &= 0x0000F7FF; /* Mask out 16-bits of ID */ |
ym1784 | 0:fe1f886dff76 | 32 | |
ym1784 | 0:fe1f886dff76 | 33 | if (CAN_std_cnt == 0) { /* For entering first ID */ |
ym1784 | 0:fe1f886dff76 | 34 | LPC_CANAF_RAM->mask[0] = 0x0000FFFF | (id << 16); |
ym1784 | 0:fe1f886dff76 | 35 | } else if (CAN_std_cnt == 1) { /* For entering second ID */ |
ym1784 | 0:fe1f886dff76 | 36 | if ((LPC_CANAF_RAM->mask[0] >> 16) > id) |
ym1784 | 0:fe1f886dff76 | 37 | LPC_CANAF_RAM->mask[0] = (LPC_CANAF_RAM->mask[0] >> 16) | (id << 16); |
ym1784 | 0:fe1f886dff76 | 38 | else |
ym1784 | 0:fe1f886dff76 | 39 | LPC_CANAF_RAM->mask[0] = (LPC_CANAF_RAM->mask[0] & 0xFFFF0000) | id; |
ym1784 | 0:fe1f886dff76 | 40 | } else { |
ym1784 | 0:fe1f886dff76 | 41 | /* Find where to insert new ID */ |
ym1784 | 0:fe1f886dff76 | 42 | cnt1 = 0; |
ym1784 | 0:fe1f886dff76 | 43 | cnt2 = CAN_std_cnt; |
ym1784 | 0:fe1f886dff76 | 44 | bound1 = (CAN_std_cnt - 1) >> 1; |
ym1784 | 0:fe1f886dff76 | 45 | while (cnt1 <= bound1) { /* Loop through standard existing IDs */ |
ym1784 | 0:fe1f886dff76 | 46 | if ((LPC_CANAF_RAM->mask[cnt1] >> 16) > id) { |
ym1784 | 0:fe1f886dff76 | 47 | cnt2 = cnt1 * 2; |
ym1784 | 0:fe1f886dff76 | 48 | break; |
ym1784 | 0:fe1f886dff76 | 49 | } |
ym1784 | 0:fe1f886dff76 | 50 | if ((LPC_CANAF_RAM->mask[cnt1] & 0x0000FFFF) > id) { |
ym1784 | 0:fe1f886dff76 | 51 | cnt2 = cnt1 * 2 + 1; |
ym1784 | 0:fe1f886dff76 | 52 | break; |
ym1784 | 0:fe1f886dff76 | 53 | } |
ym1784 | 0:fe1f886dff76 | 54 | cnt1++; /* cnt1 = U32 where to insert new ID */ |
ym1784 | 0:fe1f886dff76 | 55 | } /* cnt2 = U16 where to insert new ID */ |
ym1784 | 0:fe1f886dff76 | 56 | |
ym1784 | 0:fe1f886dff76 | 57 | if (cnt1 > bound1) { /* Adding ID as last entry */ |
ym1784 | 0:fe1f886dff76 | 58 | if ((CAN_std_cnt & 0x0001) == 0) /* Even number of IDs exists */ |
ym1784 | 0:fe1f886dff76 | 59 | LPC_CANAF_RAM->mask[cnt1] = 0x0000FFFF | (id << 16); |
ym1784 | 0:fe1f886dff76 | 60 | else /* Odd number of IDs exists */ |
ym1784 | 0:fe1f886dff76 | 61 | LPC_CANAF_RAM->mask[cnt1] = (LPC_CANAF_RAM->mask[cnt1] & 0xFFFF0000) | id; |
ym1784 | 0:fe1f886dff76 | 62 | } else { |
ym1784 | 0:fe1f886dff76 | 63 | buf0 = LPC_CANAF_RAM->mask[cnt1]; /* Remember current entry */ |
ym1784 | 0:fe1f886dff76 | 64 | if ((cnt2 & 0x0001) == 0) /* Insert new mask to even address */ |
ym1784 | 0:fe1f886dff76 | 65 | buf1 = (id << 16) | (buf0 >> 16); |
ym1784 | 0:fe1f886dff76 | 66 | else /* Insert new mask to odd address */ |
ym1784 | 0:fe1f886dff76 | 67 | buf1 = (buf0 & 0xFFFF0000) | id; |
ym1784 | 0:fe1f886dff76 | 68 | |
ym1784 | 0:fe1f886dff76 | 69 | LPC_CANAF_RAM->mask[cnt1] = buf1; /* Insert mask */ |
ym1784 | 0:fe1f886dff76 | 70 | |
ym1784 | 0:fe1f886dff76 | 71 | bound1 = CAN_std_cnt >> 1; |
ym1784 | 0:fe1f886dff76 | 72 | /* Move all remaining standard mask entries one place up */ |
ym1784 | 0:fe1f886dff76 | 73 | while (cnt1 < bound1) { |
ym1784 | 0:fe1f886dff76 | 74 | cnt1++; |
ym1784 | 0:fe1f886dff76 | 75 | buf1 = LPC_CANAF_RAM->mask[cnt1]; |
ym1784 | 0:fe1f886dff76 | 76 | LPC_CANAF_RAM->mask[cnt1] = (buf1 >> 16) | (buf0 << 16); |
ym1784 | 0:fe1f886dff76 | 77 | buf0 = buf1; |
ym1784 | 0:fe1f886dff76 | 78 | } |
ym1784 | 0:fe1f886dff76 | 79 | |
ym1784 | 0:fe1f886dff76 | 80 | if ((CAN_std_cnt & 0x0001) == 0) /* Even number of IDs exists */ |
ym1784 | 0:fe1f886dff76 | 81 | LPC_CANAF_RAM->mask[cnt1] = (LPC_CANAF_RAM->mask[cnt1] & 0xFFFF0000) | (0x0000FFFF); |
ym1784 | 0:fe1f886dff76 | 82 | } |
ym1784 | 0:fe1f886dff76 | 83 | } |
ym1784 | 0:fe1f886dff76 | 84 | CAN_std_cnt++; |
ym1784 | 0:fe1f886dff76 | 85 | |
ym1784 | 0:fe1f886dff76 | 86 | /* Calculate std ID start address (buf0) and ext ID start address <- none (buf1) */ |
ym1784 | 0:fe1f886dff76 | 87 | buf0 = ((CAN_std_cnt + 1) >> 1) << 2; |
ym1784 | 0:fe1f886dff76 | 88 | buf1 = buf0; |
ym1784 | 0:fe1f886dff76 | 89 | |
ym1784 | 0:fe1f886dff76 | 90 | /* Setup acceptance filter pointers */ |
ym1784 | 0:fe1f886dff76 | 91 | LPC_CANAF->SFF_sa = 0; |
ym1784 | 0:fe1f886dff76 | 92 | LPC_CANAF->SFF_GRP_sa = buf0; |
ym1784 | 0:fe1f886dff76 | 93 | LPC_CANAF->EFF_sa = buf0; |
ym1784 | 0:fe1f886dff76 | 94 | LPC_CANAF->EFF_GRP_sa = buf1; |
ym1784 | 0:fe1f886dff76 | 95 | LPC_CANAF->ENDofTable = buf1; |
ym1784 | 0:fe1f886dff76 | 96 | |
ym1784 | 0:fe1f886dff76 | 97 | LPC_CANAF->AFMR = 0x00000000; /* Use acceptance filter */ |
ym1784 | 0:fe1f886dff76 | 98 | } // CAN2_wrFilter |
ym1784 | 0:fe1f886dff76 | 99 | |
ym1784 | 0:fe1f886dff76 | 100 | int main() { |
ym1784 | 0:fe1f886dff76 | 101 | pc.baud(921600); |
ym1784 | 0:fe1f886dff76 | 102 | pc.printf("CAN_MONITOR 921600 bps\r\n"); |
ym1784 | 0:fe1f886dff76 | 103 | |
ym1784 | 0:fe1f886dff76 | 104 | // 500kbit/s |
ym1784 | 0:fe1f886dff76 | 105 | can2.frequency(500000); |
ym1784 | 0:fe1f886dff76 | 106 | CANMessage can_MsgRx; |
ym1784 | 0:fe1f886dff76 | 107 | |
ym1784 | 0:fe1f886dff76 | 108 | CAN2_wrFilter(0x0B4); |
ym1784 | 0:fe1f886dff76 | 109 | CAN2_wrFilter(0x1C4); |
ym1784 | 0:fe1f886dff76 | 110 | CAN2_wrFilter(0x245); |
ym1784 | 0:fe1f886dff76 | 111 | CAN2_wrFilter(0x3D3); |
ym1784 | 0:fe1f886dff76 | 112 | CAN2_wrFilter(0x498); |
ym1784 | 0:fe1f886dff76 | 113 | CAN2_wrFilter(0x4A6); |
ym1784 | 0:fe1f886dff76 | 114 | |
ym1784 | 0:fe1f886dff76 | 115 | while (1) { |
ym1784 | 0:fe1f886dff76 | 116 | // send received messages to the pc via serial line |
ym1784 | 0:fe1f886dff76 | 117 | if (can2.read(can_MsgRx)) { |
ym1784 | 0:fe1f886dff76 | 118 | pc.printf("t%03X%d", can_MsgRx.id, can_MsgRx.len); |
ym1784 | 0:fe1f886dff76 | 119 | for (char i=0; i<can_MsgRx.len; i++) { |
ym1784 | 0:fe1f886dff76 | 120 | pc.printf("%02X", can_MsgRx.data[i]); |
ym1784 | 0:fe1f886dff76 | 121 | } // for |
ym1784 | 0:fe1f886dff76 | 122 | pc.printf("\r\n"); |
ym1784 | 0:fe1f886dff76 | 123 | // toggle led2 |
ym1784 | 0:fe1f886dff76 | 124 | led2 = !led2; |
ym1784 | 0:fe1f886dff76 | 125 | } // if |
ym1784 | 0:fe1f886dff76 | 126 | } // while |
ym1784 | 0:fe1f886dff76 | 127 | } // main |