[活动] 【APM32F411V Tiny Board测评】6.实现一个简易U盘TXT阅读器

[复制链接]
 楼主| yuyy1989 发表于 2024-5-13 21:06 | 显示全部楼层 |阅读模式
APM32F411的USB支持主机或从机模式
微信截图_20240513205344.png
接下来在OTGH_MSC这个例程的基础上增加LCD显示,U盘文件扫描和TXT文件读取功能
把上个帖子的LCD驱动移植过来,由于USB占用了原来的IO,需要换一下IO才行
  1. YUYY_HS12864G18B_DEV_Type lcd_dev;
  2. void spi_init()
  3. {
  4.     GPIO_Config_T GPIO_InitStructure;
  5.     SPI_Config_T  SPI_InitStructure;
  6.     RCM_EnableAHB1PeriphClock (RCM_AHB1_PERIPH_GPIOC);
  7.     RCM_EnableAPB1PeriphClock(RCM_APB1_PERIPH_SPI2);
  8.    
  9.     GPIO_ConfigPinAF(GPIOC, GPIO_PIN_SOURCE_3, GPIO_AF_SPI1);
  10.     GPIO_ConfigPinAF(GPIOC, GPIO_PIN_SOURCE_7, GPIO_AF_SPI1);
  11.    
  12.     GPIO_ConfigStructInit(&GPIO_InitStructure);
  13.     GPIO_InitStructure.pin = GPIO_PIN_3 | GPIO_PIN_7;
  14.     GPIO_InitStructure.speed = GPIO_SPEED_100MHz;
  15.     GPIO_InitStructure.mode = GPIO_MODE_AF;
  16.     GPIO_InitStructure.otype = GPIO_OTYPE_PP;
  17.     GPIO_InitStructure.pupd = GPIO_PUPD_NOPULL;
  18.     GPIO_Config(GPIOC, &GPIO_InitStructure);
  19.    
  20.     SPI_ConfigStructInit(&SPI_InitStructure);
  21.     SPI_InitStructure.direction = SPI_DIRECTION_1LINE_TX;
  22.     SPI_InitStructure.mode = SPI_MODE_MASTER;
  23.     SPI_InitStructure.length = SPI_DATA_LENGTH_8B;
  24.     SPI_InitStructure.polarity = SPI_CLKPOL_HIGH;
  25.     SPI_InitStructure.phase = SPI_CLKPHA_2EDGE;
  26.     SPI_InitStructure.nss = SPI_NSS_SOFT;
  27.     SPI_InitStructure.baudrateDiv = SPI_BAUDRATE_DIV_8;
  28.     SPI_InitStructure.firstBit = SPI_FIRSTBIT_MSB;
  29.     SPI_InitStructure.crcPolynomial = 7;
  30.     SPI_Config(SPI2, &SPI_InitStructure);
  31.     SPI_DisableCRC(SPI2);
  32.     SPI_DisableSSOutput(SPI2);
  33.     SPI_Enable(SPI2);
  34. }
  35. void lcd_spiwritebyte(SPI_T *spix,uint8_t byte)
  36. {
  37.     while (SPI_I2S_ReadStatusFlag(spix, SPI_FLAG_TXBE) == RESET);
  38.     SPI_I2S_TxData(spix, byte);
  39. }
  40. void lcd_init()
  41. {
  42.     GPIO_Config_T gpioConfigStruct;
  43.     RCM_EnableAHB1PeriphClock (RCM_AHB1_PERIPH_GPIOC);
  44.     GPIO_ConfigStructInit(&gpioConfigStruct);
  45.     gpioConfigStruct.mode = GPIO_MODE_OUT;
  46.     gpioConfigStruct.speed = GPIO_SPEED_100MHz;
  47.     gpioConfigStruct.pin = GPIO_PIN_4 | GPIO_PIN_5 | GPIO_PIN_6;
  48.     gpioConfigStruct.otype = GPIO_OTYPE_PP;
  49.     gpioConfigStruct.pupd = GPIO_PUPD_NOPULL;
  50.     GPIO_Config(GPIOC, &gpioConfigStruct);
  51.    
  52.     lcd_dev.cs.gpio = GPIOC;
  53.     lcd_dev.cs.pin = GPIO_PIN_4;
  54.     lcd_dev.rst.gpio = GPIOC;
  55.     lcd_dev.rst.pin = GPIO_PIN_5;
  56.     lcd_dev.a0.gpio = GPIOC;
  57.     lcd_dev.a0.pin = GPIO_PIN_6;
  58.     lcd_dev.spix = SPI2;
  59.     lcd_dev.spi_sendbyte_func = (YUYY_HS12864G18B_SpiWriteByteFunc_Type)lcd_spiwritebyte;
  60.    
  61.     YUYY_HS12864G18B_Init(&lcd_dev);
  62.     YUYY_HS12864G18B_ClearScreen(&lcd_dev);
  63.     YUYY_HS12864G18B_DisplayString8x16(&lcd_dev,0,0,0," APM32F411 TEST");
  64.     YUYY_HS12864G18B_DisplayString8x16(&lcd_dev,0,2,0,"TXT FILE READER");
  65.     YUYY_HS12864G18B_DisplayString8x16(&lcd_dev,0,4,0,"  Wait USB Dev");
  66.     YUYY_HS12864G18B_DisplayString8x16(&lcd_dev,0,6,0,"Code by yuyy1989");
  67.     YUYY_HS12864G18B_DisplayFinish(&lcd_dev);
  68. }
实现TXT文件扫描和内容显示
  1. #define MAX_TXT_NUM 10
  2. char filenames[MAX_TXT_NUM][14];
  3. uint8_t txt_num = 0;
  4. uint8_t select_index = 0;
  5. uint8_t filed_opened = 0;
  6. uint8_t file_read_end = 0;
  7. uint8_t file_buffer[80];
  8. uint8_t file_buffer_len = 0;
  9. char lcd_buffer[4][17];

  10. void yuyy_show_txt()
  11. {
  12.     uint8_t start_index = 0;
  13.     uint8_t i = 0;
  14.     YUYY_HS12864G18B_ClearScreen(&lcd_dev);
  15.     if(txt_num == 0)
  16.     {
  17.         YUYY_HS12864G18B_DisplayString8x16(&lcd_dev,0,0,0,"NO TXT FILES");
  18.         return;
  19.     }
  20.     if(!filed_opened)
  21.     {
  22.         if(txt_num > 4)
  23.         {
  24.             if(select_index == txt_num - 1 )
  25.                 start_index = select_index - 3;
  26.             else if(select_index > 2 )
  27.                 start_index = select_index - 2;
  28.         }
  29.         while(start_index < txt_num)
  30.         {
  31.             YUYY_HS12864G18B_DisplayString8x16(&lcd_dev,select_index == start_index?YUYY_FONT_DATAS_REVERSE:0,i*2,0,filenames[start_index]);
  32.             i += 1;
  33.             start_index += 1;
  34.         }
  35.     }
  36.     else
  37.     {
  38.         YUYY_HS12864G18B_DisplayString8x16(&lcd_dev,0,0,0,lcd_buffer[0]);
  39.         YUYY_HS12864G18B_DisplayString8x16(&lcd_dev,0,2,0,lcd_buffer[1]);
  40.         YUYY_HS12864G18B_DisplayString8x16(&lcd_dev,0,4,0,lcd_buffer[2]);
  41.         YUYY_HS12864G18B_DisplayString8x16(&lcd_dev,0,6,0,lcd_buffer[3]);
  42.     }
  43. }
  44. void yuyy_readbuffer_to_lcd()
  45. {
  46.     uint8_t i = 0,j = 0,k = 0;
  47.     uint32_t len = 0;
  48.     memset(lcd_buffer,0,68);
  49.     if(file_buffer_len == 0)
  50.     {
  51.         f_lseek(&file,0);
  52.         file_read_end = 0;
  53.         file_buffer_len = 0;
  54.     }
  55.     if(!file_read_end && file_buffer_len < 80)
  56.     {
  57.         if(f_read(&file, &file_buffer[file_buffer_len], 80-file_buffer_len, &len) == FR_OK)
  58.         {
  59.             if(len == 0 || len < 80-file_buffer_len)
  60.             {
  61.                 file_read_end = 1;
  62.             }
  63.             file_buffer_len += len;
  64.         }
  65.     }
  66.     while(j < 4)
  67.     {
  68.         i = 0;
  69.         while(i < 16 && k < file_buffer_len)
  70.         {
  71.             if(file_buffer[k]>0x19 && file_buffer[k] < 0x7F)
  72.             {
  73.                 lcd_buffer[j][i] = file_buffer[k];
  74.                 i += 1;
  75.             }
  76.             else if(file_buffer[k] == '\n' && i > 0)
  77.             {
  78.                 i = 16;
  79.             }
  80.             k += 1;
  81.         }
  82.         j += 1;
  83.     }
  84.     i = 0;
  85.     j = k;
  86.     while(i < k && j < 80)
  87.     {
  88.         file_buffer[i] = file_buffer[j];
  89.         i += 1;
  90.         j += 1;
  91.     }
  92.     file_buffer_len -= k;
  93. }
  94. void yuyy_file_index_change()
  95. {
  96.     if(!filed_opened)
  97.     {
  98.         select_index += 1;
  99.         if(txt_num > 0 && select_index > txt_num - 1)
  100.             select_index = 0;
  101.         yuyy_show_txt();
  102.     }
  103.     else
  104.     {
  105.         yuyy_readbuffer_to_lcd();
  106.         yuyy_show_txt();
  107.     }
  108. }
  109. void yuyy_file_open_back()
  110. {
  111.     if(txt_num == 0)
  112.         return;
  113.     if(!filed_opened)
  114.     {
  115.         if(f_open(&file, filenames[select_index], FA_READ) == FR_OK)
  116.         {
  117.             filed_opened = 1;
  118.             memset(file_buffer,0,80);
  119.             yuyy_readbuffer_to_lcd();
  120.             yuyy_show_txt();
  121.         }
  122.     }
  123.     else
  124.     {
  125.         if(f_close(&file) == FR_OK)
  126.         {
  127.             filed_opened = 0;
  128.             file_read_end = 0;
  129.             file_buffer_len = 0;
  130.             yuyy_show_txt();
  131.         }
  132.     }
  133. }
  134. void yuyy_scantxt()
  135. {
  136.     uint8_t len,i;
  137.     FRESULT res;
  138.         FILINFO fileinfo;
  139.         DIR dir;
  140.     res=f_opendir(&dir,"/");
  141.     if(res != FR_OK)
  142.         return;
  143.     memset(filenames,0,MAX_TXT_NUM*14);
  144.    
  145.     txt_num = 0;
  146.     while(1)
  147.     {
  148.         char* pstr;
  149.         res = f_readdir(&dir, &fileinfo);
  150.         if (res != FR_OK || fileinfo.fname[0] == 0 || txt_num == MAX_TXT_NUM)
  151.             break;                                                 
  152.         if(fileinfo.fattrib&AM_DIR)
  153.             continue;
  154.         len = strlen(fileinfo.fname);
  155.         if(len > 4 && strncasecmp(&fileinfo.fname[len-4],".TXT",4) == 0)
  156.             memcpy(filenames[txt_num++],fileinfo.fname,13);               
  157.     }
  158.     i = 0;
  159.     while(i < txt_num)
  160.     {
  161.         printf("%d: %s",i,filenames[i]);
  162.         i++;
  163.     }
  164. }
改写USB_HostUserApplication这个方法
  1. void USB_HostUserApplication(void)
  2. {
  3.     uint8_t status = gUsbHostAppStatus;
  4.     static uint8_t userAppState = USER_APP_INIT;

  5.     switch (status)
  6.     {
  7.         case USBH_APP_CONNECTION:
  8.             break;

  9.         case USBH_APP_DISCONNECTION:
  10.             userAppState = USER_APP_INIT;
  11.             YUYY_HS12864G18B_ClearScreen(&lcd_dev);
  12.             YUYY_HS12864G18B_DisplayString8x16(&lcd_dev,0,0,0," APM32F411 TEST");
  13.             YUYY_HS12864G18B_DisplayString8x16(&lcd_dev,0,2,0,"TXT FILE READER");
  14.             YUYY_HS12864G18B_DisplayString8x16(&lcd_dev,0,4,0,"  Wait USB Dev");
  15.             YUYY_HS12864G18B_DisplayString8x16(&lcd_dev,0,6,0,"Code by yuyy1989");
  16.             YUYY_HS12864G18B_DisplayFinish(&lcd_dev);
  17.             break;

  18.         case USBH_APP_READY:
  19.             switch (userAppState)
  20.             {
  21.                 case USER_APP_INIT:
  22.                     if (f_mount(&fatfs, "0:", 0) == FR_OK)
  23.                     {
  24.                         yuyy_scantxt();
  25.                         yuyy_show_txt();
  26.                     }
  27.                     userAppState = USER_APP_RUN;
  28.                     break;

  29.                 case USER_APP_RUN:
  30.                     if (!APM_PBGetState(BUTTON_KEY1))
  31.                     {
  32.                         YUYY_DelayMs(10);
  33.                         if (!APM_PBGetState(BUTTON_KEY1))
  34.                         {
  35.                             yuyy_file_index_change();
  36.                             while (!APM_PBGetState(BUTTON_KEY1));
  37.                         }
  38.                     }
  39.                     if (!APM_PBGetState(BUTTON_KEY2))
  40.                     {
  41.                         YUYY_DelayMs(10);
  42.                         if (!APM_PBGetState(BUTTON_KEY2))
  43.                         {
  44.                             yuyy_file_open_back();
  45.                             while (!APM_PBGetState(BUTTON_KEY2));
  46.                         }
  47.                     }
  48.                     break;
  49.             }
  50.             break;

  51.         default:
  52.             break;
  53.     }
  54. }
作为主机使用时需要短接开发板上的J11,才能通过USB输出5V

微信截图_20240512211718.png 微信截图_20240513210225.png
没有插入U盘时
微信截图_20240513210339.png
选择文件
482886145bad5f6101e893d4a5d61230 00_00_00-00_00_30.gif
打开文件查看内容
3dbd233a8dc4767055c35d10567a8161 00_00_00-00_00_30.gif

szt1993 发表于 2024-5-23 17:57 | 显示全部楼层
USB_OTG使用配置起来还是挺方便的,里面的协议格式能方便讲解一下嘛
您需要登录后才可以回帖 登录 | 注册

本版积分规则

认证:同飞软件研发工程师
简介:制冷系统单片机软件开发,使用PID控制温度

161

主题

815

帖子

10

粉丝
快速回复 在线客服 返回列表 返回顶部