返回列表 发新帖我要提问本帖赏金: 100.00元(功能说明)

[活动专区] 【AT-START-F405测评】6.实现简易的U盘TXT阅读器

[复制链接]
 楼主| yuyy1989 发表于 2024-5-4 11:21 | 显示全部楼层 |阅读模式
官方例程提供了一个基础的USB存储设备读写例程,接下来在这个例程的基础上实现一个简易的TXT阅读器,功能如下:
插入U盘后列出U盘中的TXT文件,点击按键选择文件,长按打开文件显示文件内容,
文件打开后,点击按键翻页,长按关闭文件返回文件列表
打开msc_only_fat32这个例程 ,添加之前的LCD驱动到例程中
  1. YUYY_HS12864G18B_DEV_Type lcd_dev;
  2. #define LCD_A0_PIN    GPIO_PINS_4
  3. #define LCD_A0_GPIO_PORT    GPIOB
  4. #define LCD_RST_PIN    GPIO_PINS_6
  5. #define LCD_RST_GPIO_PORT    GPIOB
  6. #define LCD_CS_PIN    GPIO_PINS_7
  7. #define LCD_CS_GPIO_PORT    GPIOB
  8. void wk_spi1_init(void)
  9. {
  10.   /* add user code begin spi1_init 0 */

  11.   /* add user code end spi1_init 0 */

  12.   gpio_init_type gpio_init_struct;
  13.   spi_init_type spi_init_struct;

  14.   crm_periph_clock_enable(CRM_SPI1_PERIPH_CLOCK, TRUE);
  15.   gpio_default_para_init(&gpio_init_struct);
  16.   spi_default_para_init(&spi_init_struct);

  17.   /* add user code begin spi1_init 1 */

  18.   /* add user code end spi1_init 1 */

  19.   /* configure the SCK pin */
  20.   gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_MODERATE;
  21.   gpio_init_struct.gpio_out_type = GPIO_OUTPUT_PUSH_PULL;
  22.   gpio_init_struct.gpio_mode = GPIO_MODE_MUX;
  23.   gpio_init_struct.gpio_pins = GPIO_PINS_3;
  24.   gpio_init_struct.gpio_pull = GPIO_PULL_NONE;
  25.   gpio_init(GPIOB, &gpio_init_struct);

  26.   gpio_pin_mux_config(GPIOB, GPIO_PINS_SOURCE3, GPIO_MUX_5);

  27.   /* configure the MOSI pin */
  28.   gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_MODERATE;
  29.   gpio_init_struct.gpio_out_type = GPIO_OUTPUT_PUSH_PULL;
  30.   gpio_init_struct.gpio_mode = GPIO_MODE_MUX;
  31.   gpio_init_struct.gpio_pins = GPIO_PINS_5;
  32.   gpio_init_struct.gpio_pull = GPIO_PULL_NONE;
  33.   gpio_init(GPIOB, &gpio_init_struct);

  34.   gpio_pin_mux_config(GPIOB, GPIO_PINS_SOURCE5, GPIO_MUX_5);

  35.   /* configure param */
  36.   spi_init_struct.transmission_mode = SPI_TRANSMIT_HALF_DUPLEX_TX;
  37.   spi_init_struct.master_slave_mode = SPI_MODE_MASTER;
  38.   spi_init_struct.frame_bit_num = SPI_FRAME_8BIT;
  39.   spi_init_struct.first_bit_transmission = SPI_FIRST_BIT_MSB;
  40.   spi_init_struct.mclk_freq_division = SPI_MCLK_DIV_8;
  41.   spi_init_struct.clock_polarity = SPI_CLOCK_POLARITY_HIGH;
  42.   spi_init_struct.clock_phase = SPI_CLOCK_PHASE_2EDGE;
  43.   spi_init_struct.cs_mode_selection = SPI_CS_SOFTWARE_MODE;
  44.   spi_init(SPI1, &spi_init_struct);

  45.   spi_enable(SPI1, TRUE);

  46.   /* add user code begin spi1_init 2 */

  47.   /* add user code end spi1_init 2 */
  48. }
  49. void lcd_spiwritebyte(spi_type *spix,uint8_t byte)
  50. {
  51.     while(spi_i2s_flag_get(spix, SPI_I2S_TDBE_FLAG) == RESET);
  52.     spi_i2s_data_transmit(spix,byte);
  53. }
  54. void lcd_show_welcom()
  55. {
  56.     YUYY_HS12864G18B_ClearScreen(&lcd_dev);
  57.     YUYY_HS12864G18B_DisplayString8x16(&lcd_dev,0,0,0," AT32F405 TEST");
  58.     YUYY_HS12864G18B_DisplayString8x16(&lcd_dev,0,2,0,"TXT FILE READER");
  59.     YUYY_HS12864G18B_DisplayString8x16(&lcd_dev,0,4,0,"  Wait USB Dev");
  60.     YUYY_HS12864G18B_DisplayString8x16(&lcd_dev,0,6,0,"Code by yuyy1989");
  61. }
  62. void lcd_init()
  63. {
  64.     gpio_init_type gpio_init_struct;
  65.     gpio_default_para_init(&gpio_init_struct);
  66.     crm_periph_clock_enable(CRM_GPIOB_PERIPH_CLOCK, TRUE);

  67.     /* add user code begin gpio_config 1 */

  68.     /* add user code end gpio_config 1 */

  69.     /* gpio output config */
  70.     gpio_bits_set(GPIOB, LCD_A0_PIN | LCD_RST_PIN | LCD_CS_PIN);

  71.     gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_MODERATE;
  72.     gpio_init_struct.gpio_out_type = GPIO_OUTPUT_PUSH_PULL;
  73.     gpio_init_struct.gpio_mode = GPIO_MODE_OUTPUT;
  74.     gpio_init_struct.gpio_pins = LCD_A0_PIN | LCD_RST_PIN | LCD_CS_PIN;
  75.     gpio_init_struct.gpio_pull = GPIO_PULL_NONE;
  76.     gpio_init(GPIOB, &gpio_init_struct);
  77.    
  78.     wk_spi1_init();
  79.    
  80.     lcd_dev.cs.gpio = LCD_CS_GPIO_PORT;
  81.     lcd_dev.cs.pin = LCD_CS_PIN;
  82.     lcd_dev.a0.gpio = LCD_A0_GPIO_PORT;
  83.     lcd_dev.a0.pin = LCD_A0_PIN;
  84.     lcd_dev.rst.gpio = LCD_RST_GPIO_PORT;
  85.     lcd_dev.rst.pin = LCD_RST_PIN;
  86.     lcd_dev.spix = SPI1;
  87.     lcd_dev.spi_sendbyte_func = (YUYY_HS12864G18B_SpiWriteByteFunc_Type)lcd_spiwritebyte;
  88.    
  89.     YUYY_HS12864G18B_Init(&lcd_dev);
  90.     lcd_show_welcom();
  91. }
实现按键点击和长按的识别,这里使用1ms的定时器对按键按下状态计数实现去抖和单击长按的识别,在主循环中ms_ticked == 1时调用AppButtonLoop()并重新将ms_ticked 置0
  1. void wk_tmr6_init(void)
  2. {
  3.     crm_periph_clock_enable(CRM_TMR6_PERIPH_CLOCK, TRUE);
  4.     tmr_base_init(TMR6, 999, 215);
  5.     tmr_cnt_dir_set(TMR6, TMR_COUNT_UP);
  6.     tmr_period_buffer_enable(TMR6, FALSE);

  7.     /* configure primary mode settings */
  8.     tmr_primary_mode_select(TMR6, TMR_PRIMARY_SEL_RESET);

  9.     /* configure overflow event */
  10.     tmr_overflow_request_source_set(TMR6, TRUE);

  11.     tmr_counter_enable(TMR6, TRUE);
  12.     /* add user code begin tmr6_init 2 */
  13.     tmr_interrupt_enable(TMR6,TMR_OVF_INT,TRUE);
  14.     /* add user code end tmr6_init 2 */
  15.     nvic_irq_enable(TMR6_GLOBAL_IRQn, 0, 0);
  16. }
  17. uint8_t ms_ticked = 0;
  18. uint16_t led_conut = 0;
  19. void AppLepLoop()
  20. {
  21.     if(led_conut > 0)
  22.         led_conut -= 1;
  23.     if(led_conut == 0)
  24.     {
  25.         led_conut = 1000;
  26.         at32_led_toggle(LED2);
  27.         at32_led_toggle(LED3);
  28.         at32_led_toggle(LED4);
  29.     }
  30. }
  31. uint16_t button_down_count = 0;
  32. void AppButtonLoop()
  33. {
  34.     if(at32_button_state() != RESET)
  35.     {
  36.         button_down_count += 1;
  37.     }
  38.     else
  39.     {
  40.         if(button_down_count > 20 && button_down_count < 500)
  41.         {
  42.             USBH_DEBUG("button clicked");
  43.             yuyy_button_clicked();
  44.         }
  45.         button_down_count = 0;
  46.     }
  47.     if(button_down_count == 1000)
  48.     {
  49.         USBH_DEBUG("button long press");
  50.         yuyy_button_longpressed();
  51.     }
  52. }
  53. void AppMsTick(void)
  54. {
  55.     ms_ticked = 1;
  56. }
微信截图_20240504111605.png
实现U盘中TXT文件的扫描
  1. #define MAX_TXT_NUM 10
  2. char filenames[MAX_TXT_NUM][14];
  3. uint8_t txt_num = 0;
  4. void yuyy_scantxt()
  5. {
  6.     uint8_t len,i;
  7.     FRESULT res;
  8.         FILINFO fileinfo;
  9.         DIR dir;
  10.     res=f_opendir(&dir,"/");
  11.     if(res != FR_OK)
  12.         return;
  13.     memset(filenames,0,MAX_TXT_NUM*14);
  14.     txt_num = 0;
  15.     while(1)
  16.     {
  17.         char* pstr;
  18.         res = f_readdir(&dir, &fileinfo);
  19.         if (res != FR_OK || fileinfo.fname[0] == 0 || txt_num == MAX_TXT_NUM)
  20.             break;                                                 
  21.         if(fileinfo.fattrib&AM_DIR)
  22.             continue;
  23.         len = strlen(fileinfo.fname);
  24.         if(len > 4 && memcmp(&fileinfo.fname[len-4],".TXT",4) == 0)
  25.             memcpy(filenames[txt_num++],fileinfo.fname,13);               
  26.     }
  27.     i = 0;
  28.     while(i < txt_num)
  29.     {
  30.         USBH_DEBUG("%d: %s",i,filenames[i]);
  31.         i++;
  32.     }
  33. }
显示文件列表和文件内容
  1. uint8_t select_index = 0;
  2. uint8_t filed_opened = 0;
  3. uint8_t file_read_end = 0;
  4. uint8_t file_buffer[80];
  5. uint8_t file_buffer_len = 0;
  6. char lcd_buffer[4][17];

  7. void yuyy_show_txt()
  8. {
  9.     uint8_t start_index = 0;
  10.     uint8_t i = 0;
  11.     YUYY_HS12864G18B_ClearScreen(&lcd_dev);
  12.     if(txt_num == 0)
  13.     {
  14.         YUYY_HS12864G18B_DisplayString8x16(&lcd_dev,0,0,0,"NO TXT FILES");
  15.         return;
  16.     }
  17.     if(!filed_opened)
  18.     {
  19.         if(txt_num > 4)
  20.         {
  21.             if(select_index == txt_num - 1 )
  22.                 start_index = select_index - 3;
  23.             else if(select_index > 2 )
  24.                 start_index = select_index - 2;
  25.         }
  26.         while(start_index < txt_num)
  27.         {
  28.             YUYY_HS12864G18B_DisplayString8x16(&lcd_dev,select_index == start_index?YUYY_FONT_DATAS_REVERSE:0,i*2,0,filenames[start_index]);
  29.             i += 1;
  30.             start_index += 1;
  31.         }
  32.     }
  33.     else
  34.     {
  35.         YUYY_HS12864G18B_DisplayString8x16(&lcd_dev,0,0,0,lcd_buffer[0]);
  36.         YUYY_HS12864G18B_DisplayString8x16(&lcd_dev,0,2,0,lcd_buffer[1]);
  37.         YUYY_HS12864G18B_DisplayString8x16(&lcd_dev,0,4,0,lcd_buffer[2]);
  38.         YUYY_HS12864G18B_DisplayString8x16(&lcd_dev,0,6,0,lcd_buffer[3]);
  39.     }
  40. }
  41. void yuyy_readbuffer_to_lcd()
  42. {
  43.     uint8_t i = 0,j = 0,k = 0;
  44.     uint32_t len = 0;
  45.     memset(lcd_buffer,0,68);
  46.     if(file_buffer_len == 0)
  47.     {
  48.         f_lseek(&file,0);
  49.         file_read_end = 0;
  50.         file_buffer_len = 0;
  51.     }
  52.     if(!file_read_end && file_buffer_len < 80)
  53.     {
  54.         if(f_read(&file, &file_buffer[file_buffer_len], 80-file_buffer_len, &len) == FR_OK)
  55.         {
  56.             if(len == 0 || len < 80-file_buffer_len)
  57.             {
  58.                 file_read_end = 1;
  59.             }
  60.             file_buffer_len += len;
  61.         }
  62.     }
  63.     while(j < 4)
  64.     {
  65.         i = 0;
  66.         while(i < 16 && k < file_buffer_len)
  67.         {
  68.             if(file_buffer[k]>0x19 && file_buffer[k] < 0x7F)
  69.             {
  70.                 lcd_buffer[j][i] = file_buffer[k];
  71.                 i += 1;
  72.             }
  73.             else if(file_buffer[k] == '\n' && i > 0)
  74.             {
  75.                 i = 16;
  76.             }
  77.             k += 1;
  78.         }
  79.         j += 1;
  80.     }
  81.     i = 0;
  82.     j = k;
  83.     while(i < k && j < 80)
  84.     {
  85.         file_buffer[i] = file_buffer[j];
  86.         i += 1;
  87.         j += 1;
  88.     }
  89.     file_buffer_len -= k;
  90. }
  91. void yuyy_button_clicked()
  92. {
  93.     if(!filed_opened)
  94.     {
  95.         select_index += 1;
  96.         if(txt_num > 0 && select_index > txt_num - 1)
  97.             select_index = 0;
  98.         yuyy_show_txt();
  99.     }
  100.     else
  101.     {
  102.         yuyy_readbuffer_to_lcd();
  103.         yuyy_show_txt();
  104.     }
  105. }
  106. void yuyy_button_longpressed()
  107. {
  108.     if(txt_num == 0)
  109.         return;
  110.     if(!filed_opened)
  111.     {
  112.         if(f_open(&file, filenames[select_index], FA_READ) == FR_OK)
  113.         {
  114.             filed_opened = 1;
  115.             memset(file_buffer,0,80);
  116.             yuyy_readbuffer_to_lcd();
  117.             yuyy_show_txt();
  118.         }
  119.     }
  120.     else
  121.     {
  122.         if(f_close(&file) == FR_OK)
  123.         {
  124.             filed_opened = 0;
  125.             file_read_end = 0;
  126.             file_buffer_len = 0;
  127.             yuyy_show_txt();
  128.         }
  129.     }
  130. }
在usbh_user_application()中case USR_APP分支中注释掉原来的读写文件方法,加入yuyy_scantxt();和 yuyy_show_txt();
微信截图_20240504111742.png
运行效果



打赏榜单

ArteryMCU 打赏了 50.00 元 2024-06-07
理由:[F405开发板评测活动]内容优质

ArterySW 打赏了 30.00 元 2024-05-09
理由:上次打赏错了对象,这次补上。

caigang13 发表于 2024-5-4 11:31 来自手机 | 显示全部楼层
用的什么文件系统呢?

打赏榜单

ArterySW 打赏了 20.00 元 2024-05-07
理由:作品优秀

 楼主| yuyy1989 发表于 2024-5-4 11:34 | 显示全部楼层
caigang13 发表于 2024-5-4 11:31
用的什么文件系统呢?

FAT32
lemonboard 发表于 2024-5-5 10:31 | 显示全部楼层
真棒!
显示的速度也蛮快的
chenjun89 发表于 2024-5-5 19:57 来自手机 | 显示全部楼层
这个是个啥显示屏?
trucyw 发表于 2024-5-5 20:31 | 显示全部楼层
不错
weifeng90 发表于 2024-5-6 08:09 来自手机 | 显示全部楼层
还是这种经典的黑白屏看起来更舒服
 楼主| yuyy1989 发表于 2024-5-6 08:19 | 显示全部楼层
chenjun89 发表于 2024-5-5 19:57
这个是个啥显示屏?

12864的单色LCD
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

161

主题

815

帖子

10

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