Форум программистов, компьютерный форум, киберфорум
C++ Builder
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск  
 
 
Рейтинг 4.73/26: Рейтинг темы: голосов - 26, средняя оценка - 4.73
11 / 11 / 2
Регистрация: 15.08.2011
Сообщений: 456

Обмен данными через ком порт в потоке

06.04.2012, 09:50. Показов 5461. Ответов 29
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Программа выполняется в потоке идёт обмен данными через ком порт с мк! При выполнении программа просто останавливается, не могу понять в чём дело. Может не правильно работую с потоком?
При нажатии кнопки на форме запускается конструктор.

C++
1
2
3
4
oid __fastcall TForm1::Robo_ONClick(TObject *Sender)
{
r = new Robo;
}
C++
1
2
3
4
5
6
7
Robo::Robo()
{
work=1;
myrobo=NULL;
myrobo=CreateThread(NULL, 0, MyroboThread, NULL, 0, NULL);
lsm = new LSM303DLH;
}
Сам поток
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
DWORD WINAPI MyroboThread(LPVOID)
{
r->synchronization();
r->robo_on();
 
 
while(work)
{
 
  r->radar_write();
 
  r->speed();
 
  r->cancel_emergency_stop();
 
  r->write_sensor();
 
  lsm->lsm_ask();
 
  r->read_data();
 
}
 
Form1->Message(12);
delete lsm;
delete r;
//CloseHandle(myrobo);
//myrobo=NULL;
return 0;
}
При нажатии на кнопки на форме завершаем поток
C++
1
2
3
4
5
6
7
8
9
void Robo::stop(void)
{
work=0;
}
 
void __fastcall TForm1::Robo_OFFClick(TObject *Sender)
{
r->stop();
}
Второй день мучаюсь, пистоле уже лежит рядом на столе!
0
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
06.04.2012, 09:50
Ответы с готовыми решениями:

Обмен данными через COM порт
Доброго времени суток. Требуется производить обмен данными с неким устройством через СОМ порт. Сейчас использую вот такие функции: ...

Обмен данными через COM порт
Нашел исходник программы для работы с com портом. Какие есть стандартные команды, чтобы получить хоть какой то ответ? А то что бы не...

Обмен данными через COM-порт
Всем доброго времени суток! Подскажите пожалуйста как передать введенные данные из компонента TexBox передать в COM-порт Дело в том что...

29
11 / 11 / 2
Регистрация: 15.08.2011
Сообщений: 456
10.04.2012, 08:16  [ТС]
Студворк — интернет-сервис помощи студентам
Цитата Сообщение от vxg Посмотреть сообщение
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
bool com_port::wr
(
    unsigned char *out, unsigned long sizeof_out,
    unsigned char *in, unsigned long * const sizeof_in
)
{
        unsigned long sizeof_out_real;
        unsigned long sizeof_in_max = *sizeof_in;
        return
        WriteFile(h, out, sizeof_out, &sizeof_out_real, 0) &&
        sizeof_out_real == sizeof_out &&
        ReadFile(h, in, sizeof_in_max, sizeof_in, 0);
}
Красиво написано. Вот только если например надо считать 20 байт, а в буфере только 5?
0
Модератор
 Аватар для vxg
3410 / 2182 / 354
Регистрация: 13.01.2012
Сообщений: 8,473
10.04.2012, 20:52
ожидайте хвост. рано или поздно он придет. а если не придет в течении таймаута функция вернет код ошибки.
0
11 / 11 / 2
Регистрация: 15.08.2011
Сообщений: 456
11.04.2012, 22:28  [ТС]
vxg если вам не сложно, покажите как вы дальше обрабатываете пришедшие байты.
я делаю это последовательно, не дождавшись прихода команды целиком, наверное это неправильно...
C++
1
2
3
4
5
6
7
8
9
10
11
12
void Robo::radar_read(void)
{
static unsigned char data=180;
unsigned char deg, dis, real, invert_deg;
 
deg=usec(c->read());    //читаем из ком порта
dis=calc_dis[c->read()]; //читаем из ком порта
*(ptr_m+deg)=dis;
 
// bla bla bla
 
}
0
12 / 10 / 1
Регистрация: 04.04.2012
Сообщений: 29
12.04.2012, 09:24
Не мучайся, сделай обмен по 1-му байту символами из таблицы ASCII:

C++
1
2
3
#define ACK  0x06 //все нормально
#define NAK  0x15 //ошибка
#define NUL  0x00 //начало
Цифры передавай так: десятичное 30 передавай как: 0x33 ждем АСК , 0x30 ждем АСК
тогда не перепутаешь 30 с символом '0'

В моей рабочей проге 90% - обработка ошибок , только 10% - реально рабочий код!

Добавлено через 19 минут
Вместо контроолера я пользуюсь rstest.exe для отладки, где брал не помню,
могу на мыло выслать.
0
11 / 11 / 2
Регистрация: 15.08.2011
Сообщений: 456
12.04.2012, 11:47  [ТС]
Не знаю, по одному байту наверное по трафику не пройду, попробую все варианты...
0
Модератор
 Аватар для vxg
3410 / 2182 / 354
Регистрация: 13.01.2012
Сообщений: 8,473
16.04.2012, 13:19
Цитата Сообщение от Korbofos Посмотреть сообщение
я делаю это последовательно, не дождавшись прихода команды целиком
я ожидаю когда придет весь пакет - как по другому? ведь часть информации отсутствует
0
11 / 11 / 2
Регистрация: 15.08.2011
Сообщений: 456
17.04.2012, 07:52  [ТС]
Цитата Сообщение от vxg Посмотреть сообщение
я ожидаю когда придет весь пакет - как по другому? ведь часть информации отсутствует
Я имел в пример на С как вы его ожидаете
я сделал так
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
37
38
39
40
41
42
43
44
45
void Robo::read_data(void)
{
 
c->read_from_port(nead_read_byte); //читаем данные из порта
 
while(*c->read_byte)            //если что-то пришло
 {
 
   if(*c->read_byte>=nead_read_byte)  //если в пришло больше байт чем
   nead_read_byte=0;                  //нужно, обнуляем счётчик
   else
   nead_read_byte-=*c->read_byte;
 
   if(!read_funct)
      {
       sw_funct=c->read();
       read_funct=1;
      }
   switch (sw_funct)
   {
   case 0:
   synchronization();
   break;
 
   case radar:
   if(*c->read_byte>=2) //если пришло нужное количество байт
    {
     radar_read();    //выполняем функцию
     read_funct=0;
    }
   else return;
   break;
 
   case sensor:
   if(*c->read_byte)
   {
    read_sensor(c->read());
    read_funct=0;
   }
   else return;
   break;
 //bla-bla  
  }
 
}
читаем байты из порта
C++
1
2
3
4
5
6
7
8
9
10
11
#define max(a, b) (((a) >= (b)) ? (a) : (b))
void Com::read_from_port(unsigned long read)
{
DWORD read_byte, temp;
ClearCommError(COMport, &temp, &comstat);
   if(comstat.cbInQue) //если пришёл байт
     {
      ReadFile(COMport, rx_buf+rx_count, max(read,comstat.cbInQue), &read_byte, NULL );
      rx_count+=read_byte;
     }
}
раздаю данные в функцию
C++
1
2
3
4
5
6
7
unsigned char Com::read(void)
{
unsigned char data=*ptr_rx_buf;
ptr_rx_buf++;
if(!--rx_count)ptr_rx_buf=&rx_buf[0];
return data;
}
0
Модератор
 Аватар для vxg
3410 / 2182 / 354
Регистрация: 13.01.2012
Сообщений: 8,473
17.04.2012, 10:02
Цитата Сообщение от Korbofos Посмотреть сообщение
пример на С как вы его ожидаете
в тех проектах которые я реализовывал делалось так:
1 если длина пакета известна (например, исходя из запроса нам может быть известно сколько данных придет), то я ожидал приема всего пакета функцией ReadFile. если пакет ожидаемого размера не мог быть получен в течении таймаута функция завершалась с ошибкой и программа считала это сбоем передачи.
2 если длина заголовка пакета известна и размер данных передается в этом заголовке (например, заголовок длиной в один байт в котором записана собственно длина пакета), то я ожидал приема заголовка известной длины функцией ReadFile после чего еще раз вызывал функцию ReadFile с указанием в качестве ожидаемого количества принимаемых байт извлеченную из заголовка длину. в случае если во время первого или второго вызова ReadFile запрошенное количество байт не было получено в течение таймаута функция завершалась с ошибкой и программа считала это сбоем передачи как и в первом варианте.
3 если пакет не имеет заголовка и его длина неизвестна (например, пакет ограничивается оговоренными в протоколе начальным и конечным спецсимволами или имеет известную структуру, например, число с десятичной точкой в виде текста начинающееся со знака (+/-) и заканчивающегося пробелом или вообще ничем не заканчивающееся если окончанием считается конец пакета определяемый по паузе между передаваемыми данными), то... вы попали на "наркоманский" протокол при котором придется вычитывать данные необычными способами. решение в лоб - читать по одному байту анализируя получающийся массив на полноту и при фиксации конца пакета запускать обработку данных. альтернативой побайтному чтению может быть (сам не пробывал) вычитывание из буфера порта ровно того количества байт которое пришло за последний сеанс связи так как это вроде бы (сам не разу не работал с comstat.cbInQue) делаете вы с последующей сборкой кусков по аналогии с побайтным чтением.
---
касательно вашего кода хотелось бы отметить что в функции read_data вызов функции read_from_port происходит один раз и не совсем понятно как это будет работать если информация придет разорваная на несколько кусочков. саму сборку кусочков в вашем коде объять мозгом не могу. функция read выглядит очень странной - возвращает всего один байт и выполняет внутри себя какието непостижимые манипуляции с указателем на какието буферы.
1
12 / 10 / 1
Регистрация: 04.04.2012
Сообщений: 29
17.04.2012, 21:09
Цитата Сообщение от Korbofos Посмотреть сообщение
Не знаю, по одному байту наверное по трафику не пройду, попробую все варианты...
Есть еще варианты с кольцевым буфером, когда поток-приемник читает по одному байту,
перемещает текущий указатель вперед (ptr++).
А основная программа читает до текущего значения .
Где-то в книжках про AVR было,найду - напишу.
1
11 / 11 / 2
Регистрация: 15.08.2011
Сообщений: 456
18.04.2012, 14:11  [ТС]
у меня в мк так и сделано
C
1
2
3
4
5
6
interrupt [USART1_RXC] void usart1_rx_isr(void)
{
rx_buffer[rx_wr_index++]=UDR1;
  if (rx_wr_index == RX_BUFFER_SIZE) rx_wr_index=0; 
  if (++rx_counter == RX_BUFFER_SIZE) rx_counter=0;
}
C
1
2
3
4
5
6
7
8
9
10
11
unsigned char rx_read (void)
{
unsigned char data;
while(!rx_counter);
data=rx_buffer[rx_rd_index++];
if (rx_rd_index == RX_BUFFER_SIZE) rx_rd_index=0;
#asm("cli")
--rx_counter;
#asm("sei")
return data;
}
C
1
2
3
  case RADAR:                     //1
   radar(rx_read());
   break;
Добавлено через 1 час 16 минут
Цитата Сообщение от vxg Посмотреть сообщение
касательно вашего кода хотелось бы отметить что в функции read_data вызов функции read_from_port происходит один раз и не совсем понятно как это будет работать если информация придет разорваная на несколько кусочков. саму сборку кусочков в вашем коде объять мозгом не могу. функция read выглядит очень странной - возвращает всего один байт и выполняет внутри себя какието непостижимые манипуляции с указателем на какието буферы.
Если данные приходят не полностью, выхожу из функции read_data
C++
1
2
3
4
5
6
7
8
9
10
11
12
c->read_from_port(nead_read_byte); 
if(*c->read_byte)//если что-то пришло
 
//------
case radar:
   if(*c->read_byte>=2) //если пришло нужное количество байт
    {
     radar_read();    //выполняем функцию
     read_funct=0;
    }
   else return; //если нет нужного количества байт, выхожу из функции read_data
   break;
а если нет, дочитываю данные в следующем цикле этой функцией read_from_port();
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
18.04.2012, 14:11

Обмен данными через COM- порт
Добрый день, пытаюсь освоить передачу данных. Отсылаю на мк скажем "1", приходит "1" и "-38" почему-то. Та же история...

Обмен данными через СОМ-порт
Помогите новичку, пожалуйста) Нужно написать программу, которая ловит нажатия клавиш(стрелок) и соответственно отправляет это все через...

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

Обмен данными с устройством через com-порт
Здравствуйте. Я работаю с Акип'ом и мне нужно считывать с него измерения. Проблема в том, что я не могу получить от него банальное имя,...

Как подключится к устройству через ком порт
Есть устройство, есть dll, h, lib... Как подключить к билдеру эти библиотеки? Как подключится к устройство через ком порт?


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

Или воспользуйтесь поиском по форуму:
30
Ответ Создать тему
Новые блоги и статьи
Часы электронные
Uhbif79 12.08.2026
Выкладываю программу часов. Программа позволяет: 1. Использовать системное время и дату, 2. Есть возможность вводить время и дату вручную. 3. Реализованы 2 будильника: начало и конец рабочего дня. . . .
Часы с будильником на основе класса QLCDNumber
Uhbif79 12.08.2026
Всем добрый день, выкладываю программу часов с будильником на основе класса QLCDNumber. Здесь я пробовал самостоятельно создавал классы, впервые столкнулся с видимостью переменной одного класса из. . .
Установка MinGW GCC 16.2 и CMake
8Observer8 10.08.2026
VK Видео: https:/ / vkvideo. ru/ video-240781534_456239017 YouTube: eY5-5PyI9NM Текстовая версия
Неделя из жизни имитационной модели склада: мои кривые руки растут, откуда надо
anaschu 10.08.2026
Неделя из жизни имитационной модели склада: как я почти написал неправильную логику и что с этим делать Работаю сейчас над учебно-рабочим проектом: строю в AnyLogic имитационную модель процессов. . .
Калькулятор для расчета родства
russiannick 07.08.2026
1. Задача: Создать калькулятор для расчета родства. Родственных связей существует 8 ступеней, такие как: p - отец P - мать q - муж Q - жена b - брат B - сестра s - сын S - дочь
Мир по моей воле
kumehtar 07.08.2026
Когда-то кажется, что всё просто. Ты весь такой светлый. Причиняешь добро. Борешься за справедливость в этом тёмном мире. Потом начинаешь замечать одну неприятную вещь. Почти каждый хороший. . .
Кредитный калькулятор
Maks 05.08.2026
Решение задачи по прикладной информатике средствами 1С. Задача: Напишите приложение-калькулятор, которое помогает рассчитывать параметры кредита для аннуитетного и дифференцированного видов. . .
У нас сейчас поговорку "Опять 25" нужно переделать на "Опять +35".
kumehtar 04.08.2026
С ностальгией вспоминаю времена моего детства, когда у нас и правда +25 - была максимальная температура летом. Раньше +25 °C реально казались вершиной жары, когда можно было весь день пропадать на. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru