2 / 2 / 0
Регистрация: 04.11.2013
Сообщений: 101
1

Нежелательное обнуление счётчика в цикле при достижении значений 4077, 8157. Последовательный порт. Метод Read()

29.10.2018, 09:07. Показов 3452. Ответов 16
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Доброго времени суток!

Читаю порт в цикле по три байта, все отлично.
Нужно выводить номера измерений (одно измерение - три байта). Для этого вывожу номер каждого прохода цикла, но каждый раз после числа 4077 происходит обнуление счётчика. Дальше идёт нормально, всего 15000, доходит до самого конца, т.е. на выходе вижу 1...4077 1...10920. Иногда сброс происходит на числе 8157.
Пробовал ставить разный размер буферов ReadBufferSize и WriteBufferSize - результат тот же.

Сам цикл:

C#
1
2
3
4
int count = serialPort1.BytesToRead;
byte[] byteArray = new byte[count];
serialPort1.Read(byteArray, 0, count);
for (int i = 0; i <= count-3; i = i + 3) {}
Вывожу i, собственно с ним и проблемы. Если это число обнуляется, значит происходит выход из цикла, если правильно понимаю.

Прошу Вашей помощи! Спасибо.
0
Лучшие ответы (1)
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
29.10.2018, 09:07
Ответы с готовыми решениями:

Нежелательное обнуление переменных в цикле
Dim j, x, y, z, k As Integer j = 0 k = 0 y = 0 For i = 0 To...

Обнуление логического поля по достижении определённой даты
Добрый день, имеется в наличии простейшая БД, состоящая преимущественно из таблиц. В одной таблице...

Обнуление счетчика
Подскажите, плиз чайнику, можно ли обнулить счетчик? Если запись испорчена, можно ли возобновить...

Как запретить уменьшение формы при достижении определённых значений?
Нужно запретить ресайзить форму, если её размеры достигли определённых значений. Нужно, чтобы...

16
Эксперт .NET
17685 / 12871 / 3365
Регистрация: 17.09.2011
Сообщений: 21,136
29.10.2018, 22:11 2
Лучший ответ Сообщение было отмечено Usaga как решение

Решение

Не расчитывайте на свойство BytesToRead - оно возвращает количество байт во входящем буфере на момент его вызова. Это количество может увеличиться.
Так же не рассчитывайте на то, что метод Read запишет то количество байт, которое вы указали - на деле может быть меньше.
Проверяйте возвращаемое значение - в нем будет фактически записанное кол-во байт.

Если вы читаете по 3 байта, то держите один массив на 3 элемента и в цикле вызывайте Read пока он не заполнится.
1
2 / 2 / 0
Регистрация: 04.11.2013
Сообщений: 101
30.10.2018, 14:09  [ТС] 3
kolorotur, большое спасибо!
А можно вот это немного подробнее: "Проверяйте возвращаемое значение - в нем будет фактически записанное кол-во байт."?
0
Эксперт .NET
17685 / 12871 / 3365
Регистрация: 17.09.2011
Сообщений: 21,136
30.10.2018, 14:15 4
Цитата Сообщение от Teterichev Посмотреть сообщение
А можно вот это немного подробнее
C#
1
2
3
// В переменной received будет храниться фактически записанное количество байтов в byteArray.
// received <= count
int received = serialPort1.Read(byteArray, 0, count);
Добавлено через 1 минуту
Например, если вам нужно заполнить массив на 1024 байтов, то правильный код заполнения будет не таким:
C#
1
2
byte[] buffer = new byte[1024];
serialPort1.Read(buffer, 0, buffer.Length);
А таким:
C#
1
2
3
4
byte[] buffer = new byte[1024];
int received = 0;
while (received < buffer.Length)
   received += serialPort1.Read(buffer, received, buffer.Length - received);
1
2 / 2 / 0
Регистрация: 04.11.2013
Сообщений: 101
31.10.2018, 09:30  [ТС] 5
kolorotur, я правильно понимаю, что массив buffer, это дополнительный массив к существующему byteArray?
0
Эксперт .NET
17685 / 12871 / 3365
Регистрация: 17.09.2011
Сообщений: 21,136
31.10.2018, 09:33 6
Цитата Сообщение от Teterichev Посмотреть сообщение
массив buffer, это дополнительный массив к существующему byteArray?
Нет, это я его просто так в примере обозвал — печатать меньше
Главное не инициализируйте byteArray значением свойства BytesToRead.
Делайте его фиксированного размера — в зависимости от потребностей.
1
2 / 2 / 0
Регистрация: 04.11.2013
Сообщений: 101
31.10.2018, 14:02  [ТС] 7
kolorotur, сделал как Вы писали, но похоже как-то не так.

C#
1
2
3
4
5
6
7
8
byte[] byteArray = new byte[1024[;
int received = 0;
while (received < bytesArray.Lenght)
{
  received += serialPort1.Read(byteArray, received, byteArray - received);
  richTextBox1.AppendTaxt(BitConverter.ToString(byteArray));
  richTexrBox2.AppendText(received.ToString() + " ");
}
На выходе первый richTextBox содержит элементы нашего массива, а второй это:
1024 1024 1024 1008 1009 1024 1024 1024 1024 992 993 1024 1024 1024 1024 992 993 1024 1024 1024 1024 976 977 1024 1024 1024 664
0
Эксперт .NET
17685 / 12871 / 3365
Регистрация: 17.09.2011
Сообщений: 21,136
31.10.2018, 14:07 8
Цитата Сообщение от Teterichev Посмотреть сообщение
похоже как-то не так.
Код наверное где-то в цикле вызывается?
Ну и скопируйте фактический код, а не переписывайте на форум вручную.
1
2 / 2 / 0
Регистрация: 04.11.2013
Сообщений: 101
01.11.2018, 07:11  [ТС] 9
kolorotur, нет, код вызывается просто на событии приема. Скопировать, к сожалению, не могу, таковы ограничения, постарался все проверить на ошибки.

Вот весь код:

C#
1
2
3
4
5
6
7
8
9
10
11
private void serialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
  byte[] byteArray = new byte[1024];
  int received = 0;
  while (received < bytesArray.Lenght)
  {
    received += serialPort1.Read(byteArray, received, byteArray - received);
    richTextBox1.AppendText(BitConverter.ToString(byteArray));
    richTexrBox2.AppendText(received.ToString() + " ");
  }
}
0
Эксперт .NET
17685 / 12871 / 3365
Регистрация: 17.09.2011
Сообщений: 21,136
01.11.2018, 09:11 10
Teterichev, приведенный код опять не скомпилируется, но вывод вроде как в порядке.
Что смущает?
1
2 / 2 / 0
Регистрация: 04.11.2013
Сообщений: 101
01.11.2018, 09:35  [ТС] 11
kolorotur, все также:

На выходе первый richTextBox содержит элементы нашего массива, а второй это:
1024 1024 1024 1008 1009 1024 1024 1024 1024 992 993 1024 1024 1024 1024 992 993 1024 1024 1024 1024 976 977 1024 1024 1024 664

Добавлено через 21 секунду
kolorotur, все также:

На выходе первый richTextBox содержит элементы нашего массива, а второй это:
1024 1024 1024 1008 1009 1024 1024 1024 1024 992 993 1024 1024 1024 1024 992 993 1024 1024 1024 1024 976 977 1024 1024 1024 664
0
Эксперт .NET
17685 / 12871 / 3365
Регистрация: 17.09.2011
Сообщений: 21,136
01.11.2018, 09:40 12
Цитата Сообщение от Teterichev Посмотреть сообщение
На выходе первый richTextBox содержит элементы нашего массива, а второй это
Так а в чем проблема-то?
Ну да, второй текст содержит количества считанных из порта байтов. И?
1
2 / 2 / 0
Регистрация: 04.11.2013
Сообщений: 101
01.11.2018, 09:51  [ТС] 13
kolorotur, да, прошу прощения, все верно. Просто изначально была задача выводить номер каждого измерения (одно измерение - три байта) пока идёт передача данных. Вот и подумал что это взамен моего цикла.

Получается, что мне теперь вместо переменной count в цикле for (которая содержит BytesToRead, первый пост) нужно просто использовать нашу переменную received?
0
Эксперт .NET
17685 / 12871 / 3365
Регистрация: 17.09.2011
Сообщений: 21,136
01.11.2018, 10:16 14
Цитата Сообщение от Teterichev Посмотреть сообщение
изначально была задача выводить номер каждого измерения (одно измерение - три байта)
То есть надо просто считать сколько раз по три байта пришло на порт?
0
2 / 2 / 0
Регистрация: 04.11.2013
Сообщений: 101
01.11.2018, 10:20  [ТС] 15
kolorotur, да, именно так. Я делал просто в цикле k = k + 1, а когда обнаружил оглашенную выше проблему, стал просто выводить i.
0
Эксперт .NET
17685 / 12871 / 3365
Регистрация: 17.09.2011
Сообщений: 21,136
01.11.2018, 10:32 16
Teterichev, ну уменьшите размер буфера до трех байт и всего делов (если хотите частое обновление):
C#
1
2
3
4
5
6
7
8
9
byte[] buffer = new byte[3];
int dataCount = 0;
private void serialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
  int received = 0;
  while (received < buffer.Lenght)
    received += serialPort1.Read(buffer, received, buffer.Length - received);
  dataCount++;
}
В переменной dataCount будет ваш счетчик.
1
2 / 2 / 0
Регистрация: 04.11.2013
Сообщений: 101
02.11.2018, 09:53  [ТС] 17
kolorotur, я встроил этот код в свой, где находится главный буфер (использую его, так как не знаю сколько байт будет принято, знаю только что меньше 5КБ). Все работает, но опять до достижения того самого значения 4077 переменной i, только теперь происходит не сброс значения, а остановка программы с исключением System.IO.IOException "Операция ввода/вывода была прервана из-за завершения потока команд по запросу приложения", в строке:

C#
1
received += serialPort1.Read(buffer, received, buffer.Length - received);
Вот весь код программы:

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
byte[] buffer = new byte[3];
int dataCount = 0;
private void serialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
//Использую данный метод, так как не знаю точной длины посылки
int count = serialPort1.BytesToRead;
byte[] byteArray = new byte[count];
serialPort1.Read(byteArray, 0, count);
for (int i = 0; i <= count-3; i = i + 3) 
{
  int firstByte, secondByte, thirdByte;
  firstByte = byteArray[i];
  secondByte = byteArray[i + 1];
  thirdByte = byteArray[i + 2];
  //Эти три байта должны быть определенного вида
  //Если условия не выполняются (повреждение байта), происходит смещения на байт
  if (firstByte == 12)
  {
    int result1, result2, result3;
    result1 = firstByte * 10;  
    result2 = secondByte * 20;  
    result3 = thirdByte * 30;  
    textBox1.AppendText(dataCount.ToString() + " " + result1.ToString() + " " + result2.ToString() + " " + result3.ToString() + "\r\n");
  }
  else
  {
    i = i + 1;
    textBox1.AppendText("Смещение на один байт" + "\r\n");
  }
  //Ваш код
  int received = 0;
  while (received < buffer.Lenght)
    received += serialPort1.Read(buffer, received, buffer.Length - received);
  dataCount++;
  }
}
0
02.11.2018, 09:53
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
02.11.2018, 09:53
Помогаю со студенческими работами здесь

Сделать неактивными элементы навигации при достижении предельных значений
Здраствуйте! помогите мне пожалуйта решить проблему! вот что я хочу сделать: у меня есть набор...

Обнуление счётчика $result
Как обнулить автоинкримент в $result - переменная, которая содержит в себе информацию, вытащенную...

Обнуление счётчика по условию
Всем привет! Подскажите как правильно написать условие. Есть таблица,которая постоянно обновляется,...

Обнуление счетчика, сортировка
Покажите пример , как можно вывести кол-во перестановок, которые были использованные при...

Обнуление счетчика ОВЕН СИ8
Здравствуйте! проблема у меня такая: у меня подключен к скаде СИ8, и мне нужно вести учет...

Обнуление счетчика активации Windows 7
RETAIL версия Windows 7 (не активированная) за 15 дней до окончания срока использования обновлена...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
17
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru