Подскажите по преобразованию данных
- Войдите на сайт для отправки комментариев
Ср, 21/12/2016 - 13:37
Собственно проблема такая -
читаюсообщение с CANBUS, к примеру 01 FF 00 00 00 00 00 00 необходимо получить результат вида 01FF и перевести в десятичную систему т.е. 511, если во втором числе всё, что угодно кроме FF, то преобразуется правильно, как только FF - затык. Код ниже, что я делаю не так?
#include <mcp_can.h>
#include <SPI.h>
long unsigned rxId;
long previousMillis = 0;
unsigned char len = 0;
unsigned char rxBuf[8];
int value = LOW;
long freq = 0;
long b;
long input;
MCP_CAN CAN(10);
void setup() {
CAN.begin(CAN_500KBPS);
}
void loop() {
canread();
if (rxId == 0x37E && (len == 5 || len == 6 || len == 7)) {
goto a39;
}
a39:
canread();
if (rxId == 0x37E) {
input = uint16_t(rxBuf[0] << 7 | rxBuf[1] );
}
blink(input);
goto a39;
}
void blink (long input)
{
if (b != input)
{
b = input;
}
if (input > 0)
{
freq = 65535 / b;
if (millis() - previousMillis > freq) {
previousMillis = millis();
if (value == LOW)
value = HIGH;
else
value = LOW;
digitalWrite(3, value);
}
}
else if (input == 0)
{
digitalWrite(3, HIGH);
}
}
void canread()
{
CAN.readMsgBuf(&len, rxBuf);
rxId = CAN.getCanId();
}
Используйте для беззнаковых величин unsigned int, unsigned long, uint16_t и т.п.
Иначе при обработке значений больше 0x80, 0x8000, 0x80000000 получим неверный результат.
В приведенном фрагменте кода, знаковые переменые не требуются, заменяйте все int на unsigned, а long на unsigned long.
после замены ровно тот же результат - 01FF=00FF
Интересно, что Вы хотели здесь сделать?
void loop() { canread(); if (rxId == 0x37E && (len == 5 || len == 6 || len == 7)) { goto a39; } a39: canread(); if (rxId == 0x37E) { input = uint16_t(rxBuf[0] << 7 | rxBuf[1] ); } blink(input); goto a39; }Интересно, что Вы хотели здесь сделать?
void loop() { canread(); if (rxId == 0x37E && (len == 5 || len == 6 || len == 7)) { goto a39; } a39: canread(); if (rxId == 0x37E) { input = uint16_t(rxBuf[0] << 7 | rxBuf[1] ); } blink(input); goto a39; }1. Определить авто по уникальному ID (код сильно кастрирован ибо идентификаторы - военная тайна)
2. Прочитать 2 бита из 8
3. Моргнуть светодиодом через функцию blink
4. Вернуться в цикл а39.
Оказалось что надо так -
input = uint16_t(rxBuf[0] << 8 | rxBuf[1] );
В общем немного переписал, но грабли остались, поможите люди добрые бьюсь как лбом об стену - не преобразуется из 16 в 10ку input хоть лопни.
#include <mcp_can.h> #include <SPI.h> unsigned char len = 0, rxBuf[8]; unsigned kbps = 0, value = LOW; unsigned long rxId, input, freq = 0, previousMillis = 0; MCP_CAN CAN(10); void setup() { CAN.begin(CAN_500KBPS); } void loop() { canread(); if (rxId == 0x37E && len == 7) { goto a39; } a39: canread(); if (rxId == 0x37E) { input = uint16_t(rxBuf[0] << 8 | rxBuf[1] ); } blink(input); goto a39; } void blink (unsigned int input) { canread(); if (input != 0) { freq = 65535 - input; if (millis() - previousMillis > freq) { previousMillis = millis(); value = !value; digitalWrite(3, value); } } else if (input == 0) { digitalWrite(3, HIGH); } } void canread() { CAN.readMsgBuf(&len, rxBuf); rxId = CAN.getCanId(); }1. Определить авто по уникальному ID (код сильно кастрирован ибо идентификаторы - военная тайна)
2. Прочитать 2 бита из 8
3. Моргнуть светодиодом через функцию blink
4. Вернуться в цикл а39.
1 - понятно.
2 - понятно, только наверное 2 байта
3 - не понятно, носудя по коду моргнуть светодиодом на время 65535 минус то что прочитали 0x01FF (511) миллисек, то есть на 65024 миллисек (65 сек = чуть больше минуты), так ?
4 - код ужасный, это не надо.
более развернуто опишите.
а по поводу ваших мытарств с input, вот попробуйте, пытался по шагам
void setup() { // initialize serial communications at 9600 bps: Serial.begin(9600); byte b1=0x01,b2=0xFE; unsigned long input = b1; Serial.print("input = "); Serial.println(input,HEX); input <<= 8; Serial.print("input = "); Serial.println(input,HEX); input |= b2; Serial.print("input = "); Serial.println(input,HEX); Serial.print("input = "); Serial.println(input); } void loop() { }1. Определить авто по уникальному ID (код сильно кастрирован ибо идентификаторы - военная тайна)
2. Прочитать 2 бита из 8
3. Моргнуть светодиодом через функцию blink
4. Вернуться в цикл а39.
1 - понятно.
2 - понятно, только наверное 2 байта
3 - не понятно, носудя по коду моргнуть светодиодом на время 65535 минус то что прочитали 0x01FF (511) миллисек, то есть на 65024 миллисек (65 сек = чуть больше минуты), так ?
4 - код ужасный, это не надо.
более развернуто опишите.
а по поводу ваших мытарств с input, вот попробуйте, пытался по шагам
void setup() { // initialize serial communications at 9600 bps: Serial.begin(9600); byte b1=0x01,b2=0xFE; unsigned long input = b1; Serial.print("input = "); Serial.println(input,HEX); input <<= 8; Serial.print("input = "); Serial.println(input,HEX); input |= b2; Serial.print("input = "); Serial.println(input,HEX); Serial.print("input = "); Serial.println(input); } void loop() { }По 4му пункту - прошу пардона, ну не кодер я, немного на PHP пишу...... не суть. Плюс здесь просто кусок из контекста - циклов типа "а39" в полной версии около 200.
Попробую более развернуто - надо на выхлопе получить меандр с D3 что то примерно около 600 импульов в минуту, частота меандра естественно должна повышаться по увеличению первых 2х байт сообщения с CAN шины.
Как то так.
посмотрите вот это http://arduino.ru/forum/proekty/generator-s-reguliruemoei-chastotoi-na-arduino
нодо только установить нужную частоту и менять ее не от энкодера, а от принятых байт с CAN шины.
Спасибо, посмотрел.... чужой код хуже татарина, аж мозг вскипел.....