sujingliang 发表于 2025-1-27 11:08

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

本帖最后由 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;
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;
      gbl=gb2312;
      
      //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);
                }
                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;
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=cn;
                        zm=cn;
                        

                        
                        get_hzk_bmp(zm);


                        for(i=0; i<32; i++)
                        {   //MSK的位数
                              color=hzk_bmp;
                              //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(":\r\n");
if(f_mount(&MMCFatFs, (TCHAR const*)MMCPath, 0) == FR_OK)
{
                        //printf("\r\n");
                        res = f_opendir(&dir, "/");
                        if (res == FR_OK)
                        {
                              //printf("\r\n");
                              printf("\r\n:\r\n");
      for (;;) {
                                                i++;
            res = f_readdir(&dir, &fno);
            if (res != FR_OK || fno.fname == 0) break;
            if (fno.fname == '.') 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:\r\n%s\r\n",rtewz_buffxt);
                                                                              /* Close the open text file */
                                                                              f_close(&MyFile);
                                                }
                                                wz_buff='\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

文本阅读器非常不错的开发
页: [1]
查看完整版本: 【STM32H745I-DISCO试用】7、文本阅读器