打印
[活动]

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

[复制链接]
184|1
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
APM32F411的USB支持主机或从机模式

接下来在OTGH_MSC这个例程的基础上增加LCD显示,U盘文件扫描和TXT文件读取功能
把上个帖子的LCD驱动移植过来,由于USB占用了原来的IO,需要换一下IO才行
YUYY_HS12864G18B_DEV_Type lcd_dev;
void spi_init()
{
    GPIO_Config_T GPIO_InitStructure;
    SPI_Config_T  SPI_InitStructure;
    RCM_EnableAHB1PeriphClock (RCM_AHB1_PERIPH_GPIOC);
    RCM_EnableAPB1PeriphClock(RCM_APB1_PERIPH_SPI2);
   
    GPIO_ConfigPinAF(GPIOC, GPIO_PIN_SOURCE_3, GPIO_AF_SPI1);
    GPIO_ConfigPinAF(GPIOC, GPIO_PIN_SOURCE_7, GPIO_AF_SPI1);
   
    GPIO_ConfigStructInit(&GPIO_InitStructure);
    GPIO_InitStructure.pin = GPIO_PIN_3 | GPIO_PIN_7;
    GPIO_InitStructure.speed = GPIO_SPEED_100MHz;
    GPIO_InitStructure.mode = GPIO_MODE_AF;
    GPIO_InitStructure.otype = GPIO_OTYPE_PP;
    GPIO_InitStructure.pupd = GPIO_PUPD_NOPULL;
    GPIO_Config(GPIOC, &GPIO_InitStructure);
   
    SPI_ConfigStructInit(&SPI_InitStructure);
    SPI_InitStructure.direction = SPI_DIRECTION_1LINE_TX;
    SPI_InitStructure.mode = SPI_MODE_MASTER;
    SPI_InitStructure.length = SPI_DATA_LENGTH_8B;
    SPI_InitStructure.polarity = SPI_CLKPOL_HIGH;
    SPI_InitStructure.phase = SPI_CLKPHA_2EDGE;
    SPI_InitStructure.nss = SPI_NSS_SOFT;
    SPI_InitStructure.baudrateDiv = SPI_BAUDRATE_DIV_8;
    SPI_InitStructure.firstBit = SPI_FIRSTBIT_MSB;
    SPI_InitStructure.crcPolynomial = 7;
    SPI_Config(SPI2, &SPI_InitStructure);
    SPI_DisableCRC(SPI2);
    SPI_DisableSSOutput(SPI2);
    SPI_Enable(SPI2);
}
void lcd_spiwritebyte(SPI_T *spix,uint8_t byte)
{
    while (SPI_I2S_ReadStatusFlag(spix, SPI_FLAG_TXBE) == RESET);
    SPI_I2S_TxData(spix, byte);
}
void lcd_init()
{
    GPIO_Config_T gpioConfigStruct;
    RCM_EnableAHB1PeriphClock (RCM_AHB1_PERIPH_GPIOC);
    GPIO_ConfigStructInit(&gpioConfigStruct);
    gpioConfigStruct.mode = GPIO_MODE_OUT;
    gpioConfigStruct.speed = GPIO_SPEED_100MHz;
    gpioConfigStruct.pin = GPIO_PIN_4 | GPIO_PIN_5 | GPIO_PIN_6;
    gpioConfigStruct.otype = GPIO_OTYPE_PP;
    gpioConfigStruct.pupd = GPIO_PUPD_NOPULL;
    GPIO_Config(GPIOC, &gpioConfigStruct);
   
    lcd_dev.cs.gpio = GPIOC;
    lcd_dev.cs.pin = GPIO_PIN_4;
    lcd_dev.rst.gpio = GPIOC;
    lcd_dev.rst.pin = GPIO_PIN_5;
    lcd_dev.a0.gpio = GPIOC;
    lcd_dev.a0.pin = GPIO_PIN_6;
    lcd_dev.spix = SPI2;
    lcd_dev.spi_sendbyte_func = (YUYY_HS12864G18B_SpiWriteByteFunc_Type)lcd_spiwritebyte;
   
    YUYY_HS12864G18B_Init(&lcd_dev);
    YUYY_HS12864G18B_ClearScreen(&lcd_dev);
    YUYY_HS12864G18B_DisplayString8x16(&lcd_dev,0,0,0," APM32F411 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");
    YUYY_HS12864G18B_DisplayFinish(&lcd_dev);
}
实现TXT文件扫描和内容显示
#define MAX_TXT_NUM 10
char filenames[MAX_TXT_NUM][14];
uint8_t txt_num = 0;
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_file_index_change()
{
    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_file_open_back()
{
    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();
        }
    }
}
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 && strncasecmp(&fileinfo.fname[len-4],".TXT",4) == 0)
            memcpy(filenames[txt_num++],fileinfo.fname,13);               
    }
    i = 0;
    while(i < txt_num)
    {
        printf("%d: %s",i,filenames[i]);
        i++;
    }
}
改写USB_HostUserApplication这个方法
void USB_HostUserApplication(void)
{
    uint8_t status = gUsbHostAppStatus;
    static uint8_t userAppState = USER_APP_INIT;

    switch (status)
    {
        case USBH_APP_CONNECTION:
            break;

        case USBH_APP_DISCONNECTION:
            userAppState = USER_APP_INIT;
            YUYY_HS12864G18B_ClearScreen(&lcd_dev);
            YUYY_HS12864G18B_DisplayString8x16(&lcd_dev,0,0,0," APM32F411 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");
            YUYY_HS12864G18B_DisplayFinish(&lcd_dev);
            break;

        case USBH_APP_READY:
            switch (userAppState)
            {
                case USER_APP_INIT:
                    if (f_mount(&fatfs, "0:", 0) == FR_OK)
                    {
                        yuyy_scantxt();
                        yuyy_show_txt();
                    }
                    userAppState = USER_APP_RUN;
                    break;

                case USER_APP_RUN:
                    if (!APM_PBGetState(BUTTON_KEY1))
                    {
                        YUYY_DelayMs(10);
                        if (!APM_PBGetState(BUTTON_KEY1))
                        {
                            yuyy_file_index_change();
                            while (!APM_PBGetState(BUTTON_KEY1));
                        }
                    }
                    if (!APM_PBGetState(BUTTON_KEY2))
                    {
                        YUYY_DelayMs(10);
                        if (!APM_PBGetState(BUTTON_KEY2))
                        {
                            yuyy_file_open_back();
                            while (!APM_PBGetState(BUTTON_KEY2));
                        }
                    }
                    break;
            }
            break;

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


没有插入U盘时

选择文件

打开文件查看内容


使用特权

评论回复
沙发
szt1993| | 2024-5-23 17:57 | 只看该作者
USB_OTG使用配置起来还是挺方便的,里面的协议格式能方便讲解一下嘛

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

94

主题

543

帖子

4

粉丝