NUMAKER CAN sample

Committer:
ccli8
Date:
Wed Apr 17 17:47:56 2024 +0800
Revision:
11:36d172d475fa
Parent:
10:33d27c970411
Support loopback mode

To enable loopback mode, both TX and RX are required to enable.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
cyliang 0:df0aeb0c8f2c 1 #include "cmsis_os.h"
cyliang 0:df0aeb0c8f2c 2 #include "mbed.h"
cyliang 0:df0aeb0c8f2c 3 #include "CAN.h"
cyliang 0:df0aeb0c8f2c 4
cyliang 0:df0aeb0c8f2c 5
cyliang 0:df0aeb0c8f2c 6 DigitalOut led1(LED1, 1); //LED R OFF
cyliang 0:df0aeb0c8f2c 7 DigitalOut led2(LED2, 1); //LED G OFF
cyliang 0:df0aeb0c8f2c 8 DigitalOut led3(LED3, 1); //LED B OFF
cyliang 0:df0aeb0c8f2c 9
cyliang 0:df0aeb0c8f2c 10 #define CAN_TX_MODE_TEST 0
cyliang 0:df0aeb0c8f2c 11 #define CAN_RX_MODE_TEST 1
ccli8 11:36d172d475fa 12 #define CAN_LOOPBACK_MODE_TEST 0
ccli8 11:36d172d475fa 13 #if CAN_LOOPBACK_MODE_TEST && (!CAN_TX_MODE_TEST || !CAN_RX_MODE_TEST)
ccli8 11:36d172d475fa 14 #error "Either TX or RX not enabled for loopback mode"
ccli8 11:36d172d475fa 15 #endif
ccli8 11:36d172d475fa 16
ccli8 6:b9714e564dee 17 /* WARNING: Don't enable interrupt mode on receive side. It is not supported on Nuvoton targets. */
ccli8 6:b9714e564dee 18 #define CAN_RX_IRQ_EN 0
cyliang 0:df0aeb0c8f2c 19 #define LED_ALL_OFF led1=led2=led3=1
cyliang 0:df0aeb0c8f2c 20
cyliang 0:df0aeb0c8f2c 21 #define MSG_NUM_INDEX 5 // 0 ~ 31
cyliang 0:df0aeb0c8f2c 22 #define CAN_DEV_ID 0x1AC
cyliang 0:df0aeb0c8f2c 23
cyliang 0:df0aeb0c8f2c 24 #if defined(TARGET_NUMAKER_PFM_NUC472)
ccli8 5:499978915868 25 CAN canObj(PA_0, PA_1); // Internal in the board
cyliang 0:df0aeb0c8f2c 26 #elif defined(TARGET_NUMAKER_PFM_M453)
ccli8 5:499978915868 27 CAN canObj(PA_13, PA_12); // Internal in the board
ccli8 5:499978915868 28 #elif defined(TARGET_NUMAKER_PFM_M487)
cyliang 7:956b6cf0b070 29 CAN canObj(D9, D8); // (rd, td) Change to match external attachment
ccli8 6:b9714e564dee 30 #elif defined(TARGET_NUMAKER_IOT_M487)
ccli8 6:b9714e564dee 31 CAN canObj(A0, A1); // Change to match external attachment
cyliang 7:956b6cf0b070 32 #elif defined(TARGET_NUMAKER_IOT_M467)
cyliang 8:7310cfa7f71c 33 CAN canObj(A0, A1); // CAN1(rd, td) Change to match external attachment
cyliang 8:7310cfa7f71c 34 //CAN canObj(D9, D8); // CAN0
cyliang 0:df0aeb0c8f2c 35 #endif
cyliang 0:df0aeb0c8f2c 36
cyliang 0:df0aeb0c8f2c 37 CANMessage canMsg;
cyliang 0:df0aeb0c8f2c 38
cyliang 0:df0aeb0c8f2c 39 osThreadId mainThreadID;
cyliang 0:df0aeb0c8f2c 40
cyliang 0:df0aeb0c8f2c 41 static int read_MsgObj()
cyliang 0:df0aeb0c8f2c 42 {
cyliang 0:df0aeb0c8f2c 43 int i=0;
cyliang 0:df0aeb0c8f2c 44
cyliang 0:df0aeb0c8f2c 45 i = canObj.read(canMsg, MSG_NUM_INDEX);
cyliang 0:df0aeb0c8f2c 46
cyliang 0:df0aeb0c8f2c 47 switch (canMsg.data[0])
cyliang 0:df0aeb0c8f2c 48 {
cyliang 0:df0aeb0c8f2c 49 case 0:
cyliang 0:df0aeb0c8f2c 50 LED_ALL_OFF;
cyliang 0:df0aeb0c8f2c 51 led1=0;
cyliang 0:df0aeb0c8f2c 52 break;
cyliang 0:df0aeb0c8f2c 53
cyliang 0:df0aeb0c8f2c 54 case 1:
cyliang 0:df0aeb0c8f2c 55 LED_ALL_OFF;
cyliang 0:df0aeb0c8f2c 56 led2=0;
cyliang 0:df0aeb0c8f2c 57 break;
cyliang 0:df0aeb0c8f2c 58
cyliang 0:df0aeb0c8f2c 59 case 2:
cyliang 0:df0aeb0c8f2c 60 LED_ALL_OFF;
cyliang 0:df0aeb0c8f2c 61 led3=0;
cyliang 0:df0aeb0c8f2c 62 break;
cyliang 0:df0aeb0c8f2c 63
cyliang 0:df0aeb0c8f2c 64 default:
cyliang 0:df0aeb0c8f2c 65 LED_ALL_OFF;
cyliang 0:df0aeb0c8f2c 66 break;
cyliang 0:df0aeb0c8f2c 67 }
cyliang 0:df0aeb0c8f2c 68
cyliang 0:df0aeb0c8f2c 69 return i;
cyliang 0:df0aeb0c8f2c 70 }
cyliang 0:df0aeb0c8f2c 71
cyliang 0:df0aeb0c8f2c 72 void irq_callback(void)
cyliang 0:df0aeb0c8f2c 73 {
ccli8 6:b9714e564dee 74 /* Wake up receive task */
ccli8 6:b9714e564dee 75 osSignalSet(mainThreadID, 0x06);
cyliang 0:df0aeb0c8f2c 76 }
cyliang 0:df0aeb0c8f2c 77
cyliang 0:df0aeb0c8f2c 78 int main() {
ccli8 6:b9714e564dee 79 #if CAN_TX_MODE_TEST
ccli8 6:b9714e564dee 80 printf("CAN sender sample\r\n");
ccli8 6:b9714e564dee 81 #endif
ccli8 6:b9714e564dee 82
ccli8 6:b9714e564dee 83 #if CAN_RX_MODE_TEST
ccli8 6:b9714e564dee 84 printf("CAN receiver sample\r\n");
ccli8 6:b9714e564dee 85 #endif
ccli8 6:b9714e564dee 86
cyliang 0:df0aeb0c8f2c 87 int i=0;
cyliang 0:df0aeb0c8f2c 88 char data[8]={0};
cyliang 0:df0aeb0c8f2c 89
cyliang 0:df0aeb0c8f2c 90 mainThreadID = osThreadGetId();
cyliang 0:df0aeb0c8f2c 91
cyliang 0:df0aeb0c8f2c 92 /* Set Frequency 1khz~1000khz */
cyliang 0:df0aeb0c8f2c 93 canObj.frequency(1000000);
cyliang 0:df0aeb0c8f2c 94
cyliang 0:df0aeb0c8f2c 95 #if CAN_RX_MODE_TEST
cyliang 0:df0aeb0c8f2c 96
cyliang 0:df0aeb0c8f2c 97 #if CAN_RX_IRQ_EN
cyliang 0:df0aeb0c8f2c 98 /* Attach irq function */
cyliang 0:df0aeb0c8f2c 99 canObj.attach(irq_callback, CAN::RxIrq);
cyliang 0:df0aeb0c8f2c 100 #endif
ccli8 10:33d27c970411 101
ccli8 10:33d27c970411 102 /* According to link below, filter #0 will accept any message, and
ccli8 10:33d27c970411 103 * no other filters can accept messages without re-configuring filter #0.
ccli8 10:33d27c970411 104 * https://os.mbed.com/questions/85183/How-to-use-CAN-filter-function
ccli8 10:33d27c970411 105 *
ccli8 10:33d27c970411 106 * Re-configure filter #0 to accept message ID 0 only.
ccli8 10:33d27c970411 107 */
ccli8 10:33d27c970411 108 canObj.filter(0, 0xFFFFFFFF);
ccli8 10:33d27c970411 109
cyliang 0:df0aeb0c8f2c 110 canObj.filter(CAN_DEV_ID, 0, CANStandard, MSG_NUM_INDEX);
cyliang 0:df0aeb0c8f2c 111
cyliang 0:df0aeb0c8f2c 112 #endif
ccli8 11:36d172d475fa 113
ccli8 11:36d172d475fa 114 #if CAN_LOOPBACK_MODE_TEST
ccli8 11:36d172d475fa 115 if (!canObj.mode(CAN::SilentTest)) {
ccli8 11:36d172d475fa 116 printf("CAN: Configure to SilentTest mode failed\n\n");
ccli8 11:36d172d475fa 117 return EXIT_FAILURE;
ccli8 11:36d172d475fa 118 }
ccli8 11:36d172d475fa 119 #endif
ccli8 11:36d172d475fa 120
cyliang 0:df0aeb0c8f2c 121 while (true)
cyliang 0:df0aeb0c8f2c 122 {
cyliang 0:df0aeb0c8f2c 123
cyliang 0:df0aeb0c8f2c 124
cyliang 0:df0aeb0c8f2c 125 #if CAN_TX_MODE_TEST
cyliang 0:df0aeb0c8f2c 126
cyliang 0:df0aeb0c8f2c 127 canObj.write(CANMessage(CAN_DEV_ID, data));
cyliang 0:df0aeb0c8f2c 128
cyliang 0:df0aeb0c8f2c 129 if(data[0] == 2)
cyliang 0:df0aeb0c8f2c 130 data[0]=0;
cyliang 0:df0aeb0c8f2c 131 else
cyliang 0:df0aeb0c8f2c 132 data[0]++;
ccli8 9:bb7099cd4943 133
cyliang 0:df0aeb0c8f2c 134 memset(&data[1], data[0], 7);
ccli8 9:bb7099cd4943 135 ThisThread::sleep_for(1000ms);
ccli8 9:bb7099cd4943 136
cyliang 0:df0aeb0c8f2c 137 #endif
cyliang 0:df0aeb0c8f2c 138
cyliang 0:df0aeb0c8f2c 139 #if CAN_RX_MODE_TEST
ccli8 6:b9714e564dee 140
ccli8 6:b9714e564dee 141 #if (CAN_RX_IRQ_EN)
cyliang 0:df0aeb0c8f2c 142 /* Wait for receive task to wakeup */
ccli8 6:b9714e564dee 143 osSignalWait(0x06, osWaitForever);
cyliang 0:df0aeb0c8f2c 144 #endif
ccli8 6:b9714e564dee 145 if (!read_MsgObj()) {
ccli8 6:b9714e564dee 146 continue;
ccli8 6:b9714e564dee 147 }
ccli8 6:b9714e564dee 148
cyliang 0:df0aeb0c8f2c 149 printf("Read ID=%8X, Type=%s, DLC=%d,Data=",canMsg.id,canMsg.format?"EXT":"STD",canMsg.len);
cyliang 0:df0aeb0c8f2c 150 for(i=0; i<canMsg.len; i++)
cyliang 0:df0aeb0c8f2c 151 printf("%02X,",canMsg.data[i]);
cyliang 0:df0aeb0c8f2c 152 printf("\r\n");
cyliang 0:df0aeb0c8f2c 153 #endif
cyliang 0:df0aeb0c8f2c 154 }
cyliang 0:df0aeb0c8f2c 155
cyliang 0:df0aeb0c8f2c 156 }