int16 получить битовую маску значений
- Войдите на сайт для отправки комментариев
Пт, 05/08/2016 - 17:38
Всем привет!
Использую библиотеку Modbus RTU. Опрашиваю прибор МВ 110. Там 16 входов. Сосчитать их состояние можно одной командой. В ответ получаю значения int16.
Вот так я получаю почти то что мне нужно:
char A[17]; itoa(regs[0],A,2);
т.е. при замыкании контактов 2 и 6, я получаю ответ в виде A = 100010
Вот так только 8 контакт: 10000000
Всего 16 входов. Я хочу в print посылать значения, приведенные к нормальным, в виде:
A = 10100010 K1 = 0 K2 = 1 K3 = 0 K4 = 0 K5 = 0 K6 = 1 K7 = 0 K8 = 1 K9 = 0 K10 = 0 K11 = 0 K12 = 0 K13 = 0 K14 = 0 K15 = 0 K16 = 0
Опытным путем сделал вот так, но все равно не совсем как надо:
void loop()
{
modbus_update();
mySerial.print(" regs0: ");
char A[17];
itoa(regs[0],A,2);
mySerial.print(A);
for (byte i = 0; i < 16; i++){
mySerial.print(" K");
int i2 = 16-i;
mySerial.print(i2);
mySerial.print(": ");
mySerial.print(A[i]);
}
mySerial.println();
}
При работе кода что выше я получаю строку при замкнутом 7 контакте. regs0 = показывает что замкнут только 7 контакт, а как добавить недостающие нули? чтобы мой код правильно начал работать?
regs0: 1000000 K16: 1 K15: 0 K14: 0 K13: 0 K12: 0 K11: 0 K10: 0 K9: K8: 0 K7: K6: K5: K4: K3: K2: K1:
Ответ банальный. Не пользоваться функцией itoa.
Ответ банальный. Не пользоваться функцией itoa.
Подскажите как правильно написать?
Скорее всего подобно этому.
Но скорее в цикле A[i]=(regs[0] & (1<<i))>> i где i от 0 до 16, а regs[0] ваше число которое надо преобразовывать.
ПС: надо проверять.
Вы про битовые операции знаете? Вот их и надо использовать, как-то так, навскидку:
// файл Templates.h #ifndef _TEMPLATES_H #define _TEMPLATES_H #include <Arduino.h> template<class T> void print_bits(T val) { for(byte i=0;i<sizeof(val)*CHAR_BIT;i++) { if(val & (1 << i)) Serial.print("1"); else Serial.print("0"); } Serial.println(); } #endifСам скетч:
#include "Templates.h" void setup() { } void loop() { byte bVal = 123; print_bits<byte>(bVal); int iVal = 12345; print_bits<int>(iVal); }Тупо быстро набросал, мог где-то ошибиться, на ардуину закачивать не стал - все свободные щас заняты :(
Что-то не один из вариантов не работает :(
Что-то не один из вариантов не работает :(
Сорри, я там обшибся, щас поправлю. Вот поправленный:
#ifndef _TEMPLATES_H #define _TEMPLATES_H #include <Arduino.h> #include <limits.h> template<class T> void print_bits(T val) { for(byte i=0;i<sizeof(val)*CHAR_BIT;i++) { if(val & (1 << i)) Serial.print("1"); else Serial.print("0"); } Serial.println(); } #endifПоправил и сверху, на всякий. Совсем забыл про CHAR_BIT, голова садовая.
Проверил на http://cpp.sh/, вот код, на котором проверял всё работает как надо:
// Example program #include <iostream> #include <string> #include <limits.h> template<class T> void print_bits(T val) { for(uint8_t i=0;i<sizeof(val)*CHAR_BIT;i++) { if(val & (1 << i)) std::cout << "1"; else std::cout << "0"; } std::cout << std::endl; } int main() { uint8_t bVal = 123; print_bits<uint8_t>(bVal); int16_t iVal = 12345; print_bits<int16_t>(iVal); }Только определиться с big endian и little endian надо. Если надо в обратном порядке биты выводить, то:
// Example program #include <iostream> #include <string> #include <limits.h> template<class T> void print_bits(T val) { for(int8_t i=sizeof(val)*CHAR_BIT-1;i>=0;--i) { if(val & (1 << i)) std::cout << "1"; else std::cout << "0"; } std::cout << std::endl; } int main() { uint8_t bVal = 123; print_bits<uint8_t>(bVal); int16_t iVal = 12345; print_bits<int16_t>(iVal); }Если Вы будете нумеровать их не с 1, а, как все нормальные люди, с нуля (т.е. на 1, 2, ..., 16), а (0, 1, 2, ..., 15), то можете воспользоваться простым, рабоче-крестьянским макросом bitRead. Просто, как мычание нулевой бит переменной а - bitRead(a, 0), первый - bitRead(a,1) и т.п. И не надо городить никакого огорода с самогонными функциями. Макрос простой как валенок, определён в arduino.h вот так
Спасибо всем за помощь и советы :)
Очень помогли!