This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

[参考译文] 编译器/F28M35H52C:使用 FatFs 0.13b 嵌入式字符串函数

Guru**** 2609955 points


请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/microcontrollers/c2000-microcontrollers-group/c2000/f/c2000-microcontrollers-forum/687865/compiler-f28m35h52c-using-fatfs-0-13b-embedded-string-functions

器件型号:F28M35H52C

工具/软件:TI C/C++编译器

我已将 FatFs 从0.04b 更新为0.13b、并已将 SD_CARD_M3示例项目中的代码移植到我自己的代码中、但它无法正常工作、我需要做更多的测试、 我真正需要的是可以放入主程序中的代码、这是调用更新的 FatFs 例程的已知良好代码。  此类代码存在于 main.c 程序中、该程序是 LPC23xx 文件夹的一部分、位于此处的示例代码中  、并且 有一组示例调用、用于使用 FatFs 嵌入字符串函数(如 xputs()和 putdump())的诸如 disk_status 之类的东西、在这里对此进行了解释    

我不想重写所有示例代码、而是希望能够按原样使用 FatFs 嵌入式字符串函数、但我不清楚如何将标准输出定向到我的 UART。   

我的主程序使用 UARTStdioIntHandler,而我的 UARTprintf()命令运行正常。  我需要将 xprintf.c 添加到我的项目中、并将#include xprint.h 添加到调用 xprintxxx 函数的 c 程序中、但我在哪里/如何调整代码以告知 xprint 函数将我的 UART 用作输出?

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    这是我的主程序 DSTR_m3.c -当我使其正常工作时(或者现在有人想与我一起工作?)、我将共享 ff.c 和 ff.h。

    //######################################################################################################################
    //文件:dSTR_m3.c
    //标题:dSTR M3安装程序
    //最初基于 controlSUITE 示例 V220 setup_m3.c
    //
    //此程序用于主子系统。 它执行
    在控制子系统上执行项目之前所需的 DSTR 系统//设置。
    //
    //- PLL 配置
    //-将 UART0设置为115、200波特与 GPS 系统通信
    //-调用 PinoutSet 以配置 DSTR PCB 的所有 GPIO 引脚
    //-将特定 GPIO 映射到控制子系统
    //-从复位//
    -循环中释放控制子系统 永久处理 UART 请求、但要通过中断
    //
    /////##################################################################################################
    // Ted Mawson MB Electronic Design 2017年11月
    // 2017年11月11日/28/2017第一个运行版本、具有 GPIO 设置、UART 回显(115、200)和成功调用、使 c28内核独立运行
    // 2017年12月11日版本、将共享 RAM 的控制提供给 C28并运行 UART 的索引计数
    // 该版本还通过编辑 F28M35x_generic_C28_flash.cmd 文件
    // 2018年1/18/添加 了用于 UART 数据接收
    的命令解析系统// 2018年2月3日来"修复" ramfuncs 错误 添加了用于设置电流范围 SR1、SR2、SR5、SR10、SR20的额外命令-现在移至 C28、值通过 m2cArray[]发送、作为建议
    // 添加了由命令 VB 控制的详细切换-修复了问题并测试了 OK
    // 4/21/2018不同版本的数据流-添加了电流但需要1) SysInfo 2)常规 A/V/PF 3)电压4)电流
    // 4/22/2018代码清理、删除了 C28控制这些引脚时的 IC15控制基准 (实际上始终是这样)
    // 2018年4月25日添加了 SV、SA 命令 Stream Vols/Amps -现在 VB 命令也会正确切换
    // 2018年5月6日 添加 FatFs vn013b 的主要更改-由 Ted Mawson
    
    #include 根据旧代码生成的端口 
    #include "inc/hw_ints.h"
    #include "inc/hw_memmap.h"
    #include "inc/hw_NVIC.h"
    #include "inc/hw_sysctl.h"
    #include "inc/hw_types.h"
    #include "board_drivers/set_pinout_f28m35x.h"//由"gpio/driverm2017"修改
    需要//TM?
    #include "driverlib/interrupt.h"
    #include "driverlib/sysctl.h"
    #include "driverlib/SysTick .h"
    #include "driverlib/flash.h"
    #include "utils/cmdline.h"
    #include "utils/uartstdio.h"
    #include "utils/ustdlib.fs.h"
    #include "vfatfs/third_13" //针对 FatFs vF 的 TM 新增
    内容#include "third_party/fatfs_v13/src/diskio13.h"//针对 FatFs v0.13的 TM 新增
    内容/#include "third_party/fatfs_v13/src/cffconf.h"//针对 Fatv0.13的 TM 新增
    内容//此行下方的 TM 包含内容不在 sd_party/driverinc
    #include "h.inc"#include "ov.h"
    
    需要//TM?
    #include "driverlib/debug.h" 需要//TM?
    #include "driverlib/cpu.c" 需要//TM?
    #include "driverlib/ram.h" 需要//TM?
    #include 
    #include "shared.h" // TM M3和 C28
    
    extern void UARTStdioIntHandler (void)共用的共享.h 文件; // TMupdate -用作 IO 处理程序
    
    #ifdef _flash
    //这些由链接器定义(请参阅器件链接器命令文件)
    extern unsigned long RamfuncsLoadStart;
    extern unsigned long RamfuncsRunStart;
    extern unsigned long RamfuncsLoadSize;
    #endif
    
    #define path_BUF_size 80 // TMupdate -保存路径的缓冲区的大小,或 SD 卡中的临时数据的大小。
    #define CMD_BUF_SIZE 64 // TMupdate -保存命令行
    静态 char g_cCwdBuf[path_BUF_size]="/"的缓冲区大小; // TMupdate -用于保存到当前工作目录
    的完整路径的缓冲区静态 char g_cTmpBuf[path_BUF_size]; // TMupdate -在操作文件路径或从 SD 卡
    静态 char g_cCmdBuf[CMD_BUF_SIZE]读取数据时使用的临时数据缓冲区; // TMupdate -保存命令行的缓冲
    
    区//*********
    //下面是 FatFs 使用的数据结构。
    //
    静态 FATFS g_sFatFs;
    静态 DIR g_sDirObject;
    静态 FILINFO g_sFileInfo;
    静态 FIL g_sFileObject;
    
    //*********
    //在 FRESULT 数字代码和
    字符串表示之间保存映射的结构。 从 FatFs
    // FAT 文件系统驱动程序返回 FRESULT 代码。
    //
    typedef 结构
    {
    FRESULT 结果;
    char * pcResultStr;
    }
    tFresultString;
    
    //*************
    //一个宏,用于轻松地将结果代码添加到表中。
    //
    #define FRESULT_Entry (f) {(f)、(# f)}// TMupdate -需要允许填充以下数组
    
    //*************
    //在数字 FRESULT 代码和
    //它的名称作为字符串之间保存映射的数组。 这用于查找
    //打印到控制台的错误代码。 // TMupdate -将列表0.04b 更新为0.13b
    //*************
    tFresultString g_sFresultStrings[]=// TM 我认为这是一个 RAM 数组,但可以作为常数存储在闪存中
    ,这在{中完成
    FRESULT_Entry (FR_OK)、
    FRESULT_Entry (FR_DISK_ERR)、
    FRESULT_Entry (FR_INT_ERR)、
    FRESULT_Entry (FR_NOT _READY)、
    FRESULT_Entry (FR_NO_FILE)、
    FRESULT_Entry (FR_NO_PATH)、
    FRESULT_Entry (FR_INVALID_NAME)、
    FRESULT_Entry (FR_Denied)、
    FRESULT_Entry (FR_Exists)、
    FRESULT_Entry (FR_INVALID_OBJECT)、
    FRESULT_Entry (FR_WRITE_PROTECTED)、
    FRESULT_Entry (FR_INVALID_DRIVE)、
    FRESULT_Entry (FR_NOT _ENABLED)、
    FRESULT_Entry (FR_NO_filesystem)、
    FRESULT_Entry (FR_mkfs_aborted)、
    FRESULT_Entry (FR_TIMEOUT)、
    FRESULT_Entry (FR_LOCKED)、
    FRESULT_Entry (FR_NOT 足够的内核)、
    FRESULT_Entry (FR_TO_MOUSE_OPEN_FILES)、
    FRESULT_Entry (FR_INVALID_PARAMETER)
    };
    
    //*********
    // ChangeDirectory()返回的错误原因。
    //
    #define NAME_TOW_LON_ERROR 1
    #define opendir_error 2
    
    //*********
    //保存结果代码数的宏。
    //
    #define NUM_FRESULT_CODES (sizeof (g_sFresultStrings)/ sizeof (tFresultString))
    
    //*********
    //每秒的 SysTick 节拍数。
    //
    #define TICKS_PER_second 100
    
    //*********
    //文件名列表框小工具字符串表的存储。
    //
    #define NUM_LIST_STRINS 48
    const char * g_ppcDirListStrings[NUM_LIST_STRINTS];
    
    //*********
    //存储当前目录中的文件名。 文件名
    //存储为目录的"(D) filename.ext"格式或
    文件的"(F) filename.ext"//格式。
    //
    #define MAX_FILENAME_STRING_LEN (4 + 8 + 1 + 3 + 1)
    char g_pcFilename[NUM_LIST_STRING][MAX_FILENAME_STRIN_LEN];
    
    //*********
    //存储显示在
    //显示底部状态框中的字符串。
    //
    #define NUM_STATUS_STRINS 6
    #define MAX_STATUS_STRIN_LEN (36 + 1)
    char g_pcStatus[NUM_STATUS_STRINS][MAX_STATUS_STRIN_LEN];
    
    //*********
    //状态列表框小工具字符串表的存储。
    //
    const char * g_ppcStatusStrings[NUM_STATUS_STRINS]=
    {
    G_pcStatus[0]、
    G_pcStatus[1]、
    G_pcStatus[2]、
    G_pcStatus[3]、
    G_pcStatus[4]、
    G_pcStatus[5]
    };
    无符号长整型 g_ulStatusStringIndex = 0;
    
    //*********
    //转发由用户
    界面中使用的小工具调用的函数的声明//接口。
    //
    静态 FRESULT ChangeToDirectory (char * pcDirectory、unsigned long * pulReason);
    静态 const char * StringFromFresult(FRESULT fresult);
    
    //*********
    //此函数返回错误代码的字符串表示
    //从函数调用返回到 FatFs。 它可用于
    //打印人类可读的错误消息。
    //
    static const char *
    StringFromFresult (FRESULT fresult)
    {
    unsigned int uIdx;
    
    //输入循环以搜索错误代码表以查找匹配项
    //错误代码。
    对于(uIdx = 0;uIdx < NUM_FRESULT_CODES;uIdx++){
    if (g_sFresultStrings[uIdx].fresult=fresult){// tm 如果找到匹配项,则返回相应的错误代码
    return (g_sFresultStrings[uIdx].pcResultStr);
    }
    }
    return ("未知错误代码"); // TM 如果未找到匹配的代码,则返回字符串,表示它是未知错误代码
    }
    
    void
    SysTickHandler (void) SysTick 中断
    的// TM 处理程序{
    //调用 FatFs tick 计时器。
    disk_timerproc ();
    }
    
    //*********
    //此函数实现"ls"命令。 它打开当前
    //目录并枚举内容,并为
    它找到的每个项打印一行。 它显示文件属性、时间和
    //日期、文件大小以及名称等详细信息。 它
    显示了结尾处//文件大小的摘要以及可用空间。
    //
    int
    Cmd_ls (int argc、char * argv[])
    {
    unsigned long ulTotalSize、ulItemCount、ulFileCount、ulDirCount;
    FRESULT 结果;
    FATFS * pFatFs;
    
    //打开当前目录进行访问。
    fresult = f_opendir (&g_sDirObject、g_cCwdBuf);
    
    //检查错误,如果有问题,则返回。
    if (fresult!= FR_OK)
    {
    
    return (fresult);
    }
    
    ulTotalSize = 0;
    ulFileCount = 0;
    ulDirCount = 0;
    ulItemCount = 0;
    
    //在列表前添加一个额外的空白行。
    UARTprintf ("\n");
    
    //输入循环以枚举所有目录条目。
    for (;;)
    {
    //从目录中读取条目。
    fresult = f_readdir (&g_sDirObject、&g_sFileInfo);
    
    //检查错误,如果有问题,则返回。
    if (fresult!= FR_OK)
    {
    return (fresult);
    }
    
    //如果文件名为空,则这是的结尾
    //列表。
    if (!g_sFileInfo.fname[0])
    {
    中断;
    }
    
    //使用格式将条目信息打印在一行上
    //显示属性、日期、时间、大小和名称。
    UARTprintf ("%c%c%c%c%c %u/%02u/%02u %02u:%02u %9U %s\n"、
    (G_sFileInfo.fattrib & AM_DIR)? 'D':'-'、
    (G_sFileInfo.fattrib 和 AM_RDO)? 'R':'-'、
    (G_sFileInfo.fattrib 和 AM_HID)? 'h':'-'、
    (G_sFileInfo.fattrib 和 AM_SYS)? S':'-'、
    (G_sFileInfo.fattrib & AM_ARC)? 'A':'-'、
    (G_sFileInfo.fdate >> 9)+ 1980、
    (g_sFileInfo.fdate >> 5)和15、
    G_sFileInfo.fdate 和31、
    (g_sFileInfo.ftime >> 11)、
    (G_sFileInfo.ftime >> 5)和63、
    G_sFileInfo.fsize、
    g_sFileInfo.fname);
    
    //在列表框小部件中将信息添加为一行。
    if (ulItemCount < NUM_LIST_SPRACIES)
    {
    usprintf (g_pcFilames[ulItemCount]、"(%c)%12s"、
    (G_sFileInfo.fattrib & AM_DIR)? 'D':'F'、
    g_sFileInfo.fname);
    }
    
    //如果属性是目录,则增加目录计数。
    if (g_sFileInfo.fattrib 和 am_DIR)
    {
    ulDirCount++;
    }
    
    //否则,它是一个文件。 递增文件计数、和
    //将文件大小与总数相加。
    其他
    {
    ulFileCount++;
    ulTotalSize += g_sFileInfo.fsize;
    }
    
    //移动到我们用于填充的项目数组中的下一个条目
    //列表框。
    ulItemCount++;
    
    //等待 UART 发送缓冲区为空。
    UARTFlushTx (false);
    
    } //结束
    
    //打印显示文件、目录和大小总计的摘要行。
    UARTprintf ("\n%4U 文件、总共%10U 字节\n%4U 目录"、
    ulFileCount、ulTotalSize、ulDirCount);
    
    //获得可用空间。
    fresult=f_getfree("/",&ulTotalSize,&pFatFs);
    
    //检查错误,如果有问题,则返回。
    if (fresult!= FR_OK)
    {
    return (fresult);
    }
    
    //显示计算出的可用空间量。
    UARTprintf ("、%10uK 字节空闲\n"、ulTotalSize * pFatFs->csize / 2);// TM sect_clust > csize
    
    //等待 UART 发送缓冲区为空。
    UARTFlushTx (false);
    
    //将其添加到这里,返回时没有错误。
    退货(0);
    }
    
    //*********
    //此函数实现“cd”命令。 它采用一个参数
    //来指定使当前工作目录的目录。
    //路径分隔符必须使用正斜杠"/"。 cd //的参数
    可以是以下之一:
    //* root ("/")
    //*完全指定的路径("/my/path/to/mydir)
    //*当前目录("mydir")中的单个目录名
    //*父目录("..")
    //它不了解相对路径,所以不要尝试这样的操作:
    //("../my/new/path)
    //指定新目录后,它会尝试打开该目录
    //以确保它存在。 如果新路径已成功打开,则
    //当前工作目录(cwd)更改为新路径。
    //如果出现错误,pulReason 参数将被写入
    //以下值之一:
    //*********
    静态 FRESULT
    ChangeToDirectory (char * pcDirectory、unsigned long * pulReason)
    {
    unsigned int uIdx;
    FRESULT 结果;
    
    //将当前工作路径复制到临时缓冲区中,以此类推
    //它可以被操作。
    strcpy (g_cTmpBuf、g_cCwdBuf);
    
    //如果第一个字符是/,则这是完全指定的
    //路径、它应该按原样使用。
    if (pcDirectory[0]='/')
    {
    //确保新路径不大于 cwd 缓冲区。
    if (strlen (pcDirectory)+ 1 > sizeof (g_cCwdBuf))
    {
    *pulReason = name_too_long_error;
    return (FR_OK);
    }
    
    //如果新路径名(在 argv[1]中)不是太长,则
    //将其复制到临时缓冲区,以便可以对其进行检查。
    其他
    {
    strncpy (g_cTmpBuf、pcDirectory、sizeof (g_cTmpBuf));
    }
    }
    
    //如果参数是. 然后尝试删除最低级别
    //在 CWD 上。
    否则 if (!strcmp (pcDirectory、".."))
    {
    //获取当前路径中最后一个字符的索引。
    uIdx = strlen (g_cTmpBuf)- 1;
    
    //从路径名末尾备份到分隔符(/)
    //找到,或者直到我们到达路径的开头。
    while (((g_cTmpBuf[uIdx]!='/')&&(uIdx > 1))
    {
    //备份一个字符。
    uIdx--;
    }
    
    //现在我们处于中的最低级别分隔符
    //当前路径,或在字符串开头(根)。
    //因此在此处设置字符串的新端,有效地删除
    //路径的最后一部分。
    G_cTmpBuf[uIdx]= 0;
    }
    
    //否则,这只是当前路径的常规名称
    //目录,需要将其附加到当前路径。
    其他
    {
    //测试以确保在新的附加路径为时
    //添加到当前路径中,缓冲区中有空间
    //表示完整的新路径。 它需要包含一个新的分隔符、
    //和后缀为空字符。
    if (strlen (g_cTmpBuf)+ strlen (pcDirectory)+ 1 + 1 > sizeof (g_cCwdBuf))
    {
    *pulReason = name_too_long_error;
    return (FR_INVALID_OBJECT);
    }
    
    //新路径是可以的,所以添加分隔符,然后追加
    //路径的新目录。
    其他
    {
    //如果尚未位于根级别,则追加/
    if (strcmp (g_cTmpBuf、"/"))
    {
    strcat (g_cTmpBuf、"/");
    }
    
    //将新目录附加到路径。
    strcat (g_cTmpBuf、pcDirectory);
    }
    }
    
    //此时,候选新目录路径位于 chTmpBuf 中。
    //尝试打开它以确保它有效。
    fresult = f_opendir (&g_sDirObject、g_cTmpBuf);
    
    //如果无法打开,则是一条错误的路径。 通知
    //用户和返回。
    if (fresult!= FR_OK)
    {
    *pulReason = opendir_error;
    return (fresult);
    }
    
    //否则,它是一个有效的新路径,所以将其复制到 CWD 并进行更新
    //屏幕。
    其他
    {
    strncpy (g_cCwdBuf、g_cTmpBuf、sizeof (g_cCwdBuf));
    }
    
    //返回成功。
    return (FR_OK);
    }
    
    //*********
    //此函数实现“cd”命令。 它采用一个参数
    //来指定使当前工作目录的目录。
    //路径分隔符必须使用正斜杠"/"。 cd //的参数
    可以是以下之一:
    //* root ("/")
    //*完全指定的路径("/my/path/to/mydir)
    //*当前目录("mydir")中的单个目录名
    //*父目录("..")
    //它不了解相对路径,所以不要尝试这样的操作:
    //("../my/new/path)
    //指定新目录后,它会尝试打开该目录
    //以确保它存在。 如果新路径已成功打开,则
    //当前工作目录(cwd)更改为新路径。
    //
    int
    Cmd_cd (int argc、char * argv[])
    {
    unsigned long ulReason;
    FRESULT 结果;
    
    //尝试更改为命令行上提供的目录。
    fresult = ChangeToDirectory (argv[1],&ulReason);
    
    //如果报告了错误,请尝试提供一些有用的信息。
    if (fresult!= FR_OK)
    {
    开关(ulReason)
    {
    case opendir_error:
    UARTprintf ("打开新目录时出错。\n");
    中断;
    
    案例名称_太_长_错误:
    UARTprintf ("生成的路径名太长。\n");
    中断;
    
    默认值:
    UARTprintf ("报告了无法识别的错误。\n");
    中断;
    }
    }
    
    //返回相应的错误代码。
    返回(fresult);
    }
    
    //*********
    //此函数实现"pwd"命令。 它只需打印
    //当前工作目录。
    //
    int
    Cmd_pwd (int argc、char * argv[])
    {
    //将 CWD 打印到控制台。
    UARTprintf ("%s\n"、g_cCwdBuf);
    
    //等待 UART 发送缓冲区为空。
    UARTFlushTx (false);
    
    //返回成功。
    退货(0);
    }
    
    //*********
    //此函数实现"cat"命令。 它读取
    //文件的内容并将其打印到控制台。 这只能用于
    //文本文件。 如果在二进制文件上使用、则
    可能会在控制台上打印一堆垃圾//。
    //
    int
    Cmd_cat (int argc、char * argv[])
    {
    FRESULT 结果;
    UINT usBytesRead;// TMupdate
    
    //首先,检查以确保当前路径(CWD),加号
    //文件名加上分隔符和后缀为空,将全部完成
    //适合用于保存的临时缓冲区
    //文件名。 文件名必须完整指定、具有路径、
    //至 FatFs。
    if (strlen (g_cCwdBuf)+ strlen (argv[1])+ 1 + 1 > sizeof (g_cTmpBuf))
    {
    UARTprintf ("生成的路径名太长\n"\n);
    返回(0);
    }
    
    //将当前路径复制到临时缓冲区,以便对其进行操作。
    strcpy (g_cTmpBuf、g_cCwdBuf);
    
    //如果尚未位于根级别,则追加分隔符。
    if (strcmp ("/"、g_cCwdBuf))
    {
    strcat (g_cTmpBuf、"/");
    }
    
    //最后,附加文件名以生成完全指定的文件。
    strcat (g_cTmpBuf、argv[1]);
    
    //打开文件进行读取。
    fresult = f_open (&g_sFileObject、g_ctmpBuf、fa_read);
    
    //如果打开文件时出现问题,则返回
    //错误。
    if (fresult!= FR_OK)
    {
    return (fresult);
    }
    
    //输入循环,重复从文件中读取数据并显示数据,
    //直至到达文件末尾。
    操作
    {
    //从文件中读取数据块。 读取尽可能多的数据
    //在临时缓冲区中,包括尾部空的空格。
    fresult = f_read (&g_sFileObject、g_cTmpBuf、sizeof (g_cTmpBuf)- 1、
    usBytesRead (&U);
    
    //如果读取错误,则打印换行符和
    //将错误返回给用户。
    if (fresult!= FR_OK)
    {
    UARTprintf ("\n");
    return (fresult);
    }
    
    // Null 终止最后一个被读取使其成为 A 的块
    //可以与 printf 一起使用的以 null 结尾的字符串。
    G_cTmpBuf[usBytesRad]= 0;
    
    //打印接收到的文件的最后一个块。
    UARTprintf ("%s"、g_cTmpBuf);
    
    //等待 UART 发送缓冲区为空。
    UARTFlushTx (false);
    
    //继续读取,直到小于完整字节数
    //读取。 这意味着已到达缓冲区的末尾
    。}
    while (usBytesRead = sizeof (g_cTmpBuf)- 1);
    
    //返回成功。
    退货(0);
    }
    
    //*********
    //此函数实现“帮助”命令。 它打印
    一个简单的可用命令列表//并附有简要说明。
    //
    int
    Cmd_help (int argc、char * argv[])
    {
    tCmdLineEntry *pentrry;
    
    //打印一些标题文本。
    UARTprintf ("\n 可用命令\n");
    UARTprintf ("------------------ \n");
    
    //指向命令表的开头。
    pentrry =&g_sCmdTable[0];
    
    //输入循环以从命令表中读取每个条目。 。
    //命令名称为 NULL 时,已到达表末尾。
    while (preme->pcCmd)
    {
    //打印命令名称和简短说明。
    UARTprintf ("%s%s%s\n"、pentry -> pcCmd、pentry -> pcHelp);
    
    //前进到表中的下一个条目。
    pentre++;
    
    //等待 UART 赶上来。
    UARTFlushTx (false);
    }
    
    //返回成功。
    return (0);
    }
    
    静态
    空 Cmd_ds ( /*显示物理磁盘状态*/
    字节 drv
    )
    {
    dword dw;
    字节 CT、buf[64];
    字 w;
    char *ty、*am;
    
    
    UARTprintf ("RC=%d\n"、disk_status (drv));
    
    if (disk_ioctl (drv、get_sector_count、&dw)=RES_OK)
    UARTprintf ("驱动器大小:%lu 扇区\n"、dw);
    
    if (disk_ioctl (drv、get_block_size、&dw)=RES_OK)
    UARTprintf ("擦除块大小:%lu 扇区\n"、dw);
    
    if (disk_ioctl (drv、mmc_get_type、&CT)= RES_OK){
    Ty ="未知";AM ="";
    如果(CT 和 CT_MMC) ty ="MMC";
    如果(CT 和 CT_SD1) ty ="SDv1";
    IF (CT 和 CT_SD2){
    Ty ="SDv2";
    AM =(CT 和 CT_BLOCK)? "(块)":"(字节)";
    }
    UARTprintf ("卡类型:%s%s\n"、ty、am);
    }
    
    if (disk_ioctl (drv、mmc_get_cSD、buf)= RES_OK){
    UARTprintf (%s、"CSD:\n");
    PUT_Dump (buf、0、16、DW_CHAR);
    }
    
    if (disk_ioctl (drv、mmc_get_cid、buf)= RES_OK){
    UARTprintf (%s、"CID:\n");
    PUT_Dump (buf、0、16、DW_CHAR);
    }
    
    if (disk_ioctl (drv、mmc_get_ocr、buf)= RES_OK){
    UARTprintf (%s、"OCR:\n");
    PUT_Dump (buf、0、4、DW_CHAR);
    }
    
    if (((CT & CT_SDC)&& disk_ioctl (drv、MMC_GET_SDSTAT、buf)= RES_OK){
    UARTprintf (%s、"SD 状态:\n");
    对于(w = 0;w < 64;w += 16)
    PUT_Dump (buf+w、w、16、dw_char);
    }
    }
    //*********
    //这是保存命令名称、实现函数、
    //和简要说明的表。
    //
    tCmdLineEntry g_sCmdTable[]=
    {
    {"help"、Cmd_help、 ":显示命令列表"},
    {"h"、 CMD_help、":帮助别名"}、
    {"?"、 CMD_help、":帮助别名"}、
    {"DS"、 CMD_DS (0)、 ":显示磁盘状态"},
    {"ls"、 CMD_ls、 ":显示文件列表"},
    {"chdir"、cmd_cd、 ":更改目录"}、
    {"CD"、 CMD_CD、 “: chdir 的别名”},
    {"pwd"、Cmd_pwd、 ":显示当前工作目录"},
    {"cat"、cmd_cat、 ":显示文本文件的内容"},
    {0、0、0}
    };
    
    // TM 原型
    void processCommand (void);
    char IsCharReady (void);
    char GetRxStr (void);
    
    //*************
    //驱动程序库遇到错误时调用的错误例程。
    //
    #ifdef debug
    void
    __error__(char *pcFilename,unsigned long ulLine)
    {
    }
    
    #endif
    
    //######## M3代码####中使用的变量的声明
    // TM 定义为进入特定存储器位置的全局用户变量,请参阅共享 RAM
    上的 OneNote #pragma DATA_SECTION (ssVoltsArray、".vArray")//设置为共享 RAM 区域
    unsigned short ssVoltsArray[0x3140]; //定义12、608 x 16位无符号整数的数组
    
    #pragma DATA_SECTION (ssAmpsArray、".iArray")//设置为共享 RAM 区域
    无符号短整型 ssAmpsArray[0x3140];//定义12、608 x 16位
    
    
    无符号整数组#pragma DATA_SECTION (c2mArray、".c2mRAM[0x3140];//将 RAM 设置为共享区域20] //定义20 x 16位无符号整数的数组
    
    #pragma DATA_SECTION (m2cArray、".m2cRAM")//设置为 S7共享 RAM 区域
    无符号短整型 m2cArray[20]; //定义一个20 x 16位无符号整数的数组### NB S7中有4、096个 Uint16s 的空间(8KB)
    
    unsigned int verbose = 0;
    unsigned int streamps = 0;
    unsigned int streamVolts = 0;
    unsigned short myIndex;
    unsigned short tempUshort;
    
    
    int main (void){
    
    int i、nStatus;
    FRESULT 结果;
    
    //允许写入受保护的寄存器。
    HWREG (SYSCTL_MWRALLOW)= 0xA5A5A5;
    
    //设置 PLL、M3以75MHz 运行、C28以150MHz 运行
    SysCtlClockConfigSet (SYSCTL_USE_PLL |(SYSCTL_SPLLIMULT_M & 0xF)|
    SYSCTL_SYSDIV_1 | SYSCTL_M3SSDIV_2 |
    SYSCTL_XCLKDIV_4); // TM -最后一个 XCLKDIV_4未在 SD_CARD.C 中使用、它有什么作用?????
    
    // TM 将 S0分配给共享 RAM 的 S6以供从 RAM_Management controlSUITE 示例中获取的 c28 TM 使用
    // c28如何使用这些存储器段的详细信息在 c28链接器文件中定义。(28M35H52C1_RAM_lnk.cmd)
    // TM 需要#include "driverlib/ram.h"
    RAMMReqSharedMemAccess ((S0_ACCESS | S1_ACCESS | S2_ACCESS | S3_ACCESS | S5_ACCESS | S6_ACCESS)、SX_C28MASTER);
    
    #ifdef _FLASH
    //将时间关键代码和闪存设置代码复制到 RAM
    //其中包括以下函数:InitFlash ();
    // RamfuncsStart
    和 RamfuncsSize 链接器创建的 Ramfuncs。 请参阅器件.cmd 文件。
    memcpy (&RamfuncsRunStart、&RamfuncsLoadStart、(size_t)&RamfuncsLoadSize);
    
    //调用闪存初始化以设置闪存等待状态
    //此函数必须驻留在 RAM 中
    FlashInit();
    #endif
    
    PinoutSet();// TM 这运行与 DSTR PCB 相对应的引脚设置
    //设置位于 set_pinout_f28m35x.c 和 set_pinout_f28m35x.h 中(由 TM 修改以匹配 DSTR PCB)
    
    //为100Hz 中断配置 SysTick。
    SysTickPeriodSet (SysCtlClockGet (system_clock_speed)/ ticks_per_sond);
    SysTickEnable();
    SysTickIntEnable();
    
    //在 RAM 矢量表中注册中断处理程序
    IntRegister (FAULT_SysTick、SysTickHandler);
    
    //启用中断。
    IntMasterEnable();
    
    //初始化 UART 作为文本 I/O 的控制台
    UARTStdioInit (0);
    IntRegister (INT_UART0、UARTStdioIntHandler);
    
    //向用户打印问候消息。
    UARTprintf ("\n\nTM 更新了 NSD 卡示例程序\n");
    UARTprintf ("键入\'help\'以获取帮助。\n");
    //启用 UART 和 GPIO 外设时钟电源
    // SysCtlPeripheralEnable (SYSCTL_Periph_UART0);
    SysCtlPeripheralEnable (SYSCTL_Periph_GPIOA);
    SysCtlPeripheralEnable (LED_0_Periph); // LED0位于 PE5上(从 blinky_dc_m3.c 示例中提取)、由 C28控制
    SysCtlPeripheralEnable (RANGE2KA_Periph);
    SysCtlPeripheralEnable (RANGE5KA_Periph);
    SysCtlPeripheralEnable (RANGE20KA_Periph);
    SysCtlPeripheralEnable (RANGE10KA_Periph);
    
    m2cArray[AmpsRange]= 0;//#TMWTF##设置1kA 范围、但我们应该将其视为 M3的"已插入"范围
    //现在这不起任何作用
    
    //为端口 E 引脚5 (LED0)提供 C28控制
    GPIOPinConfigureCoreSelect (LED_0_BASE、LED_0_PIN、GPIO_PIN_C_CORE_SELECT);
    
    //解锁寄存器以更改端口 B 引脚7的提交寄存器值
    //这会禁用引脚上的 NMI 功能并允许其他复用
    //要使用的选项
    HWREG (GPIO_PORTB_BASE_GPIO_O_LOCK)= GPIO_LOCK_KEY_DD;
    //写入确认寄存器
    HWREG (GPIO_PORTB_BASE_GPIO_O_CR)|= 0x000000FF;
    //延迟
    对于(i=0;i<20;i++){};
    
    #ifdef _standalone
    #ifdef _flash
    //发送引导命令以允许 C28应用程序开始执行
    IPCMtoCBootControlSystem (CBROM_MTOC_BOOTMODE_BOOT_FROM _FLASH);
    #else
    //发送引导命令以允许 C28应用程序开始执行
    IPCMtoCBootControlSystem (CBROM_MTOC_BOOTMODE_BOOT_FROM _RAM);
    #endif
    #endif
    
    //使用逻辑磁盘0装入文件系统。
    fresult = f_mount (&g_sFatFs、""、0);// TMupdate、需要检查这是否正确
    if (fresult!= FR_OK)
    {
    UARTprintf ("f_mount 错误:%s\n"、StringFromFresult (fresult));
    返回(1);
    }
    
    
    //主代码
    while (1){
    //将提示打印到控制台。 显示 CWD。
    UARTprintf ("\n%s>"、g_cCwdBuf);
    
    //从用户获取一行文本。
    UARTgets (g_cCmdBuf、sizeof (g_cCmdBuf));
    
    //将线路从用户传递到命令处理器。
    //将对其进行解析并执行有效的命令。
    nStatus = CmdLineProcess (g_cCmdBuf);
    
    //处理命令错误的情况。
    if (nStatus = CMDLINE_BAD_CMD)
    {
    UARTprintf ("命令错误!\n");
    }
    
    //处理过多参数的情况。
    否则、如果(nStatus = CMDLINE_TOW_NOW_args)
    {
    UARTprintf ("命令处理器的参数太多!\n");
    }
    
    //否则命令被执行。 打印错误
    //如果返回一个,则编码。
    否则(nStatus!= 0)
    {
    UARTprintf ("命令返回错误代码%s\n"、
    StringFromResult(((FRESULT)nStatus));
    }
    }// while 结束(1)
    }// main 结束
    
    
    

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    TED、

    听起来您已经取得了一些进展!

    在我看来,您引用的示例(以及我查看的其他示例)中的关键行是 xdev_in_()和 xdev_out()函数。 这是您设置 I/O 设备的位置、在本例中为 UART。 如果提供的 UART 函数设置正确、"xprintf"函数负责调用这些函数。 如果您设置了 LCD 监视器或不同的 UART 管道、这还允许您即时更改输出管道。 似乎、如果您为每个管道设置输入和输出函数、您可以根据需要调用 xdev_IN/OUT、将管道重新分配到不同的端点。

    这至少是我对 xdev_的解释。 和 xprintf 功能。

    您能否向我解释一下您的端口是如何不工作的? 新的 sdcard 功能是否未按预期运行? 您是否只是尝试使输出管道正常工作、以便打印有用的信息?

    谢谢、
    标记
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    Mark、

    感谢您的回复、现在我只是想让输出管道正常工作。 我认为我所做的 ff.s 更改是可以的(除了可能存在错误)、但我上面的主程序中的大部分功能都是从 controlCARD 示例文件 v220的旧 SD_CARD_M3示例中删除的。 第633行是 Cmd_DS ()函数的替换项,该函数使用 PUT_Dump ()函数,但我开始转换一些 xsprintf ()调用,然后意识到最好将程序设置为使用已在中使用的低占用空间命令 FatFs 示例-然后我可以根据需要剪切和粘贴它们。

    我可以看到 xprintf.h 文件中有 xdev_out()(和 xdev_in_())函数,但我不理解它们的语法、它们所做的是什么,或者我需要如何/修改它们,以便使 xprintf 函数在 M3程序中正常工作。

    TED
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    我的问题是了解如何指示 FatFs Embeded String 函数通过 UART 向外发送字节。  FatFs 文档所说的是...

    "低级输出函数是用户提供的回调函数、用于向器件发送字节。 应将其地址设置为指针'xfunc_out'、以在使用之前设置默认输出器件。 例如 xdev_out (uart2_putc);输出函数将从 xputc 函数调用。 通常、此函数将字节放入 UART、LCD 或任何输出器件。 xsprintf/xfprintf 函数使用其参数覆盖默认输出器件。"

    xprintf.h 文件包含这些行。

    define xDEV_OUT (func) xfunc_out =(void (*)(unsigned char))(func)
    extern void (* xfunc_out)(unsigned char); 

    我认为#defining xdev_out (funct)作为要由 xfuncT_out 替代的宏、它在做什么?  我应该用一个命令代替"xfunct_out"吗?   如果是、将要发送的字节如何传递到被调用函数-我在这一点上不清楚、我也不清楚要使用什么 C 函数来发送字节-它是 usstdlib.c 中的字节吗?

    非常感谢您的任何帮助。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    TED、

    您可以正确地看到、这些是我个人尚未看到的一些独特宏。 我将在这里咨询一些 SW 同事、看看他们是否有任何可能有帮助的意见。 我将在星期三之前得到回复。

    -Mark
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    TED、

    请阅读函数指针。 我进行了谷歌搜索、这种语法经常出现。 基本上,xdev_out()和 xdev_in_()函数允许您在使用同一命令时热插拔输出管道

    请参考 ffsample.zip 文件夹中的其他器件示例。 在主函数中、调用 xDEV_OUT 函数、传递的函数实际上是将用于将数据从 UART 端口输出的特定 UART 输出函数。 如果您希望输出数据进入其他管道、可以随时更改此设置。

    在 xprintf.c 文件中,您会看到实际调用 xfunc_out()的唯一时间是在 xputc()函数内。 了解这一点、然后返回查看实际传递给 xDEV_OUT 函数的函数、可以看到此处唯一特定于硬件的函数是 UART Put char 函数。

    所有这些都是一种令人困惑的方法,可以说对于您的软件,您希望从 driverlib 的 UART.c 文件中获得 UARTCharPut ()和 UARTCharGet ()函数。
    即在您的主函数中:
    InitUART();//init UART 端口
    xDEV_OUT (UARTCharPut);//将输出管道设置为 UART 字符输出函数
    XDEV_IN (UARTCharGet);//将输入管道设置为 UART 字符获取函数。

    使用 xprintf 函数替换您的 UARTPrintf 函数调用。

    我*认为*这正是这里所需要的一切。 请告诉我这是否有帮助。
    -Mark
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    Mark、感谢您的详细回答、这正是我想要的。 我相信这将解决这个问题、所以我会将您的帖子标记为答案、但在接下来的两周中、我将无法对其进行一天或两天的测试。

    TED
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    很好、请随时向我们发布。

    -Mark