我继承了一些使用 elm-chaN fatfs 的代码。它创建的目录和文件缺少或错误的日期时间戳。我已将问题追溯到似乎不正确的转换。
我更换了 Actor 阵容,一切似乎都顺利。但我希望更有经验的程序员确认原始转换的构造不正确(或编译器问题)
下面是原始代码:curTime 结构将 uint16_t 分配给“Year”。其他成员是 uint8_t 类型。它们需要按照 DOS 日期/时间位图格式打包成 32b 字 (DWORD)。
{
DWORD tmr;
/* Pack date and time into a DWORD variable */
Calendar curTime = sdInterface->sdGetRTCTime();
tmr = ((DWORD)(curTime.Year-1980)<<25)
| ((DWORD)(curTime.Month) << 21)
| ((DWORD)(curTime.DayOfMonth) << 16)
| (curTime.Hours << 11)
| (curTime.Minutes << 5)
| (curTime.Seconds >> 1); //modified to truncate into two second intervals - jn
return tmr;
}
下面是修改后的代码:我将小时、分钟和秒显式转换为 DWORD 类型。令人费解的是为什么原作者会转换 Month、DayOfMonth 而不是其他 uint8_t 类型。
DWORD get_fattime(void)
{
DWORD tmr;
/* Pack date and time into a DWORD variable */
Calendar curTime = sdInterface->sdGetRTCTime();
tmr = ((DWORD)(curTime.Year-1980)<<25)
| ((DWORD)(curTime.Month) << 21)
| ((DWORD)(curTime.DayOfMonth) << 16)
| ((DWORD)(curTime.Hours) << 11)
| ((DWORD)(curTime.Minutes) << 5)
| ((DWORD)(curTime.Seconds) >> 1); //modified to truncate into two second intervals - jn
return tmr;
}
代码似乎可以工作。希望有经验的程序员进行健全性检查。
我正在更新这篇文章以提供所需的信息:首先是结构日历 curTime。
//
//! \brief Used in the RTC_C_initCalendar() function as the CalendarTime
//! parameter.
//
//*****************************************************************************
typedef struct Calendar {
//! Seconds of minute between 0-59
uint8_t Seconds;
//! Minutes of hour between 0-59
uint8_t Minutes;
//! Hour of day between 0-23
uint8_t Hours;
//! Day of week between 0-6
uint8_t DayOfWeek;
//! Day of month between 1-31
uint8_t DayOfMonth;
//! Month between 1-12
uint8_t Month;
//! Year between 0-4095
uint16_t Year;
} Calendar;
下图显示了运行原始代码的 SD 卡的目录(没有对小时、分钟和时间 uint8_t 对象进行 DWORD 转换)。请注意其中两个文件缺少日期时间戳。这些目录也缺少日期时间戳。
下面的最后两张图显示了将 DWORD 应用于 uint9_t 对象的代码的结果。目录和文件现在都有日期时间戳。
从迄今为止收到的评论来看,我倾向于这是一个编译器错误。该代码是在早期版本的编译器上开发的。这是一个新的编译器 CCS v9。
最佳答案
[这并不是一个真正的答案,但对于评论来说太复杂了。]
请尝试这个程序:
#include <stdio.h>
int main()
{
uint8_t b = 9;
DWORD w1 = b << 6;
DWORD w2 = (DWORD)b << 6;
printf("%d %d\n", (int)w1, (int)w2);
}
该程序的预期输出是
576 576
右移 6 位相当于乘以 64,9 × 64 = 576,所以这是有道理的。
如果,另一方面,你得到输出
64 576
我相信这表明您的编译器中存在错误。如果您将 9 在 8 位字段内左移 6 位,就会得到 64,这意味着您会从左侧丢失一点。
这(几乎)是有道理的,这就是@jaz_n 发布的答案所要表达的意思。但是,您的编译器不应移动 8 位字段中剩余的任何内容。当你写的时候
x << 6
其中x
是类型uint8_t
,编译器应该做的第一件事是将x
提升为全角整数类型, 然后将其左移 6 位,该字段的宽度与机器上的 int
类型一样宽(通常为 16 位或 32 位)。 p>
这解释了为什么不需要对 DWORD
进行三个“额外”转换。您必须添加它们的事实表明您的编译器可能有问题。如果您的编译器为我的测试生成了打印 64 576
的代码,则这是您的编译器错误的额外证据。
关于C Actor : Is this expression coded correctly?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57631810/