Привет всем датагорчанам-любителям МК! Сегодня мы рассмотрим двусторонний обмен между Java-приложением и микроконтроллером посредством Bluetooth. Заодно сделаем весёлую штуку: рисуем цветными пикселями в приложении и получаем такой же рисунок на матрице из адресуемой RGB-ленты.
Содержание статьи / Table Of Contents
   
Соберем устройство:
    • передающее значение освещённости Java-приложению на компьютере,
    • управляющее RGB-лентой, выбор конкретного светодиода которой и его цвета определяется Java-приложением.
Нам потребуются:Микроконтроллер ATmega328p (далее — «МК») с частотой тактирования 8 МГц. Bluetooth-модуль HC-05. RGB-лента WS2812B. Фоторезистор. Резистор на 1 кОм. Блок питания на 5 В (пойдёт от смартфона).
 представлена на Рисунке 1.
![Обмен данными между Java-приложением и МК. Часть 2. По воздуху, Bluetooth]()
Рисунок 1. Схема соединений устройства
Алгоритм работы устройства следующий: 
а) АЦП микроконтроллера в автоматическом режиме напряжение, величина которого отражает уровень освещенности на фоторезисторе, и передаёт полученное значение Java-приложению.   
б) При перемене цвета любого из 105 лэйблов в графическом интерфейсе Java-приложение передаёт соответствующую информацию МК для изменения цвета соответствующего светодиода RGB-ленты. 
 осуществляется измерением напряжения на выводе PC0 МК, соединённом с точкой между фоторезистором и резистором.
Параметры функционирования АЦП определяются кодом нижеприведённых файлов.
adc.h#ifndef ADC_H_
#define ADC_H_
#include <avr/io.h>
#include <avr/interrupt.h>
#define ADC_COUNTER_MAX         1000
void adcInit();
extern volatile unsigned char adcFlag;
extern volatile unsigned int adcCounter;
extern unsigned char adcPreviousValue;
#endif /* ADC_H_ */
 adc.c#include "adc.h"
volatile unsigned char adcFlag;
volatile unsigned int adcCounter;
unsigned char adcPreviousValue;
ISR(ADC_vect)
{
  adcCounter++;
  if(adcCounter == ADC_COUNTER_MAX) 
  {
    adcCounter = 0;
    adcFlag = 1; 
  }   
}
void adcInit()
{
  ADMUX = (1 << ADLAR);
  ADCSRA = (1 << ADEN) | (1 << ADSC) | (1 << ADATE) | (1 << ADIE) | (1 << ADPS2) | (1 << ADPS1) | (1 << ADPS0);	
}
Как видите:
• На каждое тысячное (значение макроопределения ADC_COUNTER_MAX) измерение в обработчике прерывания устанавливается в 1 флаг 
adcFlag. Реакция на это событие осуществляется в функции deviceControl, о чём — ниже. 
• Во избежание шума результат измерения выравнивается по левому краю (бит ADLAR регистра ADMUX). Далее, в deviceControl, считывается значение лишь старшего байта ADCH регистра данных АЦП. 
 происходит посредством ассемблер-кода, представленного ниже.
WS2812B.SSREG    = 0x3f    
OUTBIT  = 0
PORTB   = 0x05
  .text
    .global stripRefresh
    stripRefresh:
      movw   r26, r24
      movw   r24, r22
      in     r22, SREG
      cli
      in     r20, PORTB
      ori    r20, (1 << OUTBIT)
      in     r21, PORTB
      andi   r21, ~(1 << OUTBIT)
      ldi    r19, 7
      ld     r18, X+
     loop1:
      out    PORTB, r20
      lsl    r18
      brcs   L1
      out    PORTB, r21
      nop
      bst    r18, 7
      subi   r19, 1
      breq   bit8
      rjmp   loop1
     L1:
      nop
      bst    r18, 7
      subi   r19, 1
      out    PORTB, r21
      brne   loop1
     bit8:
      ldi    r19, 7
      out    PORTB, r20
      brts   L2
      nop
      out    PORTB, r21
      ld     r18, X+
      sbiw   r24, 1
      brne   loop1
      out    SREG, r22
      ret
     L2:
      ld     r18, X+
      sbiw   r24, 1
      out    PORTB, r21
      brne   loop1
      out    SREG, r22
      ret
  .end
  Принцип работы WS2812B, а также подробные пояснения к коду вы можете увидеть в 
первой части статьи.
происходит через модуль HC-05 посредством протокола UART, код которого представлен ниже.
Serial.h#ifndef SERIAL_H_
#define SERIAL_H_
#include <avr/io.h>
#include <avr/interrupt.h>
#include <stdbool.h>
#define UART_BAUDRATE   9600
#define FREQUENCY       8000000UL
#define UBRR_VALUE      FREQUENCY / 16 / UART_BAUDRATE - 1
void serialBegin();
void serialPrintln(const char* buff);
void serialSendByte(char symbol);
extern volatile uint8_t receivedByte[11];
extern bool receiveFlag;
#endif /* SERIAL_H_ */
 Serial.c#include "Serial.h"
volatile uint8_t receivedByte[11], byteNum = 0;
bool receiveFlag;
ISR(USART_RX_vect)
{
  receivedByte[byteNum] = UDR0;
  byteNum++;
  if(byteNum > 10)
  {
    byteNum = 0;
    receiveFlag = 1;
  }
}
void serialBegin()
{
  uint16_t ubrrValue = UBRR_VALUE;
  UBRR0H = (uint8_t)(ubrrValue >> 8);
  UBRR0L = (uint8_t)(ubrrValue);
  UCSR0B |= (1 << TXEN0) | (1 << RXEN0) | (1 << RXCIE0);
  UCSR0C |= (3 << UCSZ00);
}
void serialSendByte(char data)
{
  while (!(UCSR0A & (1 << UDRE0)));
  UDR0 = data;
}
void serialPrintln(const char* buff)
{
  while(*buff != '\0')
  {
    serialSendByte(*buff);
    buff++;
  }
  serialSendByte('\n');
}
Отличие от аналогичного кода в первой части статьи заключается лишь в количестве принимаемых байтов (11 против 4). Обусловлено это следующими причинами:
а) Введён однобайтный ключ, назначение которого будет пояснено позже.
б) Добавлен 1 байт для номера светодиода, цвет которого необходимо изменить.
в) Значение цвета разложено на сотни, десятки и единицы для каждой составляющей (красной, синей и зелёной).
 обусловлен кодом из файлов device.
device.h#ifndef DEVICE_H_
#define DEVICE_H_
#define F_CPU           8000000UL 
#include <util/delay.h>
#include <avr/io.h>
#include <string.h>
#include "Serial.h"
#include "adc.h"
#define STRIP_LENGTH    105
#define LEDS_NUM        (STRIP_LENGTH * 3)
#define STRIP_DDR       DDRB
#define STRIP_PIN       PB0
void deviceInit();
void deviceControl();
void stripOff();
void setLedColor(uint8_t* p_buf, uint8_t led, uint8_t red, uint8_t green, uint8_t blue);
extern void stripRefresh(uint8_t * ptr, uint16_t count);
extern uint8_t buf[LEDS_NUM];
#endif /* DEVICE_H_ */
 device.с#include "device.h"
unsigned char communicationFlag = 0;
uint8_t buf[LEDS_NUM];
uint8_t redColorValue, greenColorValue, blueColorValue, ledNum;
void deviceInit()
{
  serialBegin();  
  STRIP_DDR |= (1 << STRIP_PIN); 
  stripOff(); 
  adcInit();
  sei();
}  
void deviceControl()
{
  if(receiveFlag)
  {
    receiveFlag = 0;
    if(receivedByte[0] == 2) 
    {
      communicationFlag = 1;
    } 
    if(receivedByte[0] == 1) 
    {            
      ledNum = receivedByte[1];
      greenColorValue = (int)(receivedByte[2] * 100 + receivedByte[3] * 10 + receivedByte[4]);
      redColorValue = (int)(receivedByte[5] * 100 + receivedByte[6] * 10 + receivedByte[7]);
      blueColorValue = (int)(receivedByte[8] * 100 + receivedByte[9] * 10 + receivedByte[10]);
      setLedColor(buf, ledNum, redColorValue, greenColorValue, blueColorValue); 
      stripRefresh(buf, sizeof(buf));       
    }
  }
  if(communicationFlag)
  {
    if(adcFlag)
    {
      adcFlag = 0;
      unsigned char adcCurrentValue = (unsigned char)(ADCH * 100 / 255);
      if(adcPreviousValue != adcCurrentValue)
      {
        adcPreviousValue = adcCurrentValue;
        serialSendByte(adcCurrentValue);
      }
    }
  }
}
void stripOff()
{
  memset(buf, 0, sizeof(buf));
  stripRefresh(buf, sizeof(buf));
}
void setLedColor(uint8_t* p_buf, uint8_t led, uint8_t red, uint8_t green, uint8_t blue)
{
  uint16_t index = 3 * led;
  p_buf[index++] = red;
  p_buf[index++] = green;
  p_buf[index] = blue;
}
Коротко о каждой из функций:
1. В 
deviceInit() настраивается необходимая периферия: UART, АЦП и пин PB0, управляющий лентой.
2. Функции 
stripOff() и 
setLedColor() служат для выключения ленты и записи в буфер параметров цвета определённого светодиода, соответственно. 
3. В 
deviceControl() циклично опрашиваются три флага:
а) 
receiveFlag, сигнализирующий о размещении в массив 
receivedByte пакета данных, поступивших от Java-приложения. Нулевой элемент массива receivedByte[0]   содержит упоминавшийся выше ключ, в зависимости от значения которого происходит следующее:
• 1 —  из данных элементов receivedByte[2]–receivedByte[10] «склеиваются» значения зелёной, красной и синей составляющих цвета, в который затем и окрашивается светодиод с номером, хранящемся в receivedByte[1].      
• 2 — устанавливается в 1 флаг 
communicationFlag, что разрешает МК отправку значения напряжения Java-приложению. Данное значение отправляется приложением в самом начале работы лишь один раз и свидетельствует о его готовности принимать данные от МК.        
б) флаг 
adcFlag устанавливается в 1 обработчиком прерывания АЦП по завершению измерения. В этом случает происходит отправка значения напряжения при условии, что communicationFlag установлен в 1. 
Код приложения состоит из 5 классов, ответственных за:
• 
Frame — графически интерфейс,
• 
BluetoothClient, 
IncomingMessagesLoggingRunnable, 
DeviceDiscoveredLoggingCallback — обмен по протоколу Bluetooth, 
• 
Main — диспетчеризацию данных.
В конструкторе класса создаётся поле интерфейса (фрэйм), включающее в себя:
• 
Button «Scanning» и «Connect» для поиска bluetooth-устройства и соединения с ним, соответственно.  
• 
ComboBox для отражения списка найденных bluetooth-устройств.
• 105 
Label, имитирующих светодиоды RGB-ленты.
• 
Button «Color» для вызова цветовой палитры. 
• 
Label с надписью «Luminosity».
• 
ProgressBar, отражающий текущее значение напряжения на выводе PC0 МК, т.е. освещённости.   
![]()
Рисунок 2. Графический интерфейс приложения
Методы класса призваны:
1. 
actionPerformed() реагировать на нажатие кнопок:
• «Scanning» и «Connect» — установкой в 1 флагов scanningButtonFlag и connectButtonFlag, соответственно, реакция на что осуществляется в классе Main.   
• «Color» — вызовом цветовой палитры.
2. 
MouseListener() при нажатии левой клавиши мыши:
    • окрашивать в предварительно выбранный цвет Label, на который в данный момент установлен курсор  
    • устанавливать в 1 флаг sendFlag c дальнейшей реакцией в классе Main.
3. 
showMessageDialog() выдавать сообщение о соединении приложения с модулем HC-05.
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class Frame implements ActionListener {
    JLabel luminosityLabel;
    JProgressBar progressBar;
    Color customColor = new Color(215, 215, 215);
    Color currentColor;
    MouseListener ml;
    boolean scanningButtonFlag = false;
    boolean connectButtonFlag = false;
    boolean sendFlag = false;
    JFrame frame;
    JComboBox<String> comboBox;
    JButton scanningButton, connectButton, colorButton;
    Label[] label = new Label[105];
    int ledNum;
    int[] X = new int[]{
        30, 53, 76, 99, 122, 145, 168, 191, 214, 237, 260, 283, 306, 329, 352, 375, 398, 421, 444, 467, 490,        
        490, 467, 444, 421, 398, 375, 352, 329, 306, 283, 260, 237, 214, 191, 168, 145, 122, 99, 76, 53, 30,
        30, 53, 76, 99, 122, 145, 168, 191, 214, 237, 260, 283, 306, 329, 352, 375, 398, 421, 444, 467, 490,
        490, 467, 444, 421, 398, 375, 352, 329, 306, 283, 260, 237, 214, 191, 168, 145, 122, 99, 76, 53, 30,
        30, 53, 76, 99, 122, 145, 168, 191, 214, 237, 260, 283, 306, 329, 352, 375, 398, 421, 444, 467, 490
    };
    int[] Y = new int[]{
        170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170,
        193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193,
        216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, 216,
        239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239, 239,
        262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262
    };
    @Override
    public void actionPerformed(ActionEvent e) {
        if(e.getSource() == scanningButton) {
            scanningButtonFlag = true;
        }
        else if(e.getSource() == connectButton) {
            connectButtonFlag = true;
        }
        else if(e.getSource() == colorButton) {
            currentColor = JColorChooser.showDialog(colorButton,"Choose",Color.WHITE); 
        }
    }
    Frame() {
        ml = new MouseListener() {
            @Override
            public void mouseClicked(MouseEvent e) {
                for(int i = 0; i < 105; i++) {
                    if(e.getSource() == label[i]) {
                        label[i].setBackground(currentColor);
                        ledNum = i;
                        sendFlag = true;
                    }
                }
            }
            @Override
            public void mousePressed(MouseEvent e) {
                // TODO Auto-generated method stub
                
            }
            @Override
            public void mouseReleased(MouseEvent e) {
                // TODO Auto-generated method stub
                
            }
            @Override
            public void mouseEntered(MouseEvent e) {
                // TODO Auto-generated method stub
                
            }
            @Override
            public void mouseExited(MouseEvent e) {
                // TODO Auto-generated method stub
                
            }
        };
        frame = new JFrame("Bluetooth communication");
        frame.setSize(555, 560);
        frame.setLayout(null);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        scanningButton = new JButton("Scanning");
        scanningButton.setBounds(125, 20, 110, 30);
        scanningButton.setFont(new Font("Ink Free", Font.BOLD, 20));
        scanningButton.setFocusable(false);
        scanningButton.addActionListener(this);
        frame.add(scanningButton);
        connectButton = new JButton("Connect");
        connectButton.setBounds(125, 60, 110, 30);
        connectButton.setFont(new Font("Ink Free", Font.BOLD, 20));
        connectButton.setFocusable(false);
        connectButton.addActionListener(this);
        connectButton.setEnabled(false);
        frame.add(connectButton);
        comboBox = new JComboBox<>();
        comboBox.setBounds(275, 20, 130, 30);
        frame.add(comboBox);
        luminosityLabel = new JLabel("Luminosity");
        luminosityLabel.setBounds(230, 410, 150, 30);
        luminosityLabel.setForeground(Color.BLUE);
        luminosityLabel.setFont(new Font("Ink Free", Font.BOLD, 18));
        frame.add(luminosityLabel);
        progressBar = new JProgressBar(0, 0, 100);
        progressBar.setBounds(212, 440, 120, 20);
        progressBar.setForeground(Color.BLUE);
        frame.add(progressBar);
        colorButton = new JButton("Color");
        colorButton.setBounds(230, 300, 80, 30);
        colorButton.setFont(new Font("Ink Free", Font.BOLD, 20));
        colorButton.setFocusable(false);
        colorButton.setEnabled(false);
        colorButton.addActionListener(this);
        frame.add(colorButton);
        for(int i = 0; i < 105; i++) {
            label[i] = new Label();
            label[i].setBounds(X[i], Y[i], 20, 20);
            label[i].setFocusable(true);
            label[i].setBackground(customColor);
            frame.add(label[i]);
        }
        for(int i = 0; i < 105; i++) {
            label[i].addMouseListener(ml);
        }
        frame.setVisible(true);
    }
    void showMessageDialog(String message) {
        JOptionPane.showMessageDialog(frame, message);
    }
    
}
В данном классе создаётся экземпляр 
DDLC класса DeviceDiscoveredLoggingCallback и содержится лишь один метод 
startDiscovery(), обеспечивающий поиск bluetooth-устройств.
import javax.bluetooth.BluetoothStateException;
import javax.bluetooth.DiscoveryAgent;
import javax.bluetooth.DiscoveryListener;
import javax.bluetooth.LocalDevice;
public class BluetoothClient {
    
    DeviceDiscoveredLoggingCallback DDLC = new DeviceDiscoveredLoggingCallback();
    public void startDiscovery() throws BluetoothStateException, InterruptedException {
        DiscoveryAgent agent = LocalDevice.getLocalDevice().getDiscoveryAgent();
		agent.startInquiry(DiscoveryAgent.GIAC, DDLC);
		synchronized (BluetoothClient.class) {
			BluetoothClient.class.wait();
		}
    }
}
отвечает за приём данных от МК, для чего создаётся поток 
input. Поступающие данные сохраняются в массив 
buffer, после чего поднимается флаг 
receiveFlag. Реакция на последнее событие реализована в классе Main.
import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import javax.bluetooth.RemoteDevice;
import javax.microedition.io.StreamConnection;
public class IncomingMessagesLoggingRunnable implements Runnable {
    private StreamConnection connection;
	public boolean receiveFlag = false;
	int incomingData;
	byte buffer[] = new byte[1];
    public IncomingMessagesLoggingRunnable(StreamConnection connection) {
		this.connection = connection;
	}
    @Override
    public void run() {
        InputStream input = null;
		RemoteDevice device = null;
		try {
			input = new BufferedInputStream(connection.openInputStream());
			device = RemoteDevice.getRemoteDevice(connection);
		} catch (IOException e) {
			System.err.println("Listening service failed. Incoming messages won't be displayed.");
			e.printStackTrace();
			return;
		}
		while (true) {
			try {
				input.read(buffer);	
				incomingData = Byte.toUnsignedInt(buffer[0]);
				receiveFlag = true;
			} catch (IOException e) {
				System.err.println("Error while reading the incoming message.");
				e.printStackTrace();
			}
		}
    }
    
}
создаёт экземпляр 
IMLR класса IncomingMessagesLoggingRunnable,  и содержит следующие методы:
а) 
openConnection() осуществляет соединение приложения с HC-05, создавая при этом отдельный поток 
outputStream для передаваемых данных. Кроме того, метод запускает методы checkReceivedData() и sendData().
б) 
checkReceivedData() запускает задачу 
timerTask, которая при установке в 1 флага 
receiveFlag поднимает флаг 
dataReceivedFlag, реакция на что происходит в Main.    
в) 
sendData() отправляет микроконтроллеру 11 байтов с информацией о светодиоде, состояние которого необходимо изменить.
г) 
deviceDiscovered() сохраняет адреса и имена обнаруженных bluetooth-устройств в одноимённые массивы. 
д) 
inquiryCompleted() поднятием флага 
DDLCflag сигнализирует о завершении поиска bluetooth-устройств.   
import javax.bluetooth.DeviceClass;
import javax.bluetooth.DiscoveryListener;
import javax.bluetooth.LocalDevice;
import javax.bluetooth.RemoteDevice;
import javax.bluetooth.ServiceRecord;
import javax.microedition.io.Connector;
import javax.microedition.io.StreamConnection;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.nio.charset.StandardCharsets;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.Timer;
import java.util.TimerTask;
public class DeviceDiscoveredLoggingCallback implements DiscoveryListener {
    boolean DDLCflag = false;
    String[] name = new String[5];
    String[] address = new String[5];
    int counter = 0;
	StreamConnection connection;
	OutputStream outputStream;
	InputStreamReader inputStream;
	IncomingMessagesLoggingRunnable IMLR;
	public boolean dataReceivedFlag = false;
	byte[] toSendBytes = new byte[11];
	int receivedData;
    public void openConnection(String address) throws IOException {
		connection = (StreamConnection) Connector.open(address);
		
		if (connection == null) {
			System.err.println("Could not open connection to address: " + address);
			System.exit(1);
		}
		outputStream = connection.openOutputStream();
		ExecutorService service = Executors.newSingleThreadExecutor();
		IMLR = new IncomingMessagesLoggingRunnable(connection);
		service.submit(IMLR);
		checkReceivedData();
		toSendBytes[0] = 2;
		sendData();
	}
    public void checkReceivedData() {
		TimerTask timerTask = new TimerTask() {
            public void run() {
				if(IMLR.receiveFlag == true) {
					IMLR.receiveFlag = false;
					receivedData = IMLR.incomingData;					
					dataReceivedFlag = true;					
				}
			}
		};
		Timer timer = new Timer();
        timer.scheduleAtFixedRate(timerTask, 0, 200);
	}
    public void sendData() {
		try {
			outputStream.write(toSendBytes);
		} catch (IOException e1) {
			e1.printStackTrace();
		}
	}
    @Override
    public void deviceDiscovered(RemoteDevice btDevice, DeviceClass code) {
        address[counter] = btDevice.getBluetoothAddress();
		try {
			name[counter] = btDevice.getFriendlyName(false);
            counter++;
		} catch (IOException e) {
			System.err.println("Error while retrieving name for device [" + address + "]");
			e.printStackTrace();
		}
    }
    @Override
    public void inquiryCompleted(int arg0) {
        DDLCflag = true;
		synchronized (BluetoothClient.class) {
			BluetoothClient.class.notify();
		}
    }
    @Override
    public void serviceSearchCompleted(int arg0, int arg1) {
        // TODO Auto-generated method stub
        
    }
    @Override
    public void servicesDiscovered(int arg0, ServiceRecord[] arg1) {
        // TODO Auto-generated method stub
        
    }
    
}
В этом классе создаются экземпляры классов Frame и BluetoothClient.
Далее, в цикле опрашиваются флаги и в случае поднятия:
• 
scanningButtonFlag — запускается поиск bluetooth-устройств,
• 
DDLCflag —  выдаётся сообщение о завершении поиска, активируется кнопка «Connect» и деактивируется «Scanning», 
• 
ConnectButtonFlag — деактивируется кнопка «Connect» и активируется «Color», а также устанавливается соединение с выбранным bluetooth-устройством (в нашем случае — с HC-05),    
• 
sendFlag —  формируются и отправляются микроконтроллеру 11 байт со значениями ключа, номера и цвета светодиода. 
import java.io.IOException;
public class Main {
    public static void main(String[] args) throws InterruptedException, IOException {
        Frame f = new Frame();
        BluetoothClient BC = new BluetoothClient();
        while(true) {
            if(f.scanningButtonFlag == true) {
                f.scanningButtonFlag = false;
                BC.startDiscovery();
            }
            if(BC.DDLC.DDLCflag == true) {
                BC.DDLC.DDLCflag = false;
                for(int i = 0; i < 5; i++) {
                    if(BC.DDLC.address[i] != null) {
                        f.comboBox.addItem(BC.DDLC.name[i]);
                    }
                }
                f.showMessageDialog("scanning completed");
                f.connectButton.setEnabled(true);
                f.scanningButton.setEnabled(false);
            }
            if(f.connectButtonFlag == true) {
                f.connectButtonFlag = false;
                f.connectButton.setEnabled(false);                
                String address = BC.DDLC.address[f.comboBox.getSelectedIndex()];
                BC.DDLC.openConnection("btspp://" + address + ":1");
                f.colorButton.setEnabled(true);
            }
            if(f.sendFlag == true) {
                f.sendFlag = false;
                int ColorValue;
                byte key = 1, hundreds, tens, units;
                BC.DDLC.toSendBytes[0] = key;
                BC.DDLC.toSendBytes[1] = (byte)(f.ledNum);
                ColorValue = f.currentColor.getRed();
                hundreds = (byte)(ColorValue / 100);
                tens = (byte)((ColorValue - hundreds * 100) / 10);
                units = (byte)(ColorValue - hundreds * 100 - tens * 10);
                BC.DDLC.toSendBytes[2] = hundreds;
                BC.DDLC.toSendBytes[3] = tens;
                BC.DDLC.toSendBytes[4] = units;
                ColorValue = f.currentColor.getGreen();
                hundreds = (byte)(ColorValue / 100);
                tens = (byte)((ColorValue - hundreds * 100) / 10);
                units = (byte)(ColorValue - hundreds * 100 - tens * 10);
                BC.DDLC.toSendBytes[5] = hundreds;
                BC.DDLC.toSendBytes[6] = tens;
                BC.DDLC.toSendBytes[7] = units;
                ColorValue = f.currentColor.getBlue();
                hundreds = (byte)(ColorValue / 100);
                tens = (byte)((ColorValue - hundreds * 100) / 10);
                units = (byte)(ColorValue - hundreds * 100 - tens * 10);
                BC.DDLC.toSendBytes[8] = hundreds;
                BC.DDLC.toSendBytes[9] = tens;
                BC.DDLC.toSendBytes[10] = units;
                BC.DDLC.sendData();
            }
            if(BC.DDLC.dataReceivedFlag == true) {
                BC.DDLC.dataReceivedFlag = false;
                f.progressBar.setValue(BC.DDLC.receivedData);               
            }
            Thread.sleep(20);
        }
    }    
}
 
🎁
Исходники - kod.zip
 15.82 Kb ⇣ 16
    Наш файловый сервис предназначен для полноправных участников сообщества "Datagor Electronics".
    Для получения файла зарегистрируйтесь и войдите на сайт с паролем.
 
Камрад, рассмотри датагорские рекомендации
  🌼 Полезные и проверенные железяки, можно брать
  Опробовано в лаборатории редакции или читателями.