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