STM32f107 USB VCP

Кто любит RISC в жизни, заходим, не стесняемся.
Ответить
Собутыльник Кота
Аватара пользователя
Сообщения: 2567
Зарегистрирован: Вт май 01, 2018 19:44:47

Сообщение VladislavS »

У тебя CDC класс. После прохождения енумерации полезные данные ходят через EP1. Принимаемые данные кладутся в прерываниях в приёмный буфер. Передаваемые Записываешь в EP1 c помощью WriteINEP и они сами уходят.
Реклама
Открыл глаза
Сообщения: 55
Зарегистрирован: Чт ноя 29, 2018 06:56:04

Сообщение Dimas6262 »

то есть передача в комп идет по прерыванию? чет я честно говоря не понял
Реклама
Собутыльник Кота
Аватара пользователя
Сообщения: 2567
Зарегистрирован: Вт май 01, 2018 19:44:47

Сообщение VladislavS »

Нет. По прерыванию приём с компа. В моём примере в этом же прерывании символ передаётся обратно чтобы эхо в терминале было. А так можешь когда хочешь передавать, только проверить что очередь отправки пуста.
Открыл глаза
Сообщения: 55
Зарегистрирован: Чт ноя 29, 2018 06:56:04

Сообщение Dimas6262 »

ну вот, видимо очередь не пустая, хотя через терминал вижу что все пришло, и второй раз не отправляет

Добавлено after 20 minutes 33 seconds:
Get_TX_Q_cnt этой функцией очередь проверять?

Добавлено after 41 minute 48 seconds:
вот такая картина
Вложения
Безымянный.jpg
(213.78 КБ) 445 скачиваний
Реклама
Эиком - электронные компоненты и радиодетали
Собутыльник Кота
Аватара пользователя
Сообщения: 2567
Зарегистрирован: Вт май 01, 2018 19:44:47

Сообщение VladislavS »

Там очередь создаётся только если отправляешь данных больше 64 байт. Например, один из дескрипторов 67 байт вроде как. На коротких сообщениях очередь не задействуется.

У тебя как организован обмен? Если запрос-ответ, то не надо ничего проверять, просто пишешь в ep1 с помощью WriteINEP. У тебя так эхо в терминале работает. Без разницы один байт или много ты в ответ будешь посылать. Попробуй для начала не эхо слать, а какое-нибудь слово, типа "Привет!".

Если инициатором обмена является само устройство, то надо проверить в каком состоянии конечная точка (или FIFO не помню) перед отправкой . Это RM надо почитать. Там не сложно должно быть.
Реклама
Открыл глаза
Сообщения: 55
Зарегистрирован: Чт ноя 29, 2018 06:56:04

Сообщение Dimas6262 »

void USB_CDC::EP1_OUT_Int(void)
{
uint32_t epint = USB_OTG_OUTEP(1)->DOEPINT;

if(epint & USB_OTG_DOEPINT_XFRC)
{
WriteINEP(0x01,buffusb,7);
}

USB_OTG_OUTEP(1)->DOEPINT = epint;
USB_OTG_OUTEP(1)->DOEPCTL |= (USB_OTG_DOEPCTL_CNAK | USB_OTG_DOEPCTL_EPENA);
};

вот процедура, с пк я отсылаю, принимаю и отправляю в ответ "привет", затем вышел в общий цикл, жду, отправляю еще с пк, принимаю ответ, попадаю на процедуру WriteINEP, она вся проходит, но на комп ничего не прилетает
Реклама
Собутыльник Кота
Аватара пользователя
Сообщения: 2567
Зарегистрирован: Вт май 01, 2018 19:44:47

Сообщение VladislavS »

Давай так. По приёму сообщения от компа в прерывании ставь флаг, что получил данные. А в основном цикле по наличию флага обрабатывай эти данные и отсылай ответ. Не чему там не работать. Эта же функция передаёт данные через ep0 при энумерации, а там они до 67 байт в моём примере.
Открыл глаза
Сообщения: 55
Зарегистрирован: Чт ноя 29, 2018 06:56:04

Сообщение Dimas6262 »

[uquote="VladislavS",url="/forum/viewtopic.php?p=3526455#p3526455"]Давай так. По приёму сообщения от компа в прерывании ставь флаг, что получил данные. А в основном цикле по наличию флага обрабатывай эти данные и отсылай ответ. Не чему там не работать. Эта же функция передаёт данные через ep0 при энумерации, а там они до 67 байт в моём примере.[/uquote]



https://dropmefiles.com/DXcw7
(проэкт)

все тоже самое
Собутыльник Кота
Аватара пользователя
Сообщения: 2567
Зарегистрирован: Вт май 01, 2018 19:44:47

Сообщение VladislavS »

Мне сейчас не на чем посмотреть. Может вечером гляну.

Сразу на будущее. Глобальный флаг, который меняется в прерывании, определять только с volatile. Поверь, это сэкономит много времени и нервов в будущем.
Собутыльник Кота
Аватара пользователя
Сообщения: 2567
Зарегистрирован: Вт май 01, 2018 19:44:47

Сообщение VladislavS »

Dimas6262, ты одну лишнюю строчку в USB_CDC::EP1_OUT_Int() раскомментировал. В твоём проекте возиться не буду. Немного свой поправил. Добавил сохранение размера принятых данных и пример обработки принимаемых данных в основном цикле. Пройдись синхронизацией по исходникам - всё увидишь.
Спойлер

Код: Выделить всё

const char hello[] = " Hello! ";
const char bye[] = " Good Bye! ";

int main()
{    
  // IsCommandReceived возвращает кол-во принятых в буфер usb_rx_buf данных
  for(;;)
  {
    if(usb.IsCommandReceived()) 
    {
      switch(usb_rx_buf[0])
      {
        case 'H':
        case 'h':
          usb.WriteINEP(1,(uint8_t *)hello,sizeof(hello)-1);        
          break;
        case 'G':
        case 'g':
          usb.WriteINEP(1,(uint8_t *)bye,sizeof(bye)-1);  
          break;          
        default:
          usb.WriteINEP(1,usb_rx_buf,1);
      }
      usb.ClearCommandReceived();
    }
  };
}
Работает как-то так
Изображение
333.zip
(176.48 КБ) 245 скачиваний
СпойлерПройдусь всё же по поводу работы со строками.
1. Зачем ты их так маниакально как unsigned char объявляешь? Классическая Си строка это массив char.
2. Строки, содержимое которых в процессе работы не меняется, определять как const. Они будут лежать себе мирно во flash, а не копироваться в RAM как сейчас.
3. При их объявлении и инициализации не надо указывать размер. Это лишняя работа и источник ошибок. Размер надо указывать только если ты потом будешь менять эту строку и нужно зарезервировать определённый размер для этого.
4. Для определения размера строки, которую ты определил как const char[] можно применять sizeof(). Он будет вычислен на этапе компиляции, а не так как у тебя strlen() в рантайме.
5. Не надо переопределять стандартные функции типа strlen и т.д. Во-первых, достаточно было просто сделать приведение типов, чтобы они заработали. Это в случае (char *) и (unsigned char *) совершенно бесплатно. Во-вторых, в программировании это называется велосипедостроение. Поверь, авторы стандартных библиотек написали эту функцию лучше тебя и даже без ошибок.
Давай, удачи!
Вложения
Untitled.png
(3.86 КБ) 853 скачивания
Открыл глаза
Сообщения: 55
Зарегистрирован: Чт ноя 29, 2018 06:56:04

Сообщение Dimas6262 »

[uquote="VladislavS",url="/forum/viewtopic.php?p=3527054#p3527054"]Dimas6262, ты одну лишнюю строчку в USB_CDC::EP1_OUT_Int() раскомментировал. В твоём проекте возиться не буду. Немного свой поправил. Добавил сохранение размера принятых данных и пример обработки принимаемых данных в основном цикле. Пройдись синхронизацией по исходникам - всё увидишь.
Спойлер

Код: Выделить всё

const char hello[] = " Hello! ";
const char bye[] = " Good Bye! ";

int main()
{    
  // IsCommandReceived возвращает кол-во принятых в буфер usb_rx_buf данных
  for(;;)
  {
    if(usb.IsCommandReceived()) 
    {
      switch(usb_rx_buf[0])
      {
        case 'H':
        case 'h':
          usb.WriteINEP(1,(uint8_t *)hello,sizeof(hello)-1);        
          break;
        case 'G':
        case 'g':
          usb.WriteINEP(1,(uint8_t *)bye,sizeof(bye)-1);  
          break;          
        default:
          usb.WriteINEP(1,usb_rx_buf,1);
      }
      usb.ClearCommandReceived();
    }
  };
}
Работает как-то так
Изображение
333.zip
СпойлерПройдусь всё же по поводу работы со строками.
1. Зачем ты их так маниакально как unsigned char объявляешь? Классическая Си строка это массив char.
2. Строки, содержимое которых в процессе работы не меняется, определять как const. Они будут лежать себе мирно во flash, а не копироваться в RAM как сейчас.
3. При их объявлении и инициализации не надо указывать размер. Это лишняя работа и источник ошибок. Размер надо указывать только если ты потом будешь менять эту строку и нужно зарезервировать определённый размер для этого.
4. Для определения размера строки, которую ты определил как const char[] можно применять sizeof(). Он будет вычислен на этапе компиляции, а не так как у тебя strlen() в рантайме.
5. Не надо переопределять стандартные функции типа strlen и т.д. Во-первых, достаточно было просто сделать приведение типов, чтобы они заработали. Это в случае (char *) и (unsigned char *) совершенно бесплатно. Во-вторых, в программировании это называется велосипедостроение. Поверь, авторы стандартных библиотек написали эту функцию лучше тебя и даже без ошибок.
Давай, удачи![/uquote]



все тоже самое даже с твоим кодом
Собутыльник Кота
Аватара пользователя
Сообщения: 2567
Зарегистрирован: Вт май 01, 2018 19:44:47

Сообщение VladislavS »

Тогда не там роешь.
Открыл глаза
Сообщения: 55
Зарегистрирован: Чт ноя 29, 2018 06:56:04

Сообщение Dimas6262 »

Да бред какой то, нигде ничего не написано про такую ерунду, как он так может только один раз отправить пакет любой длины, а потом как будто в очередь становится и даже не принимает
Собутыльник Кота
Аватара пользователя
Сообщения: 2567
Зарегистрирован: Вт май 01, 2018 19:44:47

Сообщение VladislavS »

Ты ещё не разобрался? Больше недели прошло. Вот смотри, энумерация, судя по всему, у тебя проходит. Энумерация это в основном запросы-ответы: дай мне тот дискриптор, теперь этот, а теперь опять первый и так много раз. В моём примере один из дискрипторов 67 байт, насколько помню. То есть, обмен данными любого размера работает. Передача через ep0 и ep1 осуществляется одной и той же функцией. Не чему там не работать.

Может всё же в кубе натыкать?
Открыл глаза
Сообщения: 55
Зарегистрирован: Чт ноя 29, 2018 06:56:04

Сообщение Dimas6262 »

а там не может быть что нибудь по схемотехнике?

Добавлено after 1 minute 20 seconds:
и после второй передачи порт занят
то есть даже принять не могу

Добавлено after 3 minutes 31 second:
каким образом можно все очереди нулить?
Собутыльник Кота
Аватара пользователя
Сообщения: 2567
Зарегистрирован: Вт май 01, 2018 19:44:47

Сообщение VladislavS »

Какой порт, что значит занят, какие очереди? Давай на одном языке общаться.
Открыл глаза
Сообщения: 55
Зарегистрирован: Чт ноя 29, 2018 06:56:04

Сообщение Dimas6262 »

[uquote="VladislavS",url="/forum/viewtopic.php?p=3535156#p3535156"]Какой порт, что значит занят, какие очереди? Давай на одном языке общаться.[/uquote]


сделал передачу на ПК, прослушиваю как ком порт через Serial Monitor Port, все пришло, затем прерываю связь Serial Monitor Port, делаю 2-ю передачу, пытаюсь подключится в программе, но говорит что порт занят, но по отладчику, мы никуда не прыгаем, то есть комп думает что я ему что то передаю, а сам процессор в это время ничего не делает, не заходит в прерываиние
Собутыльник Кота
Аватара пользователя
Сообщения: 2567
Зарегистрирован: Вт май 01, 2018 19:44:47

Сообщение VladislavS »

Причём тут микроконтроллер, если ты с маздаиной справиться не можешь...
Открыл глаза
Сообщения: 55
Зарегистрирован: Чт ноя 29, 2018 06:56:04

Сообщение Dimas6262 »

А по подключению к stm32f107 клавиатуры нет ни каких примеров?
Собутыльник Кота
Аватара пользователя
Сообщения: 2567
Зарегистрирован: Вт май 01, 2018 19:44:47

Сообщение VladislavS »

Какой клавиатуры?
Ответить

Вернуться в «ARM»