Как отправить несколько данных по последовательному каналу в одном байте?

В настоящее время я считываю 3 концевых выключателя и отправляю эти данные по последовательному.напишите, используя следующий код.

#include <SPI.h>
#include <Wire.h>
#include <arduino-timer.h>

//Define limit switch pins
#define LEFT_SWITCH_PIN 5
#define RIGHT_SWITCH_PIN 6
#define REAR_SWITCH_PIN 7

bool left_switch_state;
bool right_switch_state;
bool rear_switch_state;
bool switch_state_array[3] = {left_switch_state,right_switch_state,rear_switch_state};
int switch_pin_array[3] = {LEFT_SWITCH_PIN,RIGHT_SWITCH_PIN,REAR_SWITCH_PIN};

int send_status_state = 0;

void setup() {
    Wire.begin();
    Serial.begin(115200);
    status_timer.every(200, sendStatus);
}

void sendStatus() {
  if (send_status_state == 0) {
    getLimitSwitch();
  
    unsigned char buf[5];
    buf[0] = 'S';
    buf[1] = switch_state_array[0];
    buf[2] = switch_state_array[1];
    buf[3] = switch_state_array[2];
    buf[4] = '|';
    Serial.write(buf,5);
    send_status_state = 1;
    
  } 
}

void loop() {
    status_timer.tick();
  }

void getLimitSwitch()
{
  for (int i=0; i<3; i++)
  {
    switch_state_array[i] = digitalRead(switch_pin_array[i]);
  }
}
/*********************************************************************************************************
    END FILE
*********************************************************************************************************/

как вы можете видеть, в настоящее время я использую 3 байта для отправки состояний каждого концевого выключателя отдельно.

    buf[1] = switch_state_array[0];
    buf[2] = switch_state_array[1];
    buf[3] = switch_state_array[2];

Как я могу отправить все данные концевого выключателя в одном байте?

, 👍1


1 ответ


Лучший ответ:

5

Вам следует научиться использовать побитовые операторы. Это необходимо для того, чтобы делать то, что вы хотите.

Мы можем сохранить состояние каждого коммутатора в одном бите каждый. Для этого мы сначала определяем нашу глобальную переменную, которая будет содержать состояния переключения:

byte switch_states = 0;

Затем в getLimitSwitch() мы перебираем наши контакты. Результат digitalRead() всегда равен 0 и 1. Таким образом, мы можем взять это значение и немного сдвинуть его влево. Затем мы выполняем побитовые операции ИЛИ, чтобы поместить значение в нашу переменную switch_states:

void getLimitSwitch()
{
  for (int i=0; i<3; i++)
  {
    switch_states |= ( digitalRead(switch_pin_array[i]) << i );
  }
}

Затем вы можете отправить этот байт по последовательному каналу. Он может вместить до 8 состояний.

Serial.write(switch_states);

Самая интересная линия здесь

switch_states |= ( digitalRead(switch_pin_array[i]) << i );

Давайте приведем здесь пример: Предположим, что мы смотрим на вывод с индексом 2, и он ВЫСОКИЙ. Итак, у нас есть switch_states |= ( 1 << 2 ). Это соответствует следующему представлению в двоичном состоянии switch_states |= ( 0b00000001 << 2 ). << сдвигает битовый шаблон влево; в данном случае на 2 цифры. Таким образом, мы получаем switch_states |= 0b00000100;. Это равно switch_states = switch_states | 0b00000100;. Побитовый оператор ИЛИ | возвращает значение, в котором каждый бит равен 1, если соответствующий бит по крайней мере в одном из двух оперантов равен 1. Здесь мы используем это, чтобы собрать кусочки воедино.

Если контакты имеют состояния ВЫСОКИЙ,НИЗКИЙ,ВЫСОКИЙ, то результирующее значение будет равно 0b00000101, он же. 5 в десятичной дроби.


С другой стороны, вы можете захотеть расшифровать это значение. Как это делается, зависит от архитектуры (с использованием ПК, микроконтроллера,...). Но на Arduino вы можете проверить, чтобы штифт был ВЫСОКИМ с помощью этого:

if(received_states_variable & (1 << pin_index))

Примечание: Делая это

bool left_switch_state;
bool right_switch_state;
bool rear_switch_state;
bool switch_state_array[3] = {left_switch_state,right_switch_state,rear_switch_state};

в этом нет особого смысла. Вы инициализируете элементы массива только с помощью неявно инициализированных переменных false. Вам просто не нужны обычные переменные bool. Вы можете просто определить свой массив bool. Если вы хотите инициализировать его явно, просто используйте true или false напрямую:

bool switch_state_array[3] = {false, false, false};

или даже

bool switch_state_array[3] = {false};
,

"Это необходимо, чтобы делать то, что ты хочешь". Ну, есть также структура битового поля. Мне нравится широко использовать их в C, а затем в Rust мне говорят, что трансмутация-это плохо, и я должен чувствовать себя плохо., @AndreKR

Я не знаю Ржавчины и не знаю, почему это должно быть так плохо. Но вы правы. Вы также можете использовать структуры битовых полей. Возможно, вы хотите добавить еще один ответ с кратким объяснением того, как их использовать. Я лично использую битшифтинг, но для ОП и других знание всех вариантов может помочь в дальнейшем, @chrisl