#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <math.h>
#define DATA_FRAME_SIZE 8 // CAN 数据帧长度(固定为 8 字节)
// 根据 LSB0 编码(小端字节序)将信号值写入到 CAN 数据帧中
void write_signal(uint8_t *data, int start_bit, int length, uint32_t signal_value) {
// 打印信号值的二进制表示
printf(“\nSignal Value (binary): “);
for (int i = length - 1; i >= 0; i–) {
printf(”%d”, (signal_value >> i) & 1);
}
printf(“\n”);
// 从起始位开始写入信号值 for (int i = 0; i < length; i++) { int current_bit = start_bit + i; // 当前信号位的全局位置 int byte_index = current_bit / 8; // 当前位所在的字节索引 int bit_offset = current_bit % 8; // 当前位在字节中的偏移(LSB0) // 获取信号值的当前位(从最低有效位开始) uint8_t bit_value = (signal_value >> i) & 0x01; // 设置数据帧中的对应位 if (bit_value) { data[byte_index] |= (1 << bit_offset); // 设置位为1 } else { data[byte_index] &= ~(1 << bit_offset); // 清除位(设置为0) } // 调试输出 printf(" Bit %d (byte %d, offset %d) = %d\n", current_bit, byte_index, bit_offset, bit_value); }
}
// 验证并获取用户输入,支持范围检查
int get_valid_input(const char *prompt, int min, int max) {
int value;
while (1) {
printf(“%s (%d-%d): “, prompt, min, max);
if (scanf(”%d”, &value) == 1 && value >= min && value <= max) {
while (getchar() != ‘\n’); // 清空输入缓冲区
return value; // 输入合法,返回结果
} else {
printf(“Invalid input. Please enter a value in the range [%d, %d].\n”, min, max);
while (getchar() != ‘\n’); // 清空输入缓冲区
}
}
}
// 从用户获取信号值,基于动态长度校验值范围
uint32_t get_signal_value(int length) {
// 计算最大值
uint32_t max_signal_value;
if (length < 32) {
max_signal_value = (1U << length) - 1;
} else if (length == 32) {
max_signal_value = UINT32_MAX;
} else {
// 对于长度大于32位,我们使用64位计算
max_signal_value = (uint32_t)(pow(2, length) - 1);
}
uint32_t value; while (1) { printf("Enter Signal Value (0-%u): ", max_signal_value); if (scanf("%u", &value) == 1 && value <= max_signal_value) { while (getchar() != '\n'); // 清空输入缓冲区 return value; } else { printf("Invalid Signal Value. Please enter a value in the range [0, %u].\n", max_signal_value); while (getchar() != '\n'); // 清空输入缓冲区 } }
}
// 打印位布局表格(物理视图)
void print_bit_layout(uint8_t *data, int start_bit, int length) {
printf(“\nCAN Data Frame Bit Layout (Physical View):\n”);
printf(" ±----------------------------------------------------------------+\n");
printf(" | Bit: 7 6 5 4 3 2 1 0 | Byte |\n");
printf(" ±----------------------------------------------------±---------+\n");
// 计算信号覆盖的位范围 int signal_end_bit = start_bit + length - 1; // 打印每个字节的位布局 for (int byte = 0; byte < DATA_FRAME_SIZE; byte++) { printf(" | "); // 打印每个位(从高位到低位) for (int bit = 7; bit >= 0; bit--) { int global_bit = byte * 8 + (7 - bit); // 计算全局位位置 uint8_t bit_value = (data[byte] >> bit) & 0x01; // 检查当前位是否在信号范围内 int is_signal_bit = (global_bit >= start_bit && global_bit <= signal_end_bit); // 打印位值并标记信号位 if (is_signal_bit) { printf("[%d] ", bit_value); // 信号位用方括号标记 } else { printf(" %d ", bit_value); // 非信号位 } } // 打印字节索引和十六进制值 printf("| Byte %d: %02X |\n", byte, data[byte]); } printf(" +-----------------------------------------------------+----------+\n"); // 打印全局位索引 printf(" | Global Bit Index: | |\n"); printf(" | "); for (int byte = 0; byte < DATA_FRAME_SIZE; byte++) { for (int bit = 7; bit >= 0; bit--) { int global_bit = byte * 8 + (7 - bit); printf("%2d ", global_bit); } printf("| |\n | "); } printf("\b\b\b\b +-----------------------------------------------------------------+\n"); // 打印信号信息 printf("\nSignal Information:\n"); printf(" - Start Bit: %d (LSB)\n", start_bit); printf(" - End Bit: %d (MSB)\n", signal_end_bit); printf(" - Length: %d bits\n", length); printf(" - Signal occupies bits %d to %d (inclusive)\n", start_bit, signal_end_bit); // 打印数据帧的物理视图 printf("\nPhysical Data Frame Layout (LSB0):\n"); printf(" Byte 0: "); for (int bit = 0; bit < 8; bit++) { printf("%d", (data[0] >> bit) & 1); } printf(" (LSB first)\n"); for (int i = 1; i < DATA_FRAME_SIZE; i++) { printf(" Byte %d: ", i); for (int bit = 0; bit < 8; bit++) { printf("%d", (data[i] >> bit) & 1); } printf("\n"); }
}
// 将生成的 CAN 数据附加到文件
void append_to_file(const char *filename, uint32_t signal_id, uint8_t *data, int dlc) {
FILE *file = fopen(filename, “a”);
if (file == NULL) {
perror(“Error: Cannot open file”);
exit(EXIT_FAILURE); // 无法打开文件
}
fprintf(file, "$%u $%d ", signal_id, dlc); // 输出 Signal ID 和 DLC for (int i = 0; i < dlc; i++) { fprintf(file, "%02X ", data[i]); // 输出每个字节的数据 } fprintf(file, "\n"); fclose(file); // 关闭文件 printf("CAN message appended to %s\n", filename);
}
// 主函数
int main() {
uint32_t signal_id; // 信号 ID
int start_bit; // 起始位
int length; // 信号长度
uint32_t signal_value; // 信号值
char continue_flag = ‘y’;
// 打开文件并清空内容(只执行一次) FILE *file = fopen("CAN_message.txt", "w"); if (file == NULL) { perror("Error: Cannot create file"); return EXIT_FAILURE; } fclose(file); // 主循环,允许用户生成多条消息 while (continue_flag == 'y' || continue_flag == 'Y') { printf("\n===== New Message Generation (LSB0 Format) =====\n"); // 输入 Signal ID signal_id = get_valid_input("Enter Signal ID (positive integer)", 1, INT32_MAX); // 输入 Start Bit start_bit = get_valid_input("Enter Start Bit", 0, 63); // 输入 Length length = get_valid_input("Enter Signal Length", 1, 64); // 检查 Start Bit 和 Length 的组合是否合法 if (start_bit + length > 64) { printf("Error: Start Bit + Signal Length exceeds the data frame range (64 bits).\n"); printf("Start Bit: %d, Length: %d, Max End Bit: %d\n", start_bit, length, start_bit + length - 1); continue; // 提示错误后重新开始一轮输入 } // 输入 Signal Value signal_value = get_signal_value(length); // 初始化 CAN 数据帧 uint8_t data[DATA_FRAME_SIZE] = {0}; write_signal(data, start_bit, length, signal_value); // 打印位布局表格 print_bit_layout(data, start_bit, length); // 将数据写入文件 append_to_file("CAN_message.txt", signal_id, data, DATA_FRAME_SIZE); // 用户选择是否继续生成消息 printf("\nGenerate another message? (y/n): "); scanf(" %c", &continue_flag); while (getchar() != '\n'); // 清空输入缓冲区 } printf("Program exited. File will be overwritten on next run.\n"); return 0;
}
字节写入顺序有点问题,是往上走的,写完16-23的byte2之后,再写8-15的byte1
Global Bit Index: 打印的也有问题
从左往右应该是bit7到bit0:
从上往下是byte0到byte7:
打印第一行应该是 7 6 5 4 3 2 1 0
第二行应该是 15 14 13 12 11 10 9 8
最新发布