В предыдущей части нашего урока мы создали проект и добавили в него две задачи для работы с шиной USB и библиотекой FATFS.
Вернёмся в наш проект и добавим несколько глобальных указателей и переменных
1 2 3 4 5 6 7 |
} struct_out; FATFS *fs; FIL MyFile; FRESULT res; uint32_t bytesWritten; uint8_t rtext[200]; uint8_t wtext[] = "USB Host Library : Mass Storage Example"; |
Вернёмся в функцию USB_Task02 и попытаемся открыть файл. В случае неудачи выведем соответствующее сообщение в терминальную программу, в случаи удачи — другое сообщение, а затем закроем файл
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
case MSC_APP_FILE_OPERATIONS: if (Appli_state == APPLICATION_READY) { //read and write if (f_open(&MyFile, "0:USBHost1.txt", FA_CREATE_ALWAYS | FA_WRITE) != FR_OK) { sprintf(str,"Cannot Open 'USBHost1.txt' file n"); HAL_UART_Transmit(&huart1,(uint8_t*)str,strlen(str),0x1000); } else { sprintf(str,"INFO : 'USBHost1.txt' is opened for writen"); HAL_UART_Transmit(&huart1,(uint8_t*)str,strlen(str),0x1000); f_close(&MyFile); } |
Поместим накопитель в разъём кабеля USB OTG, соберём код, прошьём контроллер и посмотрим результат в терминальной программе.
Если всё пройдёт нормально, то получим следующий результат
Попробуем что-нибудь записать в наш файл, соответственно до его закрытия
1 2 3 4 |
sprintf(str,"INFO : 'USBHost1.txt' is opened for writen"); HAL_UART_Transmit(&huart1,(uint8_t*)str,strlen(str),0x1000); res = f_write(&MyFile, wtext, sizeof(wtext), (void *)&bytesWritten); f_close(&MyFile); |
А после закрытия файла, если операция записи вызвала ошибку, выведем соответствующее сообщение в терминальную программу, а если прошла успешно, то другое сообщение
1 2 3 4 5 6 7 8 9 10 11 12 |
res = f_write(&MyFile, wtext, sizeof(wtext), (void *)&bytesWritten); f_close(&MyFile); if ((bytesWritten == 0) || (res != FR_OK)) { sprintf(str,"Cannot Write on the 'USBHost1.txt' file n"); HAL_UART_Transmit(&huart1,(uint8_t*)str,strlen(str),0x1000); } else { sprintf(str,"INFO: %lu bytes is written n",bytesWritten); HAL_UART_Transmit(&huart1,(uint8_t*)str,strlen(str),0x1000); } |
Соберём код, прошьём контроллер и посмотрим сначала результат в терминальной программе
Затем извлечём из разъёма кабеля FLASH-накопитель и поместим его в USB-порт ПК. Наш файл на месте
Откроем файл и убедимся, что содержимое файла также соответствует заданному в программе
Всё сходится, отлично!
Теперь попробуем программными средствами прочитать содержимое файла.
Сначала откроем файл для чтения, сначала заново скопировав имя файла в локальный массив, иначе путь почему-то теряется. Также не забываем перед открытием закрыть файл
1 2 3 4 5 6 7 8 9 10 11 12 |
sprintf(str,"INFO: %lu bytes is written n",bytesWritten); HAL_UART_Transmit(&huart1,(uint8_t*)str,strlen(str),0x1000); if (f_open(&MyFile, "0:USBHost1.txt", FA_READ) != FR_OK) { sprintf(str,"Cannot Open 'USBHost1.txt' file for read.n"); HAL_UART_Transmit(&huart1,(uint8_t*)str,strlen(str),0x1000); } else { sprintf(str,"INFO : 'USBHost1.txt' opened for readn"); HAL_UART_Transmit(&huart1,(uint8_t*)str,strlen(str),0x1000); } |
Добавим локальную переменную
1 2 |
struct_out *qstruct; uint16_t bytesread; |
И теперь попытаемся прочитать содержимое нашего файла
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
sprintf(str,"INFO : 'USBHost1.txt' opened for readn"); HAL_UART_Transmit(&huart1,(uint8_t*)str,strlen(str),0x1000); res = f_read(&MyFile, rtext, sizeof(rtext), (void *)&bytesread); if ((bytesread == 0) || (res != FR_OK)) { sprintf(str,"Cannot Read from the 'USBHost.txt' file n"); HAL_UART_Transmit(&huart1,(uint8_t*)str,strlen(str),0x1000); } else { sprintf(str,"INFO : Read Text : n"); HAL_UART_Transmit(&huart1,(uint8_t*)str,strlen(str),0x1000); sprintf(str,(char *)rtext); HAL_UART_Transmit(&huart1,(uint8_t*)str,strlen(str),0x1000); sprintf(str,"n"); HAL_UART_Transmit(&huart1,(uint8_t*)str,strlen(str),0x1000); } f_close(&MyFile); |
А затем сравним количество прочитанных и записанных байтов
1 2 3 4 5 6 7 8 9 10 11 |
f_close(&MyFile); if ((bytesread == bytesWritten)) { sprintf(str,"INFO : FatFs data compare SUCCESn"); HAL_UART_Transmit(&huart1,(uint8_t*)str,strlen(str),0x1000); } else { sprintf(str,"FatFs data compare ERRORn"); HAL_UART_Transmit(&huart1,(uint8_t*)str,strlen(str),0x1000); } |
Проверим ход операции чтения, для чего присоединим FLASH-накопитель к разъёму кабеля USB OTG, соберём код, прошьём контроллер и посмотрим результат в терминальной программе
Вернёмся в наш код и закомментируем пока работу с файлом USBHost1.txt
/*
//read and write
...
*/
state = MSC_APP_EXPLORER;
Теперь попробуем поработать с длинными именами, а также с длинными файлами (по содержимому).
Для этого скопируем на наш FLASH-накопитель ещё два файла — один с коротким именем, но с большим содержимым, а другой — также с большим содержимым, но ещё и с длинным именем
Объявим несколько глобальных неоптимизируемых переменных
1 2 3 |
uint8_t wtext[] = "USB Host Library : Mass Storage Example"; __IO uint16_t i=0, i1=0; __IO uint32_t f_size = 0; |
Также объявим пару глобальных массивов
1 2 3 |
char str_out[32] = {}; char str_usart[512] = {0}; uint8_t sect[512]; |
Добавим ещё одну функцию для чтения файлов с длинным содержимым добавим ещё одну функцию для чтения файлов с длинным содержимым
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 |
/* USER CODE BEGIN 4 */ //-------------------------------------------------------------- FRESULT ReadLongFile(void) { uint16_t bytesread; f_size = MyFile.obj.objsize; sprintf(str_usart,"fsize: %lurn",(unsigned long)f_size); HAL_UART_Transmit(&huart1,(uint8_t*)str_usart,strlen(str_usart),0x1000); do { if(f_size<512) { i1=f_size; } else { i1=512; } f_size-=i1; f_read(&MyFile,sect,i1,(UINT *)&bytesread); for(i=0;i<bytesread;i++) { HAL_UART_Transmit(&huart1,sect+i,1,0x1000); } } while(f_size>0); HAL_UART_Transmit(&huart1,(uint8_t*)"rn",2,0x1000); return FR_OK; } //--------------------------------------------------------------- |
В функции USB_Task02 после закомментированного кода добавим код чтения файла с длинным содержанием, но с коротким именем
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
*/ //read long file if(f_open(&MyFile,"0:F74x.txt",FA_READ)!=FR_OK) { sprintf(str,"Cannot Open 'F74x.txt' file for write.n"); HAL_UART_Transmit(&huart1,(uint8_t*)str,strlen(str),0x1000); Error_Handler(); } else { sprintf(str,"fname: %srn","F74x.txt"); HAL_UART_Transmit(&huart1,(uint8_t*)str,strlen(str),0x1000); ReadLongFile(); f_close(&MyFile); } |
Соберём код, прошьём контроллер, вернём FLASH-Drive в USB OTG-кабель, и посмотрим результат в терминальной программе
Файл полностью считался.
Теперь попробуем аналогично прочитать файл не только с большим содержимым, но ещё и с длинным именем.
Сначала закомментируем код чтения предыдущего файла
/*
if(f_open(&MyFile,"0:F74x.txt",FA_READ)!=FR_OK)
...
f_close(&MyFile);
}
*/
Прочитаем содержимое файла в терминальную программу
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
*/ //read longname file if(f_open(&MyFile,"0:stm32f746 Reference Manual.txt",FA_READ)!=FR_OK) { sprintf(str,"Cannot Open 'stm32f746 Reference Manual.txt' file for write.n"); HAL_UART_Transmit(&huart1,(uint8_t*)str,strlen(str),0x1000); Error_Handler(); } else { sprintf(str,"fname: %srn","stm32f746 Reference Manual.txt"); HAL_UART_Transmit(&huart1,(uint8_t*)str,strlen(str),0x1000); ReadLongFile(); f_close(&MyFile); } |
Благодаря определённым изменениям в обновлённой библиотеке FATFS нам теперь не нужно проводить дополнительные мероприятия по организации дополнительного буфера для чтения файлов с длинными именами.
Соберём код, прошьём контроллер и посмотрим результат в терминальной программе
Файл также полностью прочитан.
Теперь аналогично закомментируем участок кода, связанный с чтением данного файла.
Отключим FLASH-накопитель, подключим его к ПК и скопируем на него ещё несколько файлов и папок с файлами (также и с длинными именами, но не с кириллицей в именах и расширениях, так как кириллица — это вообще отдельная и нелёгкая тема)
Вернёмся в код и добавим в функцию USB_Task02 несколько локальных переменных
1 2 3 4 5 |
uint16_t bytesread; DIR dir; FILINFO fileInfo; DWORD fre_clust, fre_sect, tot_sect; uint8_t result; |
Теперь уже в другом кейсе попробуем вывести некоторую полезную информацию о нашем FLASH-накопителе, в том числе и его файловую структуру (только корневую)
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 |
case MSC_APP_EXPLORER: HAL_UART_Transmit(&huart1,(uint8_t*)"rn",2,0x1000); result = f_opendir(&dir, "/"); if (result == FR_OK) { while(1) { result = f_readdir(&dir, &fileInfo); if (result==FR_OK && fileInfo.fname[0]) { HAL_UART_Transmit(&huart1,(uint8_t*)fileInfo.fname,strlen((char*)fileInfo.fname),0x1000); if(fileInfo.fattrib&AM_DIR) { HAL_UART_Transmit(&huart1,(uint8_t*)" [DIR]",7,0x1000); } } else break; HAL_UART_Transmit(&huart1,(uint8_t*)"rn",2,0x1000); } f_closedir(&dir); f_getfree("/", &fre_clust, &fs); sprintf(str,"fre_clust: %lurn",fre_clust); HAL_UART_Transmit(&huart1,(uint8_t*)str,strlen(str),0x1000); sprintf(str,"n_fatent: %lurn",fs->n_fatent - 2); HAL_UART_Transmit(&huart1,(uint8_t*)str,strlen(str),0x1000); sprintf(str,"fs_ssize: %drn",fs->ssize); HAL_UART_Transmit(&huart1,(uint8_t*)str,strlen(str),0x1000); sprintf(str,"fs_csize: %drn",fs->csize); HAL_UART_Transmit(&huart1,(uint8_t*)str,strlen(str),0x1000); sprintf(str,"csize: %drn",fs->ssize * fs->csize); HAL_UART_Transmit(&huart1,(uint8_t*)str,strlen(str),0x1000); tot_sect = (fs->n_fatent - 2) * fs->csize; sprintf(str,"tot_sect: %lurn",tot_sect); HAL_UART_Transmit(&huart1,(uint8_t*)str,strlen(str),0x1000); fre_sect = fre_clust * fs->csize; sprintf(str,"fre_sect: %lurn",fre_sect); HAL_UART_Transmit(&huart1,(uint8_t*)str,strlen(str),0x1000); sprintf(str, "%lu KB total drive space.rn%lu KB available.rn", fre_sect/2, tot_sect/2); HAL_UART_Transmit(&huart1,(uint8_t*)str,strlen(str),0x1000); } state = MSC_APP_END; |
Соберём код, прошьём контроллер, присоединим FLASH-накопитель к отладочной плате с помощью кабеля USB OTG и посмотрим результат в терминальной программе
Вся самая важная информация о файловой системе на нашем накопителе, а также и его корневая файловая структура видна. Можно, конечно, также вывести информацию о содержимом каждой папки, и подпапки, но это мы оставим на будущее.
Итак, в данном занятии мы научились пользоваться аппаратной поддержкой шины USB HS, а именно классом USB HOST MSC, причём с использованием операционной системы реального времени FREERTOS, а также закрепили на практике данные знания при работе с реальным USB FLASH-накопителем с использованием библиотеки FATFS.
Всем спасибо за внимание!
Предыдущая часть Программирование МК STM32 Следующий урок
Отладочную плату можно приобрести здесь 32F746G-DISCOVERY
Смотреть ВИДЕОУРОК (нажмите на картинку)
Добавить комментарий