└── CanLowlevel.ino /CanLowlevel.ino: -------------------------------------------------------------------------------- 1 | 2 | enum BITRATE{CAN_50KBPS, CAN_100KBPS, CAN_125KBPS, CAN_250KBPS, CAN_500KBPS, CAN_1000KBPS}; 3 | 4 | typedef struct 5 | { 6 | uint16_t id; 7 | uint8_t data[8]; 8 | uint8_t len; 9 | } CAN_msg_t; 10 | 11 | typedef const struct 12 | { 13 | uint8_t TS2; 14 | uint8_t TS1; 15 | uint8_t BRP; 16 | } CAN_bit_timing_config_t; 17 | CAN_bit_timing_config_t can_configs[6] = {{2, 13, 45}, {2, 15, 20}, {2, 13, 18}, {2, 13, 9}, {2, 15, 4}, {2, 15, 2}}; 18 | 19 | 20 | extern CAN_bit_timing_config_t can_configs[6]; 21 | 22 | /** 23 | * Initializes the CAN controller with specified bit rate. 24 | * 25 | * @params: bitrate - Specified bitrate. If this value is not one of the defined constants, bit rate will be defaulted to 125KBS 26 | * 27 | */ 28 | void CANInit(enum BITRATE bitrate) 29 | { 30 | RCC->APB1ENR |= 0x2000000UL; // Enable CAN clock 31 | RCC->APB2ENR |= 0x1UL; // Enable AFIO clock 32 | AFIO->MAPR &= 0xFFFF9FFF; // reset CAN remap 33 | AFIO->MAPR |= 0x00004000; // et CAN remap, use PB8, PB9 34 | 35 | RCC->APB2ENR |= 0x8UL; // Enable GPIOB clock 36 | GPIOB->CRH &= ~(0xFFUL); 37 | GPIOB->CRH |= 0xB8UL; // Configure PB8 and PB9 38 | GPIOB->ODR |= 0x1UL << 8; 39 | 40 | CAN1->MCR = 0x51UL; // Set CAN to initialization mode 41 | 42 | // Set bit rates 43 | CAN1->BTR &= ~(((0x03) << 24) | ((0x07) << 20) | ((0x0F) << 16) | (0x1FF)); 44 | CAN1->BTR |= (((can_configs[bitrate].TS2-1) & 0x07) << 20) | (((can_configs[bitrate].TS1-1) & 0x0F) << 16) | ((can_configs[bitrate].BRP-1) & 0x1FF); 45 | 46 | // Configure Filters to default values 47 | CAN1->FM1R |= 0x1C << 8; // Assign all filters to CAN1 48 | CAN1->FMR |= 0x1UL; // Set to filter initialization mode 49 | CAN1->FA1R &= ~(0x1UL); // Deactivate filter 0 50 | CAN1->FS1R |= 0x1UL; // Set first filter to single 32 bit configuration 51 | 52 | CAN1->sFilterRegister[0].FR1 = 0x0UL; // Set filter registers to 0 53 | CAN1->sFilterRegister[0].FR2 = 0x0UL; // Set filter registers to 0 54 | CAN1->FM1R &= ~(0x1UL); // Set filter to mask mode 55 | 56 | CAN1->FFA1R &= ~(0x1UL); // Apply filter to FIFO 0 57 | CAN1->FA1R |= 0x1UL; // Activate filter 0 58 | 59 | CAN1->FMR &= ~(0x1UL); // Deactivate initialization mode 60 | CAN1->MCR &= ~(0x1UL); // Set CAN to normal mode 61 | 62 | while (CAN1->MSR & 0x1UL); 63 | 64 | } 65 | 66 | void CANSetFilter(uint16_t id) 67 | { 68 | static uint32_t filterID = 0; 69 | 70 | if (filterID == 112) 71 | { 72 | return; 73 | } 74 | 75 | CAN1->FMR |= 0x1UL; // Set to filter initialization mode 76 | 77 | switch(filterID%4) 78 | { 79 | case 0: 80 | // if we need another filter bank, initialize it 81 | CAN1->FA1R |= 0x1UL <<(filterID/4); 82 | CAN1->FM1R |= 0x1UL << (filterID/4); 83 | CAN1->FS1R &= ~(0x1UL << (filterID/4)); 84 | 85 | CAN1->sFilterRegister[filterID/4].FR1 = (id << 5) | (id << 21); 86 | CAN1->sFilterRegister[filterID/4].FR2 = (id << 5) | (id << 21); 87 | break; 88 | case 1: 89 | CAN1->sFilterRegister[filterID/4].FR1 &= 0x0000FFFF; 90 | CAN1->sFilterRegister[filterID/4].FR1 |= id << 21; 91 | break; 92 | case 2: 93 | CAN1->sFilterRegister[filterID/4].FR2 = (id << 5) | (id << 21); 94 | break; 95 | case 3: 96 | CAN1->sFilterRegister[filterID/4].FR2 &= 0x0000FFFF; 97 | CAN1->sFilterRegister[filterID/4].FR2 |= id << 21; 98 | break; 99 | } 100 | filterID++; 101 | CAN1->FMR &= ~(0x1UL); // Deactivate initialization mode 102 | } 103 | 104 | void CANSetFilters(uint16_t* ids, uint8_t num) 105 | { 106 | for (int i = 0; i < num; i++) 107 | { 108 | CANSetFilter(ids[i]); 109 | } 110 | } 111 | 112 | /** 113 | * Decodes CAN messages from the data registers and populates a 114 | * CAN message struct with the data fields. 115 | * 116 | * @preconditions A valid CAN message is received 117 | * @params CAN_rx_msg - CAN message struct that will be populated 118 | * 119 | */ 120 | void CANReceive(CAN_msg_t* CAN_rx_msg) 121 | { 122 | CAN_rx_msg->id = (CAN1->sFIFOMailBox[0].RIR >> 21) & 0x7FFUL; 123 | CAN_rx_msg->len = (CAN1->sFIFOMailBox[0].RDTR) & 0xFUL; 124 | 125 | CAN_rx_msg->data[0] = 0xFFUL & CAN1->sFIFOMailBox[0].RDLR; 126 | CAN_rx_msg->data[1] = 0xFFUL & (CAN1->sFIFOMailBox[0].RDLR >> 8); 127 | CAN_rx_msg->data[2] = 0xFFUL & (CAN1->sFIFOMailBox[0].RDLR >> 16); 128 | CAN_rx_msg->data[3] = 0xFFUL & (CAN1->sFIFOMailBox[0].RDLR >> 24); 129 | CAN_rx_msg->data[4] = 0xFFUL & CAN1->sFIFOMailBox[0].RDHR; 130 | CAN_rx_msg->data[5] = 0xFFUL & (CAN1->sFIFOMailBox[0].RDHR >> 8); 131 | CAN_rx_msg->data[6] = 0xFFUL & (CAN1->sFIFOMailBox[0].RDHR >> 16); 132 | CAN_rx_msg->data[7] = 0xFFUL & (CAN1->sFIFOMailBox[0].RDHR >> 24); 133 | 134 | CAN1->RF0R |= 0x20UL; 135 | } 136 | 137 | /** 138 | * Encodes CAN messages using the CAN message struct and populates the 139 | * data registers with the sent. 140 | * 141 | * @preconditions A valid CAN message is received 142 | * @params CAN_rx_msg - CAN message struct that will be populated 143 | * 144 | */ 145 | void CANSend(CAN_msg_t* CAN_tx_msg) 146 | { 147 | volatile int count = 0; 148 | 149 | CAN1->sTxMailBox[0].TIR = (CAN_tx_msg->id) << 21; 150 | 151 | CAN1->sTxMailBox[0].TDTR &= ~(0xF); 152 | CAN1->sTxMailBox[0].TDTR |= CAN_tx_msg->len & 0xFUL; 153 | 154 | CAN1->sTxMailBox[0].TDLR = (((uint32_t) CAN_tx_msg->data[3] << 24) | 155 | ((uint32_t) CAN_tx_msg->data[2] << 16) | 156 | ((uint32_t) CAN_tx_msg->data[1] << 8) | 157 | ((uint32_t) CAN_tx_msg->data[0] )); 158 | CAN1->sTxMailBox[0].TDHR = (((uint32_t) CAN_tx_msg->data[7] << 24) | 159 | ((uint32_t) CAN_tx_msg->data[6] << 16) | 160 | ((uint32_t) CAN_tx_msg->data[5] << 8) | 161 | ((uint32_t) CAN_tx_msg->data[4] )); 162 | 163 | CAN1->sTxMailBox[0].TIR |= 0x1UL; 164 | while(CAN1->sTxMailBox[0].TIR & 0x1UL && count++ < 1000000); 165 | 166 | if (!(CAN1->sTxMailBox[0].TIR & 0x1UL)) return; 167 | 168 | //Sends error log to screen 169 | while (CAN1->sTxMailBox[0].TIR & 0x1UL) 170 | { 171 | Serial.println(CAN1->ESR); 172 | Serial.println(CAN1->MSR); 173 | Serial.println(CAN1->TSR); 174 | 175 | } 176 | } 177 | 178 | /** 179 | * Returns whether there are CAN messages available. 180 | * 181 | * @returns If pending CAN messages are in the CAN controller 182 | * 183 | */ 184 | uint8_t CANMsgAvail(void) 185 | { 186 | return CAN1->RF0R & 0x3UL; 187 | } 188 | 189 | 190 | CAN_msg_t CAN_TX_msg; 191 | CAN_msg_t CAN_rx_msg; 192 | uint8_t counter = 0; 193 | void setup() { 194 | Serial.begin(115200); 195 | CANInit(CAN_250KBPS); 196 | CAN_TX_msg.len = 8; 197 | CAN_TX_msg.id = 0x400 ; 198 | } 199 | 200 | void loop() { 201 | Serial.print("Send CAN Message..."); 202 | 203 | CAN_TX_msg.data[0] = counter; 204 | CAN_TX_msg.data[1] = 0x01; 205 | CAN_TX_msg.data[2] = 0x02; 206 | CAN_TX_msg.data[3] = 0x03; 207 | 208 | 209 | CANSend(&CAN_TX_msg); 210 | counter++; 211 | if(CANMsgAvail()) 212 | { 213 | CANReceive(&CAN_rx_msg); 214 | Serial.println("Received CAN Message"); 215 | if(CAN_rx_msg.id == 0x01) 216 | { 217 | Serial.print("CAN Message from ID 0x01: "); 218 | Serial.println(CAN_rx_msg.data[0]); 219 | 220 | } 221 | } 222 | 223 | delay(1000); 224 | 225 | 226 | } 227 | --------------------------------------------------------------------------------