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

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

06.04.2012, 09:50. Показов 5299. Ответов 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
3409 / 2181 / 354
Регистрация: 13.01.2012
Сообщений: 8,461
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
3409 / 2181 / 354
Регистрация: 13.01.2012
Сообщений: 8,461
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
3409 / 2181 / 354
Регистрация: 13.01.2012
Сообщений: 8,461
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
Ответ Создать тему
Новые блоги и статьи
Автозаполнение реквизита при выборе элемента справочника
Maks 27.03.2026
Программный код из решения ниже на примере нетипового документа "ЗаявкаНаРемонтСпецтехники" разработанного в конфигурации КА2. При выборе "Спецтехники" (Тип Справочник. Спецтехника), заполняется. . .
Сумматор с применением элементов трёх состояний.
Hrethgir 26.03.2026
Тут. https:/ / fips. ru/ EGD/ ab3c85c8-836d-4866-871b-c2f0c5d77fbc Первый документ красиво выглядит, но без схемы. Это конечно не даёт никаких плюсов автору, но тем не менее. . . всё может быть. . .
Автозаполнение реквизитов при создании документа
Maks 26.03.2026
Программный код из решения ниже размещается в модуле объекта документа, в процедуре "ПриСозданииНаСервере". Алгоритм проверки заполнения реализован для исключения перезаписи значения реквизита,. . .
Команды формы и диалоговое окно
Maks 26.03.2026
1. Команда формы "ЗаполнитьЗапчасти". Программный код из решения ниже на примере нетипового документа "ЗаявкаНаРемонтСпецтехники" разработанного в конфигурации КА2. В качестве источника данных. . .
Кому нужен AOT?
DevAlt 26.03.2026
Решил сделать простой ланчер Написал заготовку: dotnet new console --aot -o UrlHandler var items = args. Split(":"); var tag = items; var id = items; var executable = args;. . .
Отправка уведомления на почту при изменении наименования справочника
Maks 24.03.2026
Программная отправка письма электронной почты на примере изменения наименования типового справочника "Склады" в конфигурации БП3. Перед реализацией необходимо выполнить настройку системной учетной. . .
модель ЗдравоСохранения 5. Меньше увольнений- больше дохода!
anaschu 24.03.2026
Теперь система здравосохранения уменьшает количество увольнений. 9TO2GP2bpX4 a42b81fb172ffc12ca589c7898261ccb/ https:/ / rutube. ru/ video/ a42b81fb172ffc12ca589c7898261ccb/ Слева синяя линия -. . .
Midnight Chicago Blues
kumehtar 24.03.2026
Такой Midnight Chicago Blues, знаешь?. . Когда вечерние улицы становятся ночными, а ты не можешь уснуть. Ты идёшь в любимый старый бар, и бармен наливает тебе виски. Ты смотришь на пролетающие. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru