Компания
STMicroelectronics экономит время разработчикам. Выпуская на рынок очередной продукт, предлагает готовое решение на его основе. Если вы видите наличие в микроконтроллере какой-то сложной периферии, например, USB или Ethernet будьте уверены, что есть набор готовых решений от ST на базе этой периферии. Тем не менее, вопросы по работе фирменного ПО встречаются.
В этой ситуации вполне разумным действием представляется упрощение исходного ПО с добавлением комментариев на русском языке. Собственно говоря, что инженеры компании "Промэлектроника" и сделали.
Стандартные приложения часто требуют связи с внешним персональным компьютером. Эта связь используется для ввода настроек в устройство и/или считывания данных, накопленных устройством за время работы. Десять лет назад в качестве такого интерфейса использовался COM-порт. Сейчас достаточно сложно найти персональный компьютер с таким интерфейсом. Да и не стоит. Разъём COM-порта не только не привлечёт покупателя оргтехники, но и отпугнёт его в большинстве случаев.
Для замены COM-порта придуман класс USB устройств, называемый CDC. Это виртуальный COM-порт. С точки зрения программиста ПК – он работает с тем же COM-портом. Однако данные передаются совершенно по иному физическому принципу. С точки зрения программиста микроконтроллера картина выглядит несколько сложнее. Для использования виртуального COM порта требуется изучение работы USB. Это достаточно сложный интерфейс. Основная сложность, как и основное достоинство – его универсальность. Поэтому описательная часть подключаемого устройства содержит много данных, которые стандартный программист микроконтроллеров не знает. Именно в этом месте на сцене появляется STMicroelectronics со своей библиотекой USB-Device. В ней описаны несколько видов USB-устройств. В частности, популярный USB virtual COM.
Пример, написанный на базе программы устройства USB virtual COM представляет собой мост USART<->USB. Достаточно корректно отключить USART и организовать обмен приложение<->USB (и забыть вообще про обмен с ПК через USART на всю оставшуюся жизнь). Вот тут на сцену выходят инженеры компании "Промэлектроника".
Несколько слов о полученном приложении. USB работает в своём векторе прерываний, поэтому код приложения выглядит следующим образом:
int main(void)
{
Set_USBClock();
USB_Interrupts_Config();
USB_Init();
while (1)
{
}
}
После всех инициализаций, до бесконечного цикла while(1) добавляете в приложение свой код. На выходе получается ваше приложение, содержащее стек обмена с ПК по USB. В приложении, написанном инженерами компании "Промэлектроника", USB работает следующим образом: при получении любого символа по USB VC приложение отправляет ответ «www.promelec.ru».
Как это работает. При получении данных по USB программа оказывается в процедуре, из файла USB_ENDP.C:
void EP3_OUT_Callback(void)
Главная задача этой процедуры – считать полученные данные из очереди USB (выделенное ОЗУ внутри периферии). Если это не сделать, USB не будет принимать данные в следующем фрейме. Считать очередь можно процедурой:
uint32_t USB_SIL_Read(uint8_t bEpAddr, uint8_t* pBufferPointer);
Указав конечную точку (EndPoint – понятие интерфейса USB) и буфер приёма, процедура произведёт считывание принятых данных и вернёт их размер в байтах. После этого Буфер приёма данных готов к приёму новой порции. Вероятно, что приложение пользователя потребует реакции на приём данных. Потому инженеры компании "Промэлектроника" в теле процедуры void EP3_OUT_Callback(void) добавили код, разрешающий отправку данных по USB.
Кроме прерывания приёма данных по USB приложение использует ещё 2 вида прерываний по USB: Start Of Frame (SOF) и окончание отправки данных по USB (процедура void EP1_IN_Callback (void))
Что такое SOF? Обмен данными по USB разбит на временные интервалы: фреймы. Деление времени на фреймы осуществляет HOST. В нашем случае – это ПК. Длительность фрейма – 1мс. Каждую миллисекунду HOST отправляет всем подключенным USB устройствам сигнал «начало фрейма» или, другими словами, SOF.
При получении данного сигнала, а в нашем случае это будет прерывание с вызовом процедуры void INTR_SOFINTR_Callback(void) устройство должно подготовить буферы обмена с USB. Если мы не считали данные – считать, если требуется отправить данные – поместить их в очередь отправки. В нашем случае, данные считываются в прерывании (описано выше), поэтому считывать их снова – не требуется. А вот отправка данных в очередь осуществляется именно в этом прерывании. Используя функцию:
uint32_t USB_SIL_Write(uint8_t bEpAddr, uint8_t* pBufferPointer, uint32_t wBufferSize);
с указанием конечной точки и области памяти, откуда требуется отправить данные, осуществится запись данных в очередь отправки USB. В течение одной миллисекунды данные уйдут в USB HOST, возникнет прерывание от USB «данные отправлены» c вызовом процедуры «void EP1_IN_Callback» (где приложение инженеров "Промэлектроники" опускает флажок «требуется отправить данные») и начнётся новый цикл обмена.
Вот так дружба компаний "Промэлектроника" и STMicroelectronics облегчает разработчику жизнь.
Описание построения преобразователя USB<->RS232 в новости от 3.07.12.