打印
[STM32H7]

【STM32H745I-DISCO试用】7、文本阅读器

[复制链接]
302|1
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
本帖最后由 sujingliang 于 2025-1-27 11:45 编辑

本文在以下2篇:
【STM32H745I-DISCO试用】5、eMMC+USB MSC=U盘: https://bbs.21ic.com/icview-3429458-1-1.html
【STM32H745I-DISCO试用】6、FATFS访问EMMC: https://bbs.21ic.com/icview-3429794-1-1.html
基础上继续做个文本阅读器,前面已经实现了U盘功能和FATFS访问文件功能,下面将驱动屏幕,并支持显示文本文件内容。
LCD驱动采用BSP中的官方函数。

效果:


一、STM32CuteMX配置
1、LTDS配置
参数选默认,后面不通过STM32CuteMX生成初始化代码。

2、DMA2D配置
参数选默认,后面不通过STM32CuteMX生成初始化代码。

3、FMC配置
参数选默认,后面不通过STM32CuteMX生成初始化代码。


4、Project Manager->Advanced Settings


选择不生成代码,这样代码中之包括必要的LTDS、DMA2D、FMC头文件和HAL库文件,后面将用BSP中的文件来实现LTDS、DMA2D、FMC的初始化。

二、代码修改
1、将以下BSP文件加入工程

这些文件是BSP驱动LCD必要的文件。

通过以下代码完成LCD初始化
 //BSP_MMC_Init(0);
        BSP_LCD_Init(0, LCD_ORIENTATION_LANDSCAPE);
  UTIL_LCD_SetFuncDriver(&LCD_Driver);
2、可以运行一些程序测试LCD驱动是否成功
static void Display_DemoDescription(void)
{
  char desc[64];
  uint32_t x_size;
  uint32_t y_size;

  UTIL_LCD_SetFont(&UTIL_LCD_DEFAULT_FONT);

  /* Clear the LCD */
  UTIL_LCD_SetBackColor(UTIL_LCD_COLOR_WHITE);
  UTIL_LCD_Clear(UTIL_LCD_COLOR_WHITE);

  /* Set the LCD Text Color */
  UTIL_LCD_SetTextColor(UTIL_LCD_COLOR_DARKBLUE);

  /* Display LCD messages */
  UTIL_LCD_DisplayStringAt(0, 10, (uint8_t *)"STM32H745I BSP", CENTER_MODE);
  UTIL_LCD_DisplayStringAt(0, 35, (uint8_t *)"Drivers examples", CENTER_MODE);

  BSP_LCD_GetXSize(0, &x_size);
  BSP_LCD_GetYSize(0, &y_size);

BSP_LCD_FillRect(0, 0, y_size/2 - 15, x_size, 100, UTIL_LCD_COLOR_BLUE);
}


如果正常可以显示一些文字和图案


3、编写一些处理获取中文字模和显示中文的函数

先通过U盘功能将gb2312_80.bin字库文件拷贝到emmc中

读取字库文件获取一个汉字的32个字节字模函数:
FRESULT ReadBinaryFile(const char* path, FSIZE_t ofs, uint8_t* buffer, uint32_t* bytesRead) 
{
        FRESULT res;
        FIL MyFile;             /* File object */
        UINT br;            /* Bytes read */
        
        /* Register the file system object to the FatFs module */
  if(f_mount(&MMCFatFs, (TCHAR const*)MMCPath, 0) != FR_OK)
  {
                printf("f_mount error\r\n");
                return res;
  }
  /* open the file in read mode */
  res = f_open(&MyFile, path, FA_READ);
  if(res != FR_OK)
  {
                printf("f_open error\r\n");
                return res;
  }
        
        res = f_lseek(&MyFile,ofs);
  if(res != FR_OK)
  {
                printf("f_lseek error\r\n");
                return res;
  }        
        
        /* Read the file */
        res = f_read(&MyFile, buffer, 32, &br);
        if (res != FR_OK) {
                        f_close(&MyFile); /* Close the file if an error occurs */
                        return res;
        }
        
        *bytesRead = br;
        
        f_close(&MyFile);        
        return FR_OK; /* Success */
}
GB2312字库偏移量计算函数
void get_hzk_bmp(uint8_t *gb2312)
{
        uint8_t gbh=0, gbl=0;
        uint32_t gbbl=0;
        uint32_t hzk_buf_size=0;
        
        gbh=gb2312[0];
        gbl=gb2312[1];
        
        //printf("%02X,%02X\r\n",gbh,gbl);
        
        if(gbh>=0xb0)
                        gbbl =((gbh - 0xa7) * 94 + (gbl - 0xa1))*32; // 根据偏移量计算公式计算偏移量
        else
                   gbbl =((gbh - 0xa1) * 94 + (gbl - 0xa1))*32; // 根据偏移量计算公式计算偏移量
        
        if(FR_OK==ReadBinaryFile(GB2312_BIN_FILE,gbbl,hzk_bmp,&hzk_buf_size))
        {
                /*
                printf("read:%d\r\n",hzk_buf_size);
                for(int i=0;i<32;i++)
                {        
                        printf("%02x ",hzk_bmp[i]);
                }
                printf("\r\n");
                */
                //disp_hz_bmp(hzk_bmp);
        }
        else{
                printf("ReadBinaryFile error\r\n");
        }
}


在LCD上显示汉字函数:
uint8_t GUI_Write16CnCharMatrix(uint16_t x, uint16_t y, uint8_t *cn, uint32_t wordColor, uint32_t backColor)
{
  uint16_t i=0, j,mx,my,wordNum;
        uint8_t zm[2];
  uint8_t color;
        uint16_t cur_index=0,ascii_num=0;
        mx=x;
  my=y;
        while (*cn != '\0')
    {
                if(mx>=480){
            mx=x;
            my+=16;
        }
               
                if(*cn<128){
                        ascii_num++;
                        cur_index++;
                        UTIL_LCD_DisplayChar(mx,my,*cn);
                        cn += 1;
                }
                else
                {
                        //if((cur_index==1018)&&(ascii_num%2==1)) return 1;
                        cur_index+=2;
                        zm[1]=cn[1];
                        zm[0]=cn[0];
                        

                        
                        get_hzk_bmp(zm);


                        for(i=0; i<32; i++)
                        {   //MSK的位数
                                color=hzk_bmp[i];
                                //printf("%02X,",color);
                                
                                
                                for(j=0;j<8;j++)
                                {
                                        /*
                                        if(i%2==0)
                                        {
                                                UTIL_LCD_FillRGBRect(mx+j,my+i/2,&color,8,1);
                                        }else
                                        {
                                                UTIL_LCD_FillRGBRect(mx+j+8,my+i/2,&color,8,1);
                                        }
                                        */
                                       
                                        if((color&0x80)==0x80)
                                        {
                                                if(i%2==0)
                                                {
                                                        BSP_LCD_WritePixel(0,mx+j,my+i/2,wordColor);
                                                        //UTIL_LCD_SetPixel(mx+j,my+i/2,wordColor);
                                                }
                                                else{
                                                        BSP_LCD_WritePixel(0,mx+j+8,my+i/2,wordColor);
                                                        //UTIL_LCD_SetPixel(mx+j+8,my+i/2,wordColor);
                                                }
                                        }
                                        else
                                        {
                                                if(i%2==0){
                                                        BSP_LCD_WritePixel(0,mx+j,my+i/2,backColor);
                                                        //UTIL_LCD_SetPixel(mx+j,my+i/2,backColor);
                                                }
                                                else{
                                                        BSP_LCD_WritePixel(0,mx+j+8,my+i/2,backColor);
                                                        //UTIL_LCD_SetPixel(mx+j+8,my+i/2,backColor);
                                                }
                                        }
                                       
                                        color<<=1;
                                       
                                }//for(j=0;j<8;j++)结束
                        }
                        //printf("\r\n");
                }
                cn += 2;
    mx += 16;
        }
        return ascii_num%2;
}
4、main文件

按键外部中断回调控制显示下一页:
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
  
  if (GPIO_Pin == GPIO_PIN_13)
  {
                cur_page++;
                refresh_page=1;
   
  }
}

while(1)
 while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */

                if(refresh_page==1)
                {
                        refresh_page=0;
                        UTIL_LCD_Clear(UTIL_LCD_COLOR_BLACK);
                        UTIL_LCD_SetBackColor(UTIL_LCD_COLOR_BLACK);
                        FS_listDirectory();
                }
                HAL_Delay(500);
  }
  /* USER CODE END 3 */
}
FS_listDirectory文件名瞎起的和内容没关系,
主要的功能是打开文本文件wkz.TXT,在LCD上显示文件内容。
static void FS_listDirectory(void)
{
        FRESULT res;
        DIR dir;
        FILINFO fno;
        uint32_t bytesread;
        uint16_t i;
        
        //printf("[Directory list]:\r\n");
  if(f_mount(&MMCFatFs, (TCHAR const*)MMCPath, 0) == FR_OK)
  {
                        //printf("[mount MMC success]\r\n");
                        res = f_opendir(&dir, "/");
                        if (res == FR_OK)
                        {
                                //printf("[open directory success]\r\n");
                                printf("\r\n[list directory / files ......]:\r\n");
        for (;;) {
                                                i++;
            res = f_readdir(&dir, &fno);
            if (res != FR_OK || fno.fname[0] == 0) break;
            if (fno.fname[0] == '.') continue;
                                       
                                        printFileInfo(&fno);
                                       
        }
                        
        f_closedir(&dir);
                }
               
                                if(f_open(&MyFile, "wkz.TXT", FA_READ) == FR_OK)
                                {
                                                                /* Read data from the text file */
                                                memset(wz_buff,0,sizeof(wz_buff));
                                                
                                                f_lseek(&MyFile,byte_offset);
                                                
                                                res = f_read(&MyFile, ( void *)wz_buff, 1020, (void *)&bytesread);

                                                if((bytesread > 0) && (res == FR_OK))
                                                {
                                                        //printf("\r\n[Display wz_buff.TXT file content]:\r\n%s\r\n",rtewz_buffxt);
                                                                                /* Close the open text file */
                                                                                f_close(&MyFile);
                                                }
                                                wz_buff[1020]='\0';
                                }
        }
                                
                                UTIL_LCD_SetFont(&Font16);
                                next_align=GUI_Write16CnCharMatrix(0,0,wz_buff,UTIL_LCD_COLOR_GREEN,UTIL_LCD_COLOR_BLACK);
                                byte_offset=byte_offset+1020-next_align;
}

三、总结
目前USB接入电脑后,U盘中的内容如下:

其中gb2312_80.bin是字库文件,wkz.txt是要显示内容的文本文件。
本文本质上是实现了读取wkz.txt内容,然后按照GB2312偏移计算公式在gb2312_80.bin找到字模,并在LCD上显示汉字。


使用特权

评论回复
沙发
星辰大海不退缩| | 2025-1-30 13:41 | 只看该作者
文本阅读器非常不错的开发

使用特权

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

本版积分规则

48

主题

96

帖子

0

粉丝