Vehicle Control Unit 0.01
This is the c library for controlling the car.
Loading...
Searching...
No Matches
Can.c
Go to the documentation of this file.
1#ifndef TEST_MODE
2#include "stm32f7xx_it.h"
3#endif
4
5#include "../../../../Inc/Systems/Comms/Can/Can.h"
6#include "../../../../Inc/Systems/Comms/Can/DBCParser.h"
7#include "../../../../Inc/Systems/PrintHelpers.h"
8
9#include <stdio.h>
10#include <string.h>
11#include <stdlib.h>
12#include <inttypes.h>
13
14// CAN message list
16
18 // Initialize the CAN message list
19 can_messages[bus].bus = bus;
21
22 return 0;
23}
24
25int load_dbc_file(CANBus bus, const unsigned char* filename)
26{
27 // Load the DBC file
28 #ifdef TEST_MODE
29 // unsigned char* dbc_contents = fopen(filename, "w");
30 #else
31 unsigned char* dbc_contents = filename;
32 #endif
33// printf("Loading DBC file: %c\r\r\n", filename[0]);
34
35 #ifndef TEST_MODE
36 // Parse the DBC file
37 parseDbcFile(&can_messages[bus], dbc_contents);
38 #endif
39
40 #ifdef TEST_MODE
41 // fclose(dbc_contents);
42 #endif
43
45 return 0;
46}
47
49 // Add the message to the list
52 return 0;
53}
54
55int add_message_lop(CANBus bus, int id, int dlc, int ide, int rtr, const char* name, const char* sender, int signal_count, CAN_Signal_Template* signals)
56{
57 // Create a CAN message template
59 message.id = id;
60 message.dlc = dlc;
61 message.ide = ide;
62 message.rtr = rtr;
63 strcpy(message.name, name);
64 strcpy(message.sender, sender);
65 message.signal_count = signal_count;
66 message.payload_length = 0;
67
68 // Copy the signals
69 for (int i = 0; i < signal_count; i++) {
70 message.signals[i] = signals[i];
71 message.payload_length += signals[i].length;
72 }
73
74 // Add the message to the list
75 return add_message(bus, message);
76}
77
78// Send a CAN message
79int send_CAN_message(CANBus bus, CANProtocol protocol, uint32_t id, uint8_t* data, uint8_t len) {
80 CAN_TxHeaderTypeDef TxHeader;
81 if (protocol == CAN_2A) {
82 TxHeader.StdId = id;
83 TxHeader.IDE = CAN_ID_STD;
84 } else if (protocol == CAN_2B) {
85 TxHeader.ExtId = id;
86 TxHeader.IDE = CAN_ID_EXT;
87 } else {
88 printf("Invalid CAN protocol\r\n");
89 return -1;
90 }
91
92 TxHeader.RTR = CAN_RTR_DATA;
93 TxHeader.DLC = len;
94
95 // Print the message
96 printf(ANSI_COLOR_YELLOW "Sending CAN Message" ANSI_COLOR_RESET ": ID: %d, DLC: %d, Data: ", id, len);
97 for (int i = 0; i < len; i++) {
98 printf("%02X ", data[i]);
99 }
100 printf("\r\n");
101
102 #ifndef TEST_MODE
103 // Send the CAN message
104 if (send_CAN_message_helper(bus, &TxHeader, data) != 0) {
105 return -2;
106 }
107 #endif
108 return 0;
109}
110
111// Receive a CAN message from the Callback
112void receive_CAN_message(CAN_RxHeaderTypeDef* RxHeader, uint8_t* RxData, CANBus bus) {
113 CAN_Message* can_message = malloc(sizeof(CAN_Message) + sizeof(CAN_Signal) * 8);
114 can_message->header = *RxHeader;
115 memcpy(can_message->data, RxData, 8);
116
117 // Parse the message
118 parseMessage(&can_messages[bus], can_message);
119
120 // Print out the contents of the message
121 printf(ANSI_COLOR_YELLOW "Received CAN Message" ANSI_COLOR_RESET ": %s (ID: %d, DLC: %d, Sender: %s)\r\n", can_message->template->name, can_message->header.StdId, can_message->header.DLC, can_message->template->sender);
122
123 // Print the signals
124 for (int i = 0; i < can_message->template->signal_count; i++) {
125 CAN_Signal* signal = &can_message->signals[i];
126 printf("\t" ANSI_COLOR_MAGENTA "Signal" ANSI_COLOR_RESET ": %s (Value: %u, Unit: %s)\r\n", signal->template->name, signal->value, signal->template->unit);
127 }
128 printf("\r\n");
129
130 // Free the message
131 free(can_message);
132}
133
134// Parse a CAN message
135void parseMessage(CAN_MessageList* messages, CAN_Message* can_message) {
136 // Find the message in the list
137 // TODO: Implement a hash table or map for faster lookup
138 for (int i = 0; i < messages->num_messages; i++) {
139 CAN_Message_Template* msg = &messages->messages[i];
140 if (msg->id == can_message->header.StdId || msg->id == can_message->header.ExtId) {
141 // Parse the signals of the message
142 can_message->template = msg;
143 parseSignals(msg, can_message);
144 return;
145 }
146 }
147}
148
149// Parse the signals of a CAN message
150void parseSignals(CAN_Message_Template* message, CAN_Message* can_message) {
151 // Find the signals in the message
152 for (int i = 0; i < message->signal_count; i++) {
153 CAN_Signal_Template* signal = &message->signals[i];
154 // Parse the signal
155 parseSignal(signal, &can_message->signals[i], can_message);
156 }
157}
158
159// Parse a CAN signal
160void parseSignal(CAN_Signal_Template* signal, CAN_Signal* can_signal, CAN_Message* can_message) {
161 can_signal->template = signal;
162
163 // Extract the raw data from the message
164 uint64_t raw_data = 0;
165 for (int i = signal->start_bit; i < signal->start_bit + signal->length; i++) {
166 raw_data |= ((can_message->data[i / 8] >> (i % 8)) & 1) << (i - signal->start_bit);
167 }
168
169 // Check if the signal is big endian
170 if (signal->endian == 1) {
171 // Reverse the bits
172 uint64_t reversed_data = 0;
173 for (int i = 0; i < signal->length; i++) {
174 reversed_data |= ((raw_data >> i) & 1) << (signal->length - i - 1);
175 }
176 raw_data = reversed_data;
177 }
178
179 // Check if the signal is signed
180 if (signal->isSigned) {
181 // Sign extend the data
182 raw_data = (raw_data << (64 - signal->length)) >> (64 - signal->length);
183 }
184
185 // Scale and offset the data
186 can_signal->value = (raw_data * signal->scale) + signal->offset;
187
188}
189
191 for (int i = 0; i < MAX_BUS; i++) {
192 printf("Printing CAN Message List for bus %d with %d messages\r\n", i, can_messages[i].num_messages);
193 for (int j = 0; j < can_messages[i].num_messages; j++) {
194 const CAN_Message_Template* msg = &can_messages[i].messages[j];
195 printf(ANSI_COLOR_GREEN "Message" ANSI_COLOR_RESET ": %s (ID: %d, DLC: %d, Sender: %s, SIGs: %d)\r\n", msg->name, msg->id, msg->dlc, msg->sender, msg->signal_count);
196 for (int k = 0; k < msg->signal_count; k++) {
197 const CAN_Signal_Template* sig = &msg->signals[k];
198 printf("\t" ANSI_COLOR_BLUE "Signal" ANSI_COLOR_RESET ": %s (Start bit: %d, Length: %d, Endain: %d, Signed: %c,\r\n\t\tScale: %f, Offset: %f, Min: %f, Max: %f, \r\n\t\tUnit: %s, Reciever: %s)\r\n", sig->name, sig->start_bit, sig->length, sig->endian, sig->isSigned, sig->scale, sig->offset, sig->min, sig->max, sig->unit, sig->reciever);
199 }
200 printf("\r\n");
201 }
202 if (can_messages[i].num_messages == 0) {
203 printf("No messages on bus %d\r\n", i);
204 }
205 }
206}
int init_CANBus(CANBus bus)
Initializes the CANBus struct.
Definition: Can.c:17
CAN_MessageList can_messages[MAX_BUS]
Definition: Can.c:15
void parseSignals(CAN_Message_Template *message, CAN_Message *can_message)
Parses signals in a CAN message.
Definition: Can.c:150
void parseSignal(CAN_Signal_Template *signal, CAN_Signal *can_signal, CAN_Message *can_message)
Parses a CAN signal.
Definition: Can.c:160
void parseMessage(CAN_MessageList *messages, CAN_Message *can_message)
Parses a CAN message.
Definition: Can.c:135
#define ANSI_COLOR_RESET
int add_message(CANBus bus, CAN_Message_Template message)
Adds a message to the CAN message list.
Definition: Can.c:48
int add_message_lop(CANBus bus, int id, int dlc, int ide, int rtr, const char *name, const char *sender, int signal_count, CAN_Signal_Template *signals)
Adds a message to the CAN message list by passing in the individual message parameters hence "LOP" (L...
Definition: Can.c:55
int send_CAN_message(CANBus bus, CANProtocol protocol, uint32_t id, uint8_t *data, uint8_t len)
Sends a CAN message.
Definition: Can.c:79
void receive_CAN_message(CAN_RxHeaderTypeDef *RxHeader, uint8_t *RxData, CANBus bus)
Receives a CAN message.
Definition: Can.c:112
int load_dbc_file(CANBus bus, const unsigned char *filename)
Loads a DBC file into the CAN database. Makes the messages and signals and stores them in the list.
Definition: Can.c:25
void print_CAN_Messages_Lists()
Prints the CAN message list.
Definition: Can.c:190
CANBus
Definition: Can.h:98
#define MAX_BUS
Definition: Can.h:94
CANProtocol
Definition: Can.h:104
@ CAN_2A
Definition: Can.h:105
@ CAN_2B
Definition: Can.h:106
int parseDbcFile(CAN_MessageList *messages, const unsigned char *dbc_contents)
Parses a DBC (CAN database) file and populates the DBC structure.
Definition: DBCParser.c:31
void print_CAN_MessageList(const CAN_MessageList *messages)
Prints the contents of a CAN message list (aka DBC file).
Definition: DBCParser.c:44
#define ANSI_COLOR_YELLOW
Definition: PrintHelpers.h:3
#define ANSI_COLOR_GREEN
Definition: PrintHelpers.h:2
#define ANSI_COLOR_BLUE
Definition: PrintHelpers.h:4
#define ANSI_COLOR_MAGENTA
Definition: PrintHelpers.h:5
This file contains the headers of the interrupt handlers.
int send_CAN_message_helper(CANBus bus, CAN_TxHeaderTypeDef *TxHeader, uint8_t *data)
Definition: stm32f7xx_it.c:292
CANBus bus
Definition: Can.h:122
CAN_Message_Template messages[MAX_MESSAGES]
Definition: Can.h:123
int num_messages
Definition: Can.h:124
char sender[MAX_NODE_NAME_LENGTH]
Definition: Can.h:78
int signal_count
Definition: Can.h:80
int payload_length
Definition: Can.h:81
CAN_Signal_Template signals[MAX_SIGNALS]
Definition: Can.h:79
char name[MAX_MESSAGE_NAME_LENGTH]
Definition: Can.h:77
uint8_t data[8]
Definition: Can.h:86
CAN_Signal signals[]
Definition: Can.h:88
CAN_Message_Template * template
Definition: Can.h:87
CAN_RxHeaderTypeDef header
Definition: Can.h:85
char unit[MAX_UNIT_NAME_LENGTH]
Definition: Can.h:29
char reciever[MAX_NODE_NAME_LENGTH]
Definition: Can.h:30
float offset
Definition: Can.h:26
float scale
Definition: Can.h:25
char name[MAX_SIGNAL_NAME_LENGTH]
Definition: Can.h:20
Definition: Can.h:33
int value
Definition: Can.h:34
CAN_Signal_Template * template
Definition: Can.h:35