嵌入式基础问题1,2,3

发布时间 2023-12-22 16:26:32作者: 李宜时

图片中的寄存器结构表示了一个16位的时间格式,其中包含了小时、分钟和秒。这个16位的寄存器被分为三个部分:

  • 位15到位11表示小时(Hours),总共5位。
  • 位10到位5表示分钟(Minutes),也是6位。
  • 位4到位0表示秒(Seconds),这里注意到是“Seconds + 2”,意味着这5位的值需要加上2才是实际的秒数。

这样的设计通常用于嵌入式系统或硬件级时间管理。

  1. 首先,给出TIME的注释,以便于其他开发者理解这个地址映射到的寄存器的结构。注释可以这样写:
// TIME寄存器地址映射
// | 15 - 11 |    10 - 5    |   4 - 0   |
// |  Hours  |    Minutes   | Seconds+2 |
// TIME地址指向的16位寄存器,高5位为小时,接下来6位为分钟,低5位表示实际秒数加2。
  1. 定义基于16位寄存器的宏,用于从这个寄存器中获取实际的小时、分钟和秒数:
#define HOURS_MASK 0xF800  // 小时掩码,用于获取小时的值
#define MINUTES_MASK 0x07E0 // 分钟掩码,用于获取分钟的值
#define SECONDS_MASK 0x001F // 秒掩码,用于获取秒的值(需要减去2)

#define GET_HOURS(time) (((time) & HOURS_MASK) >> 11) // 获取小时
#define GET_MINUTES(time) (((time) & MINUTES_MASK) >> 5) // 获取分钟
#define GET_SECONDS(time) (((time) & SECONDS_MASK) << 1) // 获取秒数并减去2

在使用这些宏时,你需要提供16位的时间寄存器值作为参数time。例如,如果你想获取时间寄存器的小时数,可以使用GET_HOURS(TIME)。这里的TIME应该是一个16位的数值,代表时间寄存器当前的值。
要实现setSecondgetSecond函数,我们可以使用两种不同的方法:位运算和位域。以下是两种方法的实现:

方法一:使用位运算

time11051.c文件中,你可以使用之前定义的宏,或者直接进行位操作。下面的代码示例使用了直接位操作的方式:

#include "time1105.h"

// 假设TIME为全局变量的指针地址,这里声明为外部变量以便链接
extern unsigned int *TIME;

void setSecond(int second) {
    // 确保传入的秒数是有效的
    second = second - 2; // 减去2以符合寄存器的存储方式
    *TIME = (*TIME & ~SECONDS_MASK) | ((second & SECONDS_MASK) << 1);
}

int getSecond() {
    return ((*TIME >> 1) & SECONDS_MASK) + 2;
}

time1105.h头文件中,声明这些函数和宏:

#ifndef TIME1105_H
#define TIME1105_H

#define SECONDS_MASK 0x001F // 秒掩码

void setSecond(int second);
int getSecond();

#endif // TIME1105_H

方法二:使用位域

time11052.c文件中,我们可以使用结构体和位域来访问特定的时间部分。这是一个更为直观和结构化的方法:

#include "time1105.h"

// 假设TIME为全局变量的指针地址,这里声明为外部变量以便链接
extern unsigned int *TIME;

typedef struct time_struct {
    unsigned int seconds : 5;
    unsigned int minutes : 6;
    unsigned int hours : 5;
} TimeStruct;

void setSecond(int second) {
    TimeStruct *timePtr = (TimeStruct *)TIME;
    timePtr->seconds = second - 2; // 减去2以符合寄存器的存储方式
}

int getSecond() {
    TimeStruct *timePtr = (TimeStruct *)TIME;
    return timePtr->seconds + 2;
}

time1105.h头文件中,你只需要声明这两个函数,因为位域结构是在.c文件中定义的:

#ifndef TIME1105_H
#define TIME1105_H

void setSecond(int second);
int getSecond();

#endif // TIME1105_H

请注意,为了简化代码,我假设TIME是一个全局变量的指针地址,并且已经在某个地方声明和初始化。如果TIME是一个宏定义的地址,那么你需要根据实际情况对代码进行相应的调整。同样,这里的SECONDS_MASK宏和位域的具体数值可能需要根据实际的时间寄存器地址和位模式进行调整。