【前言】
在实际工程中,如果需要用到外部储存,特别是大文件,测需要用到SD卡,开发板板载了SD读卡器,此次分享如何在TouchGFX中读取SD卡的属性,以及读取指定文件的内容。本次主要学习官方示例:
1、STM32Cube_FW_H7RS_V1.1.0\Projects\STM32H7S78-DK\Examples\SD\SD_ReadWrite_DMA,此示例为如何初始化SD卡。
2、STM32Cube_FW_H7RS_V1.1.0\Projects\STM32H7S78-DK\Applications\FatFs\FatFs_uSD_RTOS,此工程示例如何在FreeRTOS中实现FATFS的工程配置以及文件的读写功能。
此次的工程在前一篇的TouchGFX工程中添加指定的功能:【STM32H7R/S-DK】创建TouchGFX工程基础 - stm32/stm8 - 电子工程世界-论坛 (eeworld.com.cn)
【实现方法】
一、SD的图形化配置,打开STM32CubeMX,打开工程,添加SDMMC1,并配置为4bit传输模式,时钟为下降沿时采样,以及总结分频。
同时开启中断,以及核对与开发板原理图的GPIO是否一致,此次配置GPIO默认与原理图一致,不需要修改GPIO的配置。
生成工程后,使用MDK打开。
二、由于在SD的Init中需要用HAL_Delay函数,需要手工开启SysTick中断,如果没有开启就会阻塞在初始化上。
我这里的解决方法是自己重写了HAL_Delay函数,以及初始化的函数。
#include "delay.h"
#include "main.h"
uint8_t fac_us=0;
uint16_t fac_ms=0;
void Delay_Init()
{
//只可以选择不分频或者8分频,这里选择系统时钟8分频,最后频率为9MHZ
SysTick->CTRL &= ~(1<<2);
//SystemCoreClock为72000000,最终fac_us为9,也就是记录震动9次。因为频率为9MHZ所以为1us
fac_us = SystemCoreClock / 8000000;
fac_ms = fac_us*1000; //1000us=1ms
}
/*
CTRL SysTick控制及状态寄存器
LOAD SysTick重装载数值寄存器
VAL SysTick当前数值寄存器
*/
void Delay_us(uint32_t nus)
{
uint32_t temp;
SysTick->LOAD =nus*fac_us; //设置加载的值,比如1us就要计数9次。nus传入1,CALIB=1*9=9,最后就是1us
SysTick->VAL =0x00; //清空计数器中的值,LOAD里的值不是写入后就会加载,而是在systick使能且VAL值为0时才加载
SysTick->CTRL |=SysTick_CTRL_ENABLE_Msk; //使能时钟,开始计时
do
{
temp=SysTick->CTRL; //查询是否计数完成
}while((temp&0x01)&&!(temp&(1<<16))); //先判断定时器是否在运行,再判断是否计数完成
SysTick->CTRL&=~SysTick_CTRL_ENABLE_Msk; //关闭计数器
SysTick->VAL =0X00; //清空计数器
}
void Delay_ms(uint32_t nms)
{
uint32_t temp;
SysTick->LOAD =nms*fac_ms; //设置加载的值,比如1us就要计数9次。nus传入1,CALIB=1*9=9,最后就是1us
SysTick->VAL =0x00; //清空计数器中的值,LOAD里的值不是写入后就会加载,而是在systick使能且VAL值为0时才加载
SysTick->CTRL |=SysTick_CTRL_ENABLE_Msk; //使能时钟,开始计时
do
{
temp=SysTick->CTRL; //查询是否计数完成
}while((temp&0x01)&&!(temp&(1<<16))); //先判断定时器是否在运行,再判断是否计数完成
SysTick->CTRL&=~SysTick_CTRL_ENABLE_Msk; //关闭计数器
SysTick->VAL =0X00; //清空计数器
}
void HAL_Delay(uint32_t nms)
{
uint32_t temp;
SysTick->LOAD =nms*fac_ms; //设置加载的值,比如1us就要计数9次。nus传入1,CALIB=1*9=9,最后就是1us
SysTick->VAL =0x00; //清空计数器中的值,LOAD里的值不是写入后就会加载,而是在systick使能且VAL值为0时才加载
SysTick->CTRL |=SysTick_CTRL_ENABLE_Msk; //使能时钟,开始计时
do
{
temp=SysTick->CTRL; //查询是否计数完成
}while((temp&0x01)&&!(temp&(1<<16))); //先判断定时器是否在运行,再判断是否计数完成
SysTick->CTRL&=~SysTick_CTRL_ENABLE_Msk; //关闭计数器
SysTick->VAL =0X00; //清空计数器
}
在main.c中添加初始化函数就行了。
三、SD测试,在TouchGFX中添加一个Text控件,以及一个按键,在Screen1View.cpp中添加测试代码:
void Screen1View::fungetsdinfo()
{
HAL_SD_CardInfoTypeDef pCardInfo = {0};
HAL_StatusTypeDef ret = HAL_SD_GetCardInfo(&hsd1,&pCardInfo);
Unicode::snprintf(textCardInfoBuffer, TEXTCARDINFO_SIZE, "CardType=%d\nCardVersion=%d\nBlockSize=%dk\n",
pCardInfo.CardType,pCardInfo.CardVersion,pCardInfo.BlockSize);
textCardInfo.invalidate();
}
其功能为读取SD卡的一些基本参数,并更新到text控制中,下载后得到界面如下:
四、FATFS移植
1、在生成的工程中的文件夹内,已经有了fatfs的源码了,路径为:Middlewares\Third_Party\FatFs\source,我们只需要添加指定文件到工程中。
2、根据官方的示例,我添加了如下文件到工程中:
1、修改sd_diskio_config.h中的指定的hsd1
2、修改ffconf.h如下:
#define FFCONF_DEF 80286 /* Revision ID */
/*-----------------------------------------------------------------------------/
/ Additional user header to be used
/-----------------------------------------------------------------------------*/
#include "main.h"
#include "stm32h7rsxx_hal.h"
/*---------------------------------------------------------------------------/
/ Function Configurations
/---------------------------------------------------------------------------*/
#define FF_FS_READONLY 0
/* This option switches read-only configuration. (0:Read/Write or 1:Read-only)
/ Read-only configuration removes writing API functions, f_write(), f_sync(),
/ f_unlink(), f_mkdir(), f_chmod(), f_rename(), f_truncate(), f_getfree()
/ and optional writing functions as well. */
#define FF_FS_MINIMIZE 0
/* This option defines minimization level to remove some basic API functions.
/
/ 0: Basic functions are fully enabled.
/ 1: f_stat(), f_getfree(), f_unlink(), f_mkdir(), f_truncate() and f_rename()
/ are removed.
/ 2: f_opendir(), f_readdir() and f_closedir() are removed in addition to 1.
/ 3: f_lseek() function is removed in addition to 2. */
#define FF_USE_FIND 0
/* This option switches filtered directory read functions, f_findfirst() and
/ f_findnext(). (0:Disable, 1:Enable 2:Enable with matching altname[] too) */
#define FF_USE_MKFS 1
/* This option switches f_mkfs() function. (0:Disable or 1:Enable) */
#define FF_USE_FASTSEEK 1
/* This option switches fast seek function. (0:Disable or 1:Enable) */
#define FF_USE_EXPAND 0
/* This option switches f_expand function. (0:Disable or 1:Enable) */
#define FF_USE_CHMOD 0
/* This option switches attribute manipulation functions, f_chmod() and f_utime().
/ (0:Disable or 1:Enable) Also FF_FS_READONLY needs to be 0 to enable this option. */
#define FF_USE_LABEL 0
/* This option switches volume label functions, f_getlabel() and f_setlabel().
/ (0:Disable or 1:Enable) */
#define FF_USE_FORWARD 0
/* This option switches f_forward() function. (0:Disable or 1:Enable) */
#define FF_USE_STRFUNC 2
#define FF_PRINT_LLI 1
#define FF_PRINT_FLOAT 1
#define FF_STRF_ENCODE 3
/*---------------------------------------------------------------------------/
/ Locale and Namespace Configurations
/---------------------------------------------------------------------------*/
#define FF_CODE_PAGE 936
/* This option specifies the OEM code page to be used on the target system.
/ Incorrect code page setting can cause a file open failure.
/
/ 437 - U.S.
/ 720 - Arabic
/ 737 - Greek
/ 771 - KBL
/ 775 - Baltic
/ 850 - Latin 1
/ 852 - Latin 2
/ 855 - Cyrillic
/ 857 - Turkish
/ 860 - Portuguese
/ 861 - Icelandic
/ 862 - Hebrew
/ 863 - Canadian French
/ 864 - Arabic
/ 865 - Nordic
/ 866 - Russian
/ 869 - Greek 2
/ 932 - Japanese (DBCS)
/ 936 - Simplified Chinese (DBCS)
/ 949 - Korean (DBCS)
/ 950 - Traditional Chinese (DBCS)
/ 0 - Include all code pages above and configured by f_setcp()
*/
#define FF_USE_LFN 0
#define FF_MAX_LFN 255
#define FF_LFN_UNICODE 0
#define FF_LFN_BUF 255
#define FF_SFN_BUF 12
#define FF_FS_RPATH 0
/*---------------------------------------------------------------------------/
/ Drive/Volume Configurations
/---------------------------------------------------------------------------*/
#define FF_VOLUMES 1
/* Number of volumes (logical drives) to be used. (1-10) */
#define FF_STR_VOLUME_ID 0
#define FF_VOLUME_STRS "RAM","NAND","CF","SD","SD2","USB","USB2","USB3"
#define FF_MULTI_PARTITION 0
#define FF_MIN_SS 512
#define FF_MAX_SS 512
#define FF_LBA64 0
#define FF_MIN_GPT valueNotSetted
#define FF_USE_TRIM 0
-----------------------------------------------------------------------*/
#define FF_FS_TINY 0
#define FF_FS_EXFAT 0
#define FF_FS_NORTC 0
#define FF_NORTC_MON 6
#define FF_NORTC_MDAY 4
#define FF_NORTC_YEAR 2015
#define FF_FS_NOFSINFO 0
#define FF_FS_LOCK 2
#define FF_FS_REENTRANT 0
#define FF_FS_TIMEOUT 1000
/*--- End of configuration options ---*/
3、编写用户函数fatfs.c函数,此函数也是学习FATFS的示例工程,在工程中创建一个FreeRTOS的任务线程,如果检测到SD插入,则进行挂载,挂载结束后写入文件STM32.TXT,并写入一串符串:const static uint8_t wtext[] = "This is STM32 working\n with FatFs uSD+FreeRTOS\n eeworld"; /* File write buffer */
如果写入成功,再读取此文件到rtext字符数组中。
4、为了测试,我又单独写了一个读取函数,方便touchGFX进行读取测试,代码如下:
void fs_read(void)
{
FRESULT res; /* FatFs function common result code */
uint32_t byteswritten, bytesread; /* File write/read counts */
res = f_open(&SDFile, "STM32.TXT", FA_READ);
if(res == FR_OK)
{
/* Read data from the text file */
res = f_read(&SDFile, ( void *)rtext, sizeof(rtext), (void *)&bytesread);
if((bytesread > 0) && (res == FR_OK))
{
/* Close the open text file */
f_close(&SDFile);
}
f_close(&SDFile);
}
}
四、TouchGFX界面设计
在touchGFX Designer中,再添加text控制与一个button控件,添加读取测试,代码如下:
void Screen1View::funShow()
{
fs_read();
Unicode::fromUTF8(rtext,textFileBuffer,100);
textFile.invalidate();
}
【实现效果】
点击屏幕中的不同按键,可以获取对应的信息。
此次工程为我第一次体验基于的TouchGFX下面的SD卡的读写测试,在SD驱动Init中遇到了因为HAL_Delay的问题折腾了好几天,最后追踪到问题点,并成功解决。基余的根据官方的示例并无困难。
【附工程源码】
引用: kylixyao 发表于 2024-9-21 21:41 不错不错,值得学习
感谢大佬的关注。
引用: 电子烂人 发表于 2024-9-22 16:38 大佬牛皮,学习了
大佬过奖了,您的文章比我写得好!
厉害厉害,可以把SD卡的图片读取出来,然后显示吗?
引用: wangerxian 发表于 2024-9-23 09:10 厉害厉害,可以把SD卡的图片读取出来,然后显示吗?
这个使用LTDC应该不是难题,难题是TouchGFX他有自己的图片算法,我得仔细想想。
lu哥,我就收藏了。。。。。。。。。。。。。。。。。。。
btw,rust还搞不?
引用: lugl4313820 发表于 2024-9-23 21:37 这个使用LTDC应该不是难题,难题是TouchGFX他有自己的图片算法,我得仔细想想。
他用的好像是bmp格式存储图片数据的,我觉得可以试试。
引用: hellokitty_bean 发表于 2024-9-24 08:51 lu哥,我就收藏了。。。。。。。。。。。。。。。。。。。 btw,rust还搞不?
rust现在还没有那个水平来搞呀,还没有入门呢
lu哥加油。。。。。准备沿着你的脚印前进呢。。。。。。。。
引用: mameng 发表于 2024-10-18 15:47 工程代码10积分 下载后怎么是STM32H7S78-DK_Appli\STM32H7S78-DK_Appli.axf: Error: L6200E: Symbol __stdo ...
你检查一下工程,看一下usart.h的头文件是不是包含进去了。