Jump to content

    

USB CDC +HAL. Как правильно обрабатывать переподключение?

Сгенерировал в CUBE проект USB CDC (библиотека HAL, контроллер STM32F103C8)

Завелось с полпинка, работает абсолютно без нареканий.

Одно но есть - с компом устройство общается через примитивный пока софт. Когда я перепрошиваю контроллер софт теряет связь с устройством. Это естественно и не вызывало удивления, пока я думал, что дело только в софте, который не обрабатывает ошибки. 

Однако, если перепрошить контроллер, а потом снова запустить софт - все равно нет подключения. Спасает только передергивание USB кабеля. 

Я так понял, что перепрошитое устройство должно давать какую-то команду не просто софту, а именно контроллеру USB в компьютере, чтобы "знакомство" прошло повторно?

Как это реализовать?

Инициализация USB у меня такая

 

void MX_USB_DEVICE_Init(void)
{
  /* USER CODE BEGIN USB_DEVICE_Init_PreTreatment */
  
  /* USER CODE END USB_DEVICE_Init_PreTreatment */
  
  /* Init Device Library, add supported class and start the library. */
  if (USBD_Init(&hUsbDeviceFS, &FS_Desc, DEVICE_FS) != USBD_OK)
  {
    Error_Handler();
  }
  if (USBD_RegisterClass(&hUsbDeviceFS, &USBD_CDC) != USBD_OK)
  {
    Error_Handler();
  }
  if (USBD_CDC_RegisterInterface(&hUsbDeviceFS, &USBD_Interface_fops_FS) != USBD_OK)
  {
    Error_Handler();
  }
  if (USBD_Start(&hUsbDeviceFS) != USBD_OK)
  {
    Error_Handler();
  }

  /* USER CODE BEGIN USB_DEVICE_Init_PostTreatment */
  
  /* USER CODE END USB_DEVICE_Init_PostTreatment */
}

 

Обмен в главном цикле такой

 

 while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
    referenceValue=GetTargetTemperature(TIME_POSITION);
		measurementValue=INFO_VAR.CurrentUpperThermoCouple;
		PID_out = pid_Controller(referenceValue, measurementValue);
		
		if (INFO_VAR.WORK_STATE==1)
		{
 		INFO_VAR.UpperFrontHeaterPOWER=PID_out;
	 	INFO_VAR.UpperRearHeaterPOWER=PID_out;
		}		
		InfoVarPrepare();
    CalculatePowerParametres();
		uint16_t len = strlen((const char*)UserRxBufferFS);  
    if(len > 0)
    {
      OptionsBufferDecode();
			InfoBufferCode();
   		CDC_Transmit_FS((uint8_t*)DataOut, sizeof(DataOut));      
      memset(UserRxBufferFS, 0, sizeof(UserRxBufferFS));

		
    }

 

Share this post


Link to post
Share on other sites
54 минуты назад, -=Женек=- сказал:

Я так понял, что перепрошитое устройство должно давать какую-то команду не просто софту, а именно контроллеру USB в компьютере, чтобы "знакомство" прошло повторно?

Как это реализовать?

Читать спецификацию USB на тему "Сигнализация подключения отключения USB-device".

Там узнаете, что для перезапуска энумерации со стороны USB-хоста, USB-device должен (если это FS/HS-устройство) понизить уровень на линии D+ (отключить подтяжку резистором например - зависит от схемы) на некоторое время, а затем - обратно повысить уровень на D+ (включить резистор подтяжки).

Share this post


Link to post
Share on other sites
4 minutes ago, jcxz said:

Читать спецификацию

Читать исходный вопрос. Если Вы думаете, что при перезапуске контроллера подтяжка не отключается - ну... Вы очень странно думаете.

 

Проблема, возможно, в том, что виндовс как-то неадекватно себя ведёт при исчезновении COM-порта. Когда-то давно (в эпоху WinXP/Win7) разбирались. Если устройство пропало, потом появилось, в этот порт ничего записать уже нельзя (что логично, в принципе). Но и после того, как его закроешь, он как-то странно открывалось. Самое лучшее, что придумали - писишный программист сразу же после исчезновения устройства закрывал порт, при подключении пытался открыть обратно. Ну либо костыль: "дрыгать" коннект со стороны железки, если этот порт никто не открывает в течении N секунд.

На win10 я с этой проблемой не сталкивался, вероятно, в майкрософте это поправили.

Share this post


Link to post
Share on other sites
1 час назад, esaulenka сказал:

Если устройство пропало, потом появилось, в этот порт ничего записать уже нельзя (что логично, в принципе). Но и после того, как его закроешь, он как-то странно открывалось.

Интересно,  что операционная система думала о программисте,  который пытается закрыть неоткрытый порт...

Share this post


Link to post
Share on other sites
15 минут назад, VladislavS сказал:

Интересно,  что операционная система думала о программисте,  который пытается закрыть неоткрытый порт...

Дескриптор-то остался, и его (и связанные с ним ресурсы) надо вернуть в систему. Так что вполне логично и правильно вызвать CloseHandle() для порта, который отвалился.

 

1 час назад, esaulenka сказал:

Если Вы думаете, что при перезапуске контроллера подтяжка не отключается - ну... Вы очень странно думаете.

Надо схему смотреть. Насколько я помню, у F103 нет встроенной подтяжки USB, и приходится делать внешнюю. Схемы бывают разные, с транзисторами и без. И в некоторых случаях приходится предпринимать специальные действия в программе, чтобы вызвать ре-енумерацию.

Share this post


Link to post
Share on other sites
1 час назад, esaulenka сказал:

Читать исходный вопрос. Если Вы думаете, что при перезапуске контроллера подтяжка не отключается - ну... Вы очень странно думаете.

Если Вы умеете видеть принципиальную схему автора на расстоянии, то Вы - Великий Ясновидец видимо. Я такими способностями не обладаю. :wink2:

А подтяжка может не отключаться при перезапуске МК по множеству причин. Достаточно хоть немного подумать (например: просто тупо стоит подтяжка всегда без управления от МК).

Это уже не говоря о том, что перезапуск МК может происходить очень быстро и если ТС даже не задумывался о состоянии подтяжки (что скорее всего так и есть), то у него при перезапуске эта подтяжка вообще может моргать на миллисекунды и USB-хост будет просто проигнорировать такое "отключение".

Цитата

Проблема, возможно, в том, что виндовс как-то неадекватно себя ведёт при исчезновении COM-порта. Когда-то давно (в эпоху WinXP/Win7) разбирались. Если устройство пропало, потом появилось, в этот порт ничего записать уже нельзя (что логично, в принципе). Но и после того, как его закроешь, он как-то странно открывалось.

Если COM-порт был открыт во время отключения USB-COM, то пока его не закроешь - он не будет работать. Но достаточно его закрыть и после этого можно открывать заново - и он должен открываться корректно.

Цитата

На win10 я с этой проблемой не сталкивался, вероятно, в майкрософте это поправили.

У меня на XP всё работает нормально - закрываю COM, потом открываю - и всё ок. Так что проблема думаю не в винде.

Share this post


Link to post
Share on other sites

Хм.. 

У меня внешнего управления подтяжкой нет. Плата -примитивная китайская отладочная.

Вижу три варианта

1. Не реализовано управление подтяжкой в самом контроллере

2. Наверное действительно во время ресета слишком мало времени проходит и кратковременное дерганье подтяжки ни на что не влияет.

3. На китайской плате между контроллером и usb стоит какая-то защита в 6ногом корпусе. Они ж разные бывают, может быть она и мешает управлению.

В общем, спасибо за наводку, приеду с дачи завтра - попробую.

Share this post


Link to post
Share on other sites
2 часа назад, -=Женек=- сказал:

3. На китайской плате между контроллером и usb стоит какая-то защита в 6ногом корпусе. Они ж разные бывают, может быть она и мешает управлению.

Почитайте, может и мешает, хотя по симптомам случай не ваш:

 

Share this post


Link to post
Share on other sites
5 часов назад, -=Женек=- сказал:

У меня внешнего управления подтяжкой нет. Плата -примитивная китайская отладочная.

Тогда надо ручками:

* при старте инициализируете ногу A12 как выход, переводите в 0 и ждёте немножко

* потом переключаете A12 в ANALOGINPUT, и вызываете инициализацию USB.

Share this post


Link to post
Share on other sites

Долго же ТС будет искать ногу с таким заковыристым обозначением - F103C8 в "нечеловеческих" корпусах не бывают ;-)

Share this post


Link to post
Share on other sites
5 минут назад, Obam сказал:

Долго же ТС будет искать ногу с таким заковыристым обозначением - F103C8 в "нечеловеческих" корпусах не бывают ;-)

Вы про A12? И в LQFP64, и даже в LQFP48 есть эта нога.

А, понял. Вы думали, что это номер ноги. Нет, это нога 12 порта A. Которая USB D+.

Share this post


Link to post
Share on other sites
59 minutes ago, AHTOXA said:

Тогда надо ручками:

* при старте инициализируете ногу A12 как выход, переводите в 0 и ждёте немножко

* потом переключаете A12 в ANALOGINPUT, и вызываете инициализацию USB.

Уже догадался. Но... неужели нельзя было сделать эту мелочь на аппаратном уровне? Нет, я не жалуюсь, мне просто не верится.

Share this post


Link to post
Share on other sites

Мало ли, может у вас в работе F103V8I - попробуй отличи ногу (шар) А12 от, на самом деле, PA12.

Share this post


Link to post
Share on other sites
1 час назад, Obam сказал:

Мало ли, может у вас в работе F103V8I - попробуй отличи ногу (шар) А12 от, на самом деле, PA12.

Может быть много чего, но в стартовом посте явно указан STM32F103C8. Так что ваша придирка мимо кассы.

Share this post


Link to post
Share on other sites

.А подскажите мне такую вещь.

У меня usb cdc, устройство, настроенное соответствующим образом, определяется  в компе как виртуальный ком порт. Но при этом обладает атрибутами usb - именем устройства например.

Скажите, как прочитать имя устройста, определяющегося как компорт?

У меня на компе проект в Embarcadero, в нем компонент TAdpComport (из пакета AsyncPro). Кто -то работал с таким? Как узнать имя устройства? Ну или может если кто не работал именно с таким компонентом, но подскажет куда копать? А то неохота просто по номеру компорта подключатся. Хочется поименовать устройство и чтоб имено его искал софт на компе.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this