发新帖本帖赏金 100.00元(功能说明)我要提问
返回列表
[活动专区]

【AT-START-F405测评】6.实现简易的U盘TXT阅读器

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

  /* add user code end spi1_init 0 */

  gpio_init_type gpio_init_struct;
  spi_init_type spi_init_struct;

  crm_periph_clock_enable(CRM_SPI1_PERIPH_CLOCK, TRUE);
  gpio_default_para_init(&gpio_init_struct);
  spi_default_para_init(&spi_init_struct);

  /* add user code begin spi1_init 1 */

  /* add user code end spi1_init 1 */

  /* configure the SCK pin */
  gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_MODERATE;
  gpio_init_struct.gpio_out_type = GPIO_OUTPUT_PUSH_PULL;
  gpio_init_struct.gpio_mode = GPIO_MODE_MUX;
  gpio_init_struct.gpio_pins = GPIO_PINS_3;
  gpio_init_struct.gpio_pull = GPIO_PULL_NONE;
  gpio_init(GPIOB, &gpio_init_struct);

  gpio_pin_mux_config(GPIOB, GPIO_PINS_SOURCE3, GPIO_MUX_5);

  /* configure the MOSI pin */
  gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_MODERATE;
  gpio_init_struct.gpio_out_type = GPIO_OUTPUT_PUSH_PULL;
  gpio_init_struct.gpio_mode = GPIO_MODE_MUX;
  gpio_init_struct.gpio_pins = GPIO_PINS_5;
  gpio_init_struct.gpio_pull = GPIO_PULL_NONE;
  gpio_init(GPIOB, &gpio_init_struct);

  gpio_pin_mux_config(GPIOB, GPIO_PINS_SOURCE5, GPIO_MUX_5);

  /* configure param */
  spi_init_struct.transmission_mode = SPI_TRANSMIT_HALF_DUPLEX_TX;
  spi_init_struct.master_slave_mode = SPI_MODE_MASTER;
  spi_init_struct.frame_bit_num = SPI_FRAME_8BIT;
  spi_init_struct.first_bit_transmission = SPI_FIRST_BIT_MSB;
  spi_init_struct.mclk_freq_division = SPI_MCLK_DIV_8;
  spi_init_struct.clock_polarity = SPI_CLOCK_POLARITY_HIGH;
  spi_init_struct.clock_phase = SPI_CLOCK_PHASE_2EDGE;
  spi_init_struct.cs_mode_selection = SPI_CS_SOFTWARE_MODE;
  spi_init(SPI1, &spi_init_struct);

  spi_enable(SPI1, TRUE);

  /* add user code begin spi1_init 2 */

  /* add user code end spi1_init 2 */
}
void lcd_spiwritebyte(spi_type *spix,uint8_t byte)
{
    while(spi_i2s_flag_get(spix, SPI_I2S_TDBE_FLAG) == RESET);
    spi_i2s_data_transmit(spix,byte);
}
void lcd_show_welcom()
{
    YUYY_HS12864G18B_ClearScreen(&lcd_dev);
    YUYY_HS12864G18B_DisplayString8x16(&lcd_dev,0,0,0," AT32F405 TEST");
    YUYY_HS12864G18B_DisplayString8x16(&lcd_dev,0,2,0,"TXT FILE READER");
    YUYY_HS12864G18B_DisplayString8x16(&lcd_dev,0,4,0,"  Wait USB Dev");
    YUYY_HS12864G18B_DisplayString8x16(&lcd_dev,0,6,0,"Code by yuyy1989");
}
void lcd_init()
{
    gpio_init_type gpio_init_struct;
    gpio_default_para_init(&gpio_init_struct);
    crm_periph_clock_enable(CRM_GPIOB_PERIPH_CLOCK, TRUE);

    /* add user code begin gpio_config 1 */

    /* add user code end gpio_config 1 */

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

    gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_MODERATE;
    gpio_init_struct.gpio_out_type = GPIO_OUTPUT_PUSH_PULL;
    gpio_init_struct.gpio_mode = GPIO_MODE_OUTPUT;
    gpio_init_struct.gpio_pins = LCD_A0_PIN | LCD_RST_PIN | LCD_CS_PIN;
    gpio_init_struct.gpio_pull = GPIO_PULL_NONE;
    gpio_init(GPIOB, &gpio_init_struct);
   
    wk_spi1_init();
   
    lcd_dev.cs.gpio = LCD_CS_GPIO_PORT;
    lcd_dev.cs.pin = LCD_CS_PIN;
    lcd_dev.a0.gpio = LCD_A0_GPIO_PORT;
    lcd_dev.a0.pin = LCD_A0_PIN;
    lcd_dev.rst.gpio = LCD_RST_GPIO_PORT;
    lcd_dev.rst.pin = LCD_RST_PIN;
    lcd_dev.spix = SPI1;
    lcd_dev.spi_sendbyte_func = (YUYY_HS12864G18B_SpiWriteByteFunc_Type)lcd_spiwritebyte;
   
    YUYY_HS12864G18B_Init(&lcd_dev);
    lcd_show_welcom();
}
实现按键点击和长按的识别,这里使用1ms的定时器对按键按下状态计数实现去抖和单击长按的识别,在主循环中ms_ticked == 1时调用AppButtonLoop()并重新将ms_ticked 置0
void wk_tmr6_init(void)
{
    crm_periph_clock_enable(CRM_TMR6_PERIPH_CLOCK, TRUE);
    tmr_base_init(TMR6, 999, 215);
    tmr_cnt_dir_set(TMR6, TMR_COUNT_UP);
    tmr_period_buffer_enable(TMR6, FALSE);

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

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

    tmr_counter_enable(TMR6, TRUE);
    /* add user code begin tmr6_init 2 */
    tmr_interrupt_enable(TMR6,TMR_OVF_INT,TRUE);
    /* add user code end tmr6_init 2 */
    nvic_irq_enable(TMR6_GLOBAL_IRQn, 0, 0);
}
uint8_t ms_ticked = 0;
uint16_t led_conut = 0;
void AppLepLoop()
{
    if(led_conut > 0)
        led_conut -= 1;
    if(led_conut == 0)
    {
        led_conut = 1000;
        at32_led_toggle(LED2);
        at32_led_toggle(LED3);
        at32_led_toggle(LED4);
    }
}
uint16_t button_down_count = 0;
void AppButtonLoop()
{
    if(at32_button_state() != RESET)
    {
        button_down_count += 1;
    }
    else
    {
        if(button_down_count > 20 && button_down_count < 500)
        {
            USBH_DEBUG("button clicked");
            yuyy_button_clicked();
        }
        button_down_count = 0;
    }
    if(button_down_count == 1000)
    {
        USBH_DEBUG("button long press");
        yuyy_button_longpressed();
    }
}
void AppMsTick(void)
{
    ms_ticked = 1;
}
微信截图_20240504111605.png
实现U盘中TXT文件的扫描
#define MAX_TXT_NUM 10
char filenames[MAX_TXT_NUM][14];
uint8_t txt_num = 0;
void yuyy_scantxt()
{
    uint8_t len,i;
    FRESULT res;
        FILINFO fileinfo;
        DIR dir;
    res=f_opendir(&dir,"/");
    if(res != FR_OK)
        return;
    memset(filenames,0,MAX_TXT_NUM*14);
    txt_num = 0;
    while(1)
    {
        char* pstr;
        res = f_readdir(&dir, &fileinfo);
        if (res != FR_OK || fileinfo.fname[0] == 0 || txt_num == MAX_TXT_NUM)
            break;                                                 
        if(fileinfo.fattrib&AM_DIR)
            continue;
        len = strlen(fileinfo.fname);
        if(len > 4 && memcmp(&fileinfo.fname[len-4],".TXT",4) == 0)
            memcpy(filenames[txt_num++],fileinfo.fname,13);               
    }
    i = 0;
    while(i < txt_num)
    {
        USBH_DEBUG("%d: %s",i,filenames[i]);
        i++;
    }
}
显示文件列表和文件内容
uint8_t select_index = 0;
uint8_t filed_opened = 0;
uint8_t file_read_end = 0;
uint8_t file_buffer[80];
uint8_t file_buffer_len = 0;
char lcd_buffer[4][17];

void yuyy_show_txt()
{
    uint8_t start_index = 0;
    uint8_t i = 0;
    YUYY_HS12864G18B_ClearScreen(&lcd_dev);
    if(txt_num == 0)
    {
        YUYY_HS12864G18B_DisplayString8x16(&lcd_dev,0,0,0,"NO TXT FILES");
        return;
    }
    if(!filed_opened)
    {
        if(txt_num > 4)
        {
            if(select_index == txt_num - 1 )
                start_index = select_index - 3;
            else if(select_index > 2 )
                start_index = select_index - 2;
        }
        while(start_index < txt_num)
        {
            YUYY_HS12864G18B_DisplayString8x16(&lcd_dev,select_index == start_index?YUYY_FONT_DATAS_REVERSE:0,i*2,0,filenames[start_index]);
            i += 1;
            start_index += 1;
        }
    }
    else
    {
        YUYY_HS12864G18B_DisplayString8x16(&lcd_dev,0,0,0,lcd_buffer[0]);
        YUYY_HS12864G18B_DisplayString8x16(&lcd_dev,0,2,0,lcd_buffer[1]);
        YUYY_HS12864G18B_DisplayString8x16(&lcd_dev,0,4,0,lcd_buffer[2]);
        YUYY_HS12864G18B_DisplayString8x16(&lcd_dev,0,6,0,lcd_buffer[3]);
    }
}
void yuyy_readbuffer_to_lcd()
{
    uint8_t i = 0,j = 0,k = 0;
    uint32_t len = 0;
    memset(lcd_buffer,0,68);
    if(file_buffer_len == 0)
    {
        f_lseek(&file,0);
        file_read_end = 0;
        file_buffer_len = 0;
    }
    if(!file_read_end && file_buffer_len < 80)
    {
        if(f_read(&file, &file_buffer[file_buffer_len], 80-file_buffer_len, &len) == FR_OK)
        {
            if(len == 0 || len < 80-file_buffer_len)
            {
                file_read_end = 1;
            }
            file_buffer_len += len;
        }
    }
    while(j < 4)
    {
        i = 0;
        while(i < 16 && k < file_buffer_len)
        {
            if(file_buffer[k]>0x19 && file_buffer[k] < 0x7F)
            {
                lcd_buffer[j][i] = file_buffer[k];
                i += 1;
            }
            else if(file_buffer[k] == '\n' && i > 0)
            {
                i = 16;
            }
            k += 1;
        }
        j += 1;
    }
    i = 0;
    j = k;
    while(i < k && j < 80)
    {
        file_buffer[i] = file_buffer[j];
        i += 1;
        j += 1;
    }
    file_buffer_len -= k;
}
void yuyy_button_clicked()
{
    if(!filed_opened)
    {
        select_index += 1;
        if(txt_num > 0 && select_index > txt_num - 1)
            select_index = 0;
        yuyy_show_txt();
    }
    else
    {
        yuyy_readbuffer_to_lcd();
        yuyy_show_txt();
    }
}
void yuyy_button_longpressed()
{
    if(txt_num == 0)
        return;
    if(!filed_opened)
    {
        if(f_open(&file, filenames[select_index], FA_READ) == FR_OK)
        {
            filed_opened = 1;
            memset(file_buffer,0,80);
            yuyy_readbuffer_to_lcd();
            yuyy_show_txt();
        }
    }
    else
    {
        if(f_close(&file) == FR_OK)
        {
            filed_opened = 0;
            file_read_end = 0;
            file_buffer_len = 0;
            yuyy_show_txt();
        }
    }
}
在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

使用特权

评论回复
发新帖 本帖赏金 100.00元(功能说明)我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

109

主题

594

帖子

4

粉丝