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.

[参考译文] 编译器/TM4C123GH6PZ:向 micro SD 卡写入数据的问题

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

https://e2e.ti.com/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/785123/compiler-tm4c123gh6pz-problem-of-writing-data-to-micro-sd-card

器件型号:TM4C123GH6PZ
主题中讨论的其他器件:TM4C123

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

您好、先生、

在将 SD 卡与 TM4C123连接时、我面临很多问题。 我不熟悉 SD 卡编程、如果有任何问题、请告知我。

我正在尝试在 UART 终端中显示数据。 我在终端窗口中得到了垃圾值。 将 程序保持在调试模式并选中"Getting the correct data in the watch window (在观察窗口中获取正确的数据)"。 我不明白 为什么在 PC 终端中出现垃圾值、程序和终端窗口中的波特率是相同的。

2.我在磁盘初始化条件下遇到的下一个问题是,程序在下面给定的部分中持续运行,而不是执行进一步的步骤。  

静态
字节 WAIT_READY (空)

字节分辨率;


Timer2 = 50;//等待就绪超时500ms */
RCVR_SPI ();
操作
RES = RCVR_SPI ();
while ((res!= 0xFF)&& Timer2);

返回 res;

在这里、我连续得到零。

下面给出了完整的代码。

include "stdint.h"
#include "stdbool.h"
#include "string.h"
#include "stdio.h"
#include "inc/hw_memmap.h"
#include "driverlib/fpu #defts/gpio.h"

#include "driverlib/interrupts.h"
#include "drivers/drivers.mdex"

#include "#mdefintrintrinc/包含"#drivers.idex"#mdeftex"#mdefintrintrintrl.htm#/drive.htm#include "#include"#def/drivers/drivers.htm#include"#include"#include"#include "drivers/drivers.mdefintrintrintrintrintrintrintrintrintrintrintrintrintrintrintrintrintr.md.htm#include





"#include "#"#"#.htm#.htm#include "#.htm#include "#.htm#include "#include "#def"#def"#include "#def/stat/drive.htm#/






//
//定义保存路径的缓冲区的大小,或
来自// SD 卡的临时数据的大小。 分配了两个具有此大小的缓冲区。 缓冲区大小
//必须足够大,以容纳预期的最长完整路径名称,包括
//文件名和尾随的空字符。
//
//
//////下面是 FatFs 使用的数据结构。
////
*****************
静态****FOFS g_sFatFs;//逻辑驱动器的工作区域(文件系统对象结构(FATFS))*//static
DIR g_sDirObject;//目录对象结构(DIR)*//static
FILINFOG_sFileInfo;//文件状态结构(FILINFO



)*//fFIL g_sFILE*;//静态文件结构(void)*/*(void
//
//保持 FRESULT 数字代码与
//字符串表示之间映射的结构。 从 FatFs FAT 文件//
系统驱动程序返回 FRESULT 代码。
////
*****************
typedef 结构
{
FRESULT iFResult;//文件函数返回代码(FRESULT)*
/ char * pcResultStr;
}
tFResultString;

//*************
//
//一个宏,可以轻松地将结果代码添加到表中。
////
*****************
#define FRESULT_Entry (f) {(f)、(#f)}//(字符串化)在宏定义

//中将宏参数转换为字符串常量(#f)
//
//保存数字 FRESULT 代码与字符
串//名称之间映射的表。 用于查找打印到
//控制台的错误代码。
////
*****************
tFResultString g_psFResultStrings[]=
{
FRESULT_Entry (FR_OK)、 /*(0)成功*/
FRESULT_Entry (FR_DISK_ERR)、 /*(1)在低级磁盘 I/O 层中发生硬错误*/
FRESULT_Entry (FR_INT_ERR)、 /*(2)断言失败*/
FRESULT_Entry (FR_NOT _READY)、 /*(3)物理驱动器无法正常工作*/
FRESULT_Entry (FR_NO_FILE)、 /*(4)找不到文件*/
FRESULT_entry (FR_NO_PATH), /*(5)找不到路径*/
FRESULT_Entry (FR_INVALID_NAME), /*(6)路径名格式无效*/
FRESULT_Entry (FR_Denied), /*(7)由于禁止的访问或目录已满而拒绝访问*/
FRESULT_entry (FR_Exists)、 /*(8)由于禁止访问而拒绝访问*/
FRESULT_Entry (FR_INVALID_OBJECT),/*(9)文件/目录对象无效*/
FRESULT_Entry (FR_WRITE_PROTECTED),/*(10)物理驱动器受写保护*/
FRESULT_Entry (FR_INVALID_DRIVE), /*(11)逻辑驱动器编号无效*/
FRESULT_Entry (FR_NOT _ENABLED), /*(12)卷没有工作区*/
FRESULT_Entry (FR_NO_filesystem)、 /*(13)没有有效的 FAT 卷*/
FRESULT_Entry (FR_mkfs_aborted)、 /*(14) f_mkfs()由于任何参数错误而中止*/
FRESULT_entry (FR_TIMEOUT), /*(15)无法在定义的时间段内获得访问卷的授权*/
FRESULT_Entry (FR_LOCKED)、 /*(16)根据文件共享策略拒绝该操作*/
FRESULT_Entry (FR_NOT _END_CORE)、/*(17)无法分配 LFN 工作缓冲区*/
FRESULT_Entry (FR_TOW_LOW_OPEN_FILES)、/*(18)打开文件数>_FS_SHARE */ FR_INIT
*(提供的参数


无效)
//
//保存结果代码数的宏。
////
*****************
#define NUM_FRESULT_CODES (sizeof (g_psFResultStrings)/ \
sizeof (tFResultString)//


*********
//
//此函数返回错误代码的字符串表示,该错误代码是
//从对 FatFs 的函数调用返回的。 它可用于打印人工
//可读错误消息。
////
*****************
const char * StringFromFResult (FRESULT iFResult)
{
uint_fast8_t ui8Idx;

//
输入循环以搜索错误代码表以查找匹配的错误代码。
//
for (ui8Idx = 0;ui8Idx < NUM_FRESULT_CODES;ui8Idx++)
{
//
如果找到匹配项,则返回错误代码的字符串名称。
//
if (g_psFResultStrings[ui8Idx].iFResult == iFResult)
{
return (g_psFResultStrings[ui8Idx].pcResResultStr);
}
//


此时未找到匹配的代码,因此返回一个字符串,指示
//未知错误。
//
return ("未知错误代码");
}

//*********
//
//这是该 SysTick 中断的处理程序。 FatFs 需要一个计时器节拍
//每10ms 用于内部计时。
////
*****************
void SysTickHandler (void)
{
disk_timerproc ();MMC-dk-tm4c123g.c 内的//function
}

//*************
//
//如果驱动程序库遇到错误,则调用的错误例程。
////
*****************
#ifdef debug
void __error__(char *dpcFilename、uint32_t ui32Line)
{

#endif

//*********
//
//配置 UART 及其引脚。 这必须在 UARTprintf()之前调用。
////
*****************
void ConfigureUART (void)
{
//
//启用用于 UART0引脚的 GPIO 端口 A。
// TODO:将其更改为您正在使用的 GPIO 端口。
//
ROM_SysCtlPeripheralEnable (SYSCTL_Periph_GPIOA);
//
//启用 UART0以便我们可以配置时钟。
//
ROM_SysCtlPeripheralEnable (SYSCTL_Periph_UART0);
//
//为端口 A0和 A1上的 UART0功能配置引脚复用。
//如果您的器件不支持引脚复用、则无需执行此步骤。
// TODO:更改此选项以选择您正在使用的端口/引脚。
//
ROM_GPIOPinConfigure (GPIO_PA0_U0RX);
ROM_GPIOPinConfigure (GPIO_PA1_U0TX);
//
//使用内部8MHz 振荡器作为 UART 时钟源。
//
// UARTClockSourceSet (UART0_BASE、UART_CLOCK _PIOSC);
ROM_GPIOPinTypeUART (GPIO_Porta_base、GPIO_PIN_0 | GPIO_PIN_1);
// UARTConfigSetExpClk (UART0_BASE、 SysCtlClockGet ()、115200、(UART_CONFIG_WLEN_8|UART_CONFIG_STOP_ONE|UART_CONFIG_PAR_NONE));
//
//为这些引脚选择替代(UART)功能。
// TODO:更改此选项以选择您正在使用的端口/引脚。
//
//ROM_GPIOPinTypeUART (GPIO_Porta_base、GPIO_PIN_0 | GPIO_PIN_1);
//ROM_UARTCharPut (UART0_BASE、'A');
//UARTClockSourceSet (UART0_BASE、UART_CLOCK_PIOSC);
//
//初始化控制台 I/O 的 UART
//
UARTStdioConfig (0、9600、80000);

UARTprintf ("\n\n\nSD 卡程序\n");

//SysCtlDelay (100);
}

//
//
//程序主函数。 它执行初始化、然后运行命令
//处理循环以从控制台读取命令。
////
*****************
int main (void)
{
//int nStatus;

FRESULT iFResult;
//
//为中断处理程序启用怠惰堆栈。 这允许使用浮点
//在中断处理程序中使用的指令,但代价是
//额外的堆栈用法。
ROM_FPULazyStackingEnable ();

//ROM_SysCtlClockSet (SYSCTL_SYSDIV_4|SYSCTL_USE_PLL | SYSCTL_8MHZ|SYSCTAL_OSC_MAIN);//8MHz 晶体振荡
器 ROM_SysCtlClockSet (SYSC_8MHZ);SYSC_UST_SYSC_UST_SHUTTOP_8MFFT;/SYSC_SYSC_UST_SYSC_SHUTTOP_8MHz
//
//为100Hz 中断配置 SysTick。 FatFs 驱动程序需要10ms
//勾选。
//
ROM_IntMasterEnable();
ROM_SysTickPeriodSet (SysCtlClockGet ()/100);
ROM_SysTickIntEnable();
ROM_SysTickEnable();


// SysTickInterruptenable
//IntMasterEnable ();//启用处理器的中断。
//SysTickPeriodSet (79997);//为 SysTick 计时器设置1ms 的周期。
//SysTickIntEnable();//启用 SysTick 中断。
//SysTickEnable();//启用 SysTick。 SysTickEnable();//启用 SysTick。



//SysCtlPeripheralEnable (SYSCTL_Periph_SSI0);
//while (!SysCtlPeripheralReady (SYSCTL_Periph_SSI0));
//SysCtlPeripheralEnable (SYSCTL_Periph_GPIOA);
//while (!SysCtlPeripheralReady (SYSCTL_Periph_SSI0)
;//配置 GPIO2_
//GPIOPinConfigure (GPIO_PA3_SSI0FSS);
//GPIOPinConfigure (GPIO_PA4_SSI0RX);
//GPIOPinConfigure (GPIO_PA5_SSI0TX);
//GPIOPinTypeSSI (GPIO_Porta_base、GPIO_PIN_5 | GPIO_PIN_4 |GPIO_3|GPIO_PIN_PIN_2);

//
//初始化 UART 作为文本 I/O 的控制台
//
ConfigureUART ();
SysCtlDelay (100);
UARTprintf ("\n\n\NSD 卡示例程序\n");

iFResult = f_mount (0、&g_sFatFS);//////*使用逻辑磁盘1装入文件系统。 //
if (iFResult!= FR_OK)
{
UARTprintf ("f_mount 错误:%s\n"、StringFromFResult (iFResult));
SysCtlDelay (1000);
return (1);
}

power_on ();

bool a = WAIT_READY ();//等待卡就绪

dstatus errd;

if (a){
send_initial_clock_train ();
errd = disk_initialize (0);
UARTprintf ("\n 正在初始化磁盘0。 状态=%i\n"、errd);
}
/*********

创建一个包含以下内容的 testfile.txt 文件

/
FIL fil; //填充:指向空文件对象结构

的指针 uint32_t count = 8*512;//多个写入块(4096bytes)
iFResult = f_open (&fil、"testfile.txt"、fa_new|fa_write);
SysCtlDelay (&SysCtlClockGet ()/3);

if ("testfile.txt"、fault_new|from_write|fault+



(&f);{&truned!\fault!"(&f)<printfault_result (&f);{fault_reswrite!"(&f);{&fault_fault_fault_from&f!!!!! %s\n"、StringFromFResult (iFResult);}
iFResult = f_close (&fil);
f_mount (0、NULL);

}

请帮助我解决该问题。

期待快速回复。

此致、

Alphy

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    您写了以下行、假设系统时钟为8MHz。
    UARTStdioConfig (0、9600、80000);

    但是、您还写道:
    ROM_SysCtlClockSet (SYSCTL_XTAL_8MHZ|SYSCTL_OSC_MAIN|SYSCTL_USE_OSC|SYSCTL_SYSDIV_5);//8MHz 晶体振荡器

    由于您使用的是 PLL、并且您选择的分频器为5、以上行将系统时钟配置为40MHz。 PLL VCO 输出为200MHz。 将200MHz 除以5后、只能得到40MHz。 因此、这将导致不正确的波特率。