напиши сам, что тут сложного? Один оператор if - else - Если число меньше-равно 9 - выводим первый ноль, если больше - нет.вместо 0х01 выводится 0х1. в моём проекте эти нули важны.
Да никакие нули из CAN не приходят.Получается,что из CAN нули приходят, а вывести я это не могу без доп. if-else?
01
, 1
, 0x01
и 0x1
это одно и то же число, и даже 0x0000001
это то же самое число. Ведущие нули значения не имеют.Да никакие нули из CAN не приходят.01
,1
,0x01
и0x1
это одно и то же число, и даже0x0000001
это то же самое число. Ведущие нули значения не имеют.
А7-А6 | Первый символ DTC |
---|---|
00 | P-Силовая Установка |
01 | C-Шасси |
10 | B-Тело |
11 | U-Сеть |
@Semmen74, я вижу вы сами это мало понимаете и потому других путаете. У вас нет никаких 01-09 в первом байте. Смотрите на свою табличку в сообщении #8 внимательнее, первый столбец обозначен A7-A6. В курсе, что это значит? - Это первые два бита первого байта, а вовсе не целиком байт, как вы читаете.Хорошо. Объясню. на запрос приходит ответ об ошибках. одна ошибка -2 байта. и если в пером байте 01-09 то подставляем букву P
А7-А6Первый символ DTC
Вот сделал вот так:у вас буфер 8 символов. просто при получении выведите все 8 символов по одному да посмотрите что приходит. Если приходит 2 байта ответа, то это по идее должны быть 2 первых элемента массива.
Вы хотите сказать, что сообщения читать справа налево?@Semmen74, я вижу вы сами это мало понимаете и потому других путаете. У вас нет никаких 01-09 в первом байте. Смотрите на свою табличку в сообщении #8 внимательнее, первый столбец обозначен A7-A6. В курсе, что это значит? - Это первые два бита первого байта, а вовсе не целиком байт, как вы читаете.
Формат DTC кодов ошибок описан в куче мест в интернете, вы бы сначала разобрались как они устроены. а то вы читаете из Кана какую-то ерунду и не знаете как ей пользоваться.
Я бы посоветовал вам начать проект с изучения битовых операций, потому что для того чтоб правильно интервпретировать ошибки из КАН, надо уметь извлекать каждый отдельный бит из байта, а вы в трех соснах путаетесь, не можете 0х00 от 0х0 отличить
выложите строго тот код, которым вы читаете данные, а то этот вы явно сейчас по памяти писали, тут у вас куча ошибок - незакрытые скобки. нет индексов в буфере... Да и порядок данных в коде и в выводе разный.Вот сделал вот так:
Serial.println("Количество ошибок:");
.....
я хочу сказать, что некоторые из байтов надо разбирать побитно. А вы их на печать выдаете как символы - так у вас ничего не получится.Вы хотите сказать, что сообщения читать справа налево?
выложите строго тот код, которым вы читаете данные, а то этот вы явно сейчас по памяти писали, тут у вас куча ошибок - незакрытые скобки. нет индексов в буфере... Да и порядок данных в коде и в выводе разный.
я хочу сказать, что некоторые из байтов надо разбирать побитно. А вы их на печать выдаете как символы - так у вас ничего не получится.
я не это просил.Это набросок. Не оптимизированный. Работа с библиотекой CAN BAS-Shild/
да, этоВы имеете ввиду вот это:
/*void taskCanRecv() {
if (getPid) { // Получить PID
getPid = 0;
sendPid(PID_INPUT);
PID_INPUT = 0;
}
if (CAN_MSGAVAIL == CAN.checkReceive()) { // проверка получения данных
CAN.readMsgBuf(&len, buf); // чтение данных, len: длина данных, buf: данные
Serial.println("\r\n------------------------------------------------------------------");
Serial.print("Get Data from ID: 0x");
Serial.println(CAN.getCanId(), HEX);
for (int i = 0; i < len; i++) { // Вывод данных
Serial.print("0x");
Serial.print(buf[i], HEX);
Serial.print("\t");
}
Serial.println();
}
}
да, это
Только на будущее вставляйте код - как код, а то читать неудобно и комментировать слоно
Собственно, я с вами эти пропавшие квадратные скобки в строке 15 и хотел обсудить... а это оказывается потому что вы код неверно вставили.C++:/*void taskCanRecv() { if (getPid) { // Получить PID getPid = 0; sendPid(PID_INPUT); PID_INPUT = 0; } if (CAN_MSGAVAIL == CAN.checkReceive()) { // проверка получения данных CAN.readMsgBuf(&len, buf); // чтение данных, len: длина данных, buf: данные Serial.println("\r\n------------------------------------------------------------------"); Serial.print("Get Data from ID: 0x"); Serial.println(CAN.getCanId(), HEX); for (int i = 0; i < len; i++) { // Вывод данных Serial.print("0x"); Serial.print(buf[i], HEX); Serial.print("\t"); } Serial.println(); } }
Вставляйте код правильно, чтобы не тратить время на обсуждение ошибок, которых нет
потому что вы вставляете код просто как текст.Да я и вставлял как есть, но почему то сайт убирает квадратные скобки
#include <SPI.h>
#include "mcp_can.h" // Подключаем библиотеку для работы с CAN
#include "UTFT.h" // Подключаем библиотеку для работы с дисплеем
#include "TouchScreen.h" // Подключаем библиотеку для работы с TouchScreen
// подключаем шрифты
extern uint8_t SmallFont[]; // Устанавливаем маленький шрифт
extern uint8_t BigFont[]; // Устанавливаем большой шрифт
extern uint8_t SevenSegNumFont[]; // Устанавливаем семисегментный шрифт
#ifdef ARDUINO_SAMD_VARIANT_COMPLIANCE // Проверка соответствия связи МК с портами
#define SERIAL SerialUSB
#else
#define SERIAL Serial
#endif
// Определяем выводы используемые для управления дисплеем 2.8" TFT 320x240 UNO:
const uint8_t RS = 8; // MOSI
const uint8_t WR = 7; // SCK
const uint8_t CS = 6; // CS
const uint8_t RST = 5; // RST
const uint8_t SER = 4; // D/C
// Определяем выводы используемые для чтения данных с TouchScreen:
const uint8_t YP = A0; // Вывод Y+ должен быть подключен к аналоговому входу
const uint8_t XM = A1; // Вывод X- должен быть подключен к аналоговому входу
const uint8_t YM = A2; // Вывод Y- должен быть подключен к аналоговому входу
const uint8_t XP = A3; // Вывод X+ должен быть подключен к аналоговому входу
// Определяем экстремумы для значений считываемых с аналоговых входов при определении точек нажатия на TouchScreen:
const int tsMinX = 100; // соответствующий точке начала координат по оси X
const int tsMinY = 120; // соответствующий точке начала координат по оси Y
const int tsMaxX = 950; // соответствующий максимальной точке координат по оси X
const int tsMaxY = 915; // соответствующий максимальной точке координат по оси Y
const int mipPress = 10; // соответствующий минимальной степени нажатия на TouchScreen
const int maxPress = 1000; // соответствующий максимальной степени нажатия на TouchScreen
//const uint8_t pen_radius = 3; // указываем размер точки, которая будет появляться при рисовании
const int SPI_CS_PIN = 9; // Определяем выводы, используемые для управления CAN Shild
// Создаём объекты библиотек:
MCP_CAN CAN(SPI_CS_PIN); // Установка CS pin
UTFT myGLCD(TFT01_24SP, RS, WR, CS, RST, SER); // Создаём объект для работы с дисплеем
TouchScreen ts = TouchScreen(XP, YP, XM, YM); // Создаём объект для работы с TouchScreen
// Определяем PIDs
#define PID_ENGIN_PRM 0x0C //
#define PID_VEHICLE_SPEED 0x0D //
#define PID_COOLANT_TEMP 0x05 //
#define CAN_ID 0x7DF //
#define CAN_ID_2 0x7E0
unsigned char OTRej_3[] = {0x01, 0x03, 0x00, 0, 0, 0, 0, 0}; // Запрос текущих ошибок DTC
unsigned char OTRTR [] = {0x30, 0, 0, 0, 0, 0, 0, 0};
void set_mask_filt() {
// Установка маски (set mask, set both the mask to 0x7FC)
CAN.init_Mask(0, 0, 0x7FC); // Маска для стандартных сообщений
CAN.init_Mask(1, 0, 0x7FC); // Маска для расширенных сообщений
// Установка фильтров для чтения сообщений ID 0x04 ~ 0x09 байт
CAN.init_Filt(0, 0, 0x7E8);
CAN.init_Filt(0, 0, 0x7E9);
CAN.init_Filt(2, 0, 0x7E8);
CAN.init_Filt(3, 0, 0x7E9);
CAN.init_Filt(4, 0, 0x7E8);
CAN.init_Filt(5, 0, 0x7E8);
}
void setup() {
Serial.begin(115200); // Инициируем передачу данных в монитор последовательного порта на скорости 115200 бод
myGLCD.InitLCD(); // Инициируем работу с TFT дисплеем
while (CAN_OK != CAN.begin(CAN_500KBPS)) { // init can bus : baudrate = 500k
Serial.println("CAN BUS Shield init fail");
Serial.println(" Init CAN BUS Shield again");
myGLCD.setFont (BigFont); // устанавливаем большой шрифт
myGLCD.print("CAN BUS Shield init fail", CENTER, 100); // выводим текст в указанных координатах
delay(100);
}
Serial.println("CAN BUS Shield init ok!");
set_mask_filt();
myGLCD.setFont (BigFont); // устанавливаем большой шрифт
myGLCD.print("CAN init ok!", CENTER, 100); // выводим текст в указанных координатах
delay(2000);
myGLCD.clrScr(); // Чистим экран
delay(100);
myGLCD.setColor(VGA_WHITE); // Указываем белый цвет
myGLCD.drawLine(0, 0, 40, 40); // Рисуем линию
myGLCD.drawLine(40, 0, 0, 40); // Рисуем линию
myGLCD.setColor(VGA_YELLOW); // Указываем жёлтый цвет
myGLCD.fillRect(0, 40, 40, 80); // Рисуем квадрат
myGLCD.setColor(VGA_GREEN); // Указываем зелёный цвет
myGLCD.fillRect(0, 80, 40, 120); // Рисуем квадрат
myGLCD.setColor(VGA_RED); // Указываем красный цвет
myGLCD.fillRect(0, 120, 40, 160); // Рисуем квадрат
myGLCD.setColor(VGA_PURPLE); // Указываем фиолетовый цвет
myGLCD.fillRect(0, 160, 40, 200); // Рисуем квадрат
myGLCD.setColor(VGA_BLUE); // Указываем синий цвет
myGLCD.fillRect(0, 200, 40, 240); // Рисуем квадрат
}
void loop() {
// Считываем показания с TouchScreen:
TSPoint p = ts.getPoint(); // Считываем координаты и интенсивность нажатия на TouchScreen в структуру p
// Возвращаем режим работы выводов:
pinMode(XM, OUTPUT); // Возвращаем режим работы вывода X- в значение «выход» для работы с дисплеем
pinMode(YP, OUTPUT); // Возвращаем режим работы вывода Y+ в значение «выход» для работы с дисплеем
// Если зафиксировано нажатие на TouchScreen, то ...
if (p.z > mipPress && p.z < maxPress) { // Если степень нажатия достаточна для фиксации координат TouchScreen
p.x = map(p.x, tsMinX, tsMaxX, 0, 320); // Преобразуем значение p.x от диапазона tsMinX...tsMaxX, к диапазону 0...320
p.y = map(p.y, tsMinY, tsMaxY, 0, 240); // Преобразуем значение p.y от диапазона tsMinY...tsMaxY, к диапазону 0...240
if (p.x <= 40) { // Если нажатие было в зоне выбора цветов, то
if (p.y < 40 ) { // Если нажатие было в зоне кнопки "очищение экрана", то
myGLCD.clrScr(); // Чистим экран дисплея
myGLCD.setColor(VGA_WHITE); // Указываем цвет
myGLCD.drawLine(0, 0, 40, 40); // Рисуем линию
myGLCD.drawLine(40, 0, 0, 40); // Рисуем линию
myGLCD.setColor(VGA_YELLOW); // Указываем цвет
myGLCD.fillRect(0, 40, 40, 80); // Рисуем квадрат
myGLCD.setColor(VGA_GREEN); // Указываем цвет
myGLCD.fillRect(0, 80, 40, 120); // Рисуем квадрат
myGLCD.setColor(VGA_RED); // Указываем цвет
myGLCD.fillRect(0, 120, 40, 160); // Рисуем квадрат
myGLCD.setColor(VGA_PURPLE); // Указываем цвет
myGLCD.fillRect(0, 160, 40, 200); // Рисуем квадрат
myGLCD.setColor(VGA_BLUE); // Указываем цвет
myGLCD.fillRect(0, 200, 40, 240); // Рисуем квадрат
}
else if (p.y > 80 && p.y <= 120 ) { // Если нажатие было в зоне зелёного квадрата, то
myGLCD.setColor(VGA_GREEN); // Устанавливаем цвет
myGLCD.setFont (BigFont); // устанавливаем большой шрифт
myGLCD.print("Request DTC 3", 45, 100); // выводим текст в указанных координатах
CAN.sendMsgBuf(CAN_ID, 0, 8, OTRej_3); // Запрос режима 03
}
}
}
TaskRecive03();
}
void TaskRecive03() {
unsigned char len = 0;
unsigned char buf[8];
if (CAN_MSGAVAIL == CAN.checkReceive()) {
CAN.readMsgBuf(&len, buf);
if ( buf[0] == 0x02 &&
buf[1] == 0x43 &&
buf[2] == 0x00)
{
Serial.print("В автомобиле ошибок нет");
}
else if (buf[0] > 0x02 &&
buf[1] == 0x43 &&
buf[2] >= 0x01 <= 0x02)
{
Serial.print (buf[3], HEX);
Serial.println(buf[4], HEX);
Serial.print (buf[5], HEX);
Serial.println(buf[6], HEX);
Serial.println(buf[7], HEX);
}
else if ( buf[0] == 0x10 &&
buf[2] == 0x43 &&
buf[3] >= 0x03)
{
Serial.println("Количество ошибок:");
Serial.println(buf[3], DEC);
Serial.println("Коды ошибок:");
Serial.print (buf[4], HEX);
Serial.println(buf[5], HEX);
Serial.print (buf[6], HEX);
Serial.println(buf[7], HEX);
CAN.sendMsgBuf(CAN_ID_2, 0, 8, OTRTR); // Запрос RTR
}
else if ( buf[0] == 0x21)
{
Serial.println(buf[1], buf[2]);
Serial.println(buf[3], buf[4]);
Serial.println(buf[5], buf[6]);
Serial.print(buf[7]);
}
else if ( buf[0] == 0x22)
{
Serial.println(buf[1]);
Serial.println(buf[2], buf[3]);
Serial.println(buf[4], buf[5]);
Serial.println(buf[6], buf[7]);
}
else if ( buf[0] == 0x23)
{
Serial.println(buf[1], buf[2]);
Serial.println(buf[3], buf[4]);
Serial.println(buf[5], buf[6]);
Serial.print(buf[7]);
}
}
}
Хороший пример. Давайте разберем0x4 0x43 0x1 0x1 0x13 0x0 0x0 0x0
Количество ошибок:1
Хороший пример. Давайте разберем
Во первых, отбросим первые три числа - они к ошибкам отношения не имеют.
Четвертое число - количество ошибок, там 0х1, что значит просто - 1 ошибка. И не важно, 0х1 там , 0х01 или просто 1.
Далее идут сами ошибки
0x13 0x0 0x0 0x0
Вот тут и надо искать ваши "00" "01" и так далее.И не в виде отдельных байт. а прямо в ошибках
Где? - да в коде 0х13 например.
Код 0х13 начинается битов "00"
Определить это просто - 0х13 в бинарном виде - это будет 00010011, первые два бита слева - "00"
Так что 0х13 - это ошибка типа P и с номером 19 (потому что 0х13 - 19 в десятичной системе)
Этот разбор - только пример. Как именно пакуются ошибки - надо смотреть в стандарте. Они могут занимать несколько байт. Но главное, что я хотел донести - что комбинации "00" "01" - не являются отдельными байтами, они запакованы в сами байты ошибок. Об этом однозначно говорит запись А7-А6 в заголовке вашей таблицы. "А7-А6" - означает "два старших бита первого байта ошибки"
Вы сами разберитесь, число ошибок у вас в третьем байте или в четвертом.Не четвёртое число, а третье-количество ошибок
Serial.println("Количество ошибок:");
Serial.println(buf[3], DEC);
Serial.println("Коды ошибок:");
Serial.print (buf[4], HEX);
Serial.println(buf[5], HEX);
Serial.print (buf[6], HEX);
Serial.println(buf[7], HEX);
ну да, вот и я о том же смотреть надо битыА теперь смотрим табличку и 1-ый байт
0b0000 0100 - подчеркнуты два бита А7 и А6 , они 0 и 0
Одно другому не противоречит. В разных режимах формат может быть разным.Но в режиме 03 ни каких PID нет. И в режиме 07 и в режиме 02 тоже нет.
Так все-таки третий? а в программе у вас - четвертый3 байт слева -количество ошибок. Проверено на практике