面试题答案
一键面试假设硬件寄存器功能和操作要求如下:
假设有一个控制LED的寄存器组,位于地址0x40000000开始的内存空间。
- 控制寄存器(Control Register, CR):
- 地址:0x40000000
- 功能:控制LED的亮灭。第0位为1时LED亮,为0时LED灭。
- 状态寄存器(Status Register, SR):
- 地址:0x40000004
- 功能:表示LED当前的状态。第0位为1时表示LED亮,为0时表示LED灭。
C语言代码实现:
#include <stdint.h>
// 定义寄存器结构体
typedef struct {
volatile uint32_t CR; // 控制寄存器
volatile uint32_t SR; // 状态寄存器
} LED_Registers;
// 定义寄存器基地址
#define LED_BASE_ADDR ((LED_Registers *)0x40000000)
// 初始化函数
void LED_Init(void) {
LED_Registers *ledRegs = LED_BASE_ADDR;
ledRegs->CR = 0; // 初始LED为灭
}
// 控制LED亮灭函数
void LED_Control(uint8_t onOff) {
LED_Registers *ledRegs = LED_BASE_ADDR;
if (onOff) {
ledRegs->CR |= 1; // 置第0位为1,LED亮
} else {
ledRegs->CR &= ~1; // 清第0位为0,LED灭
}
}
// 读取LED状态函数
uint8_t LED_GetStatus(void) {
LED_Registers *ledRegs = LED_BASE_ADDR;
return (ledRegs->SR & 1)? 1 : 0; // 返回第0位的值
}
在上述代码中:
- 寄存器结构体定义:通过
typedef struct
定义了一个包含控制寄存器CR
和状态寄存器SR
的结构体LED_Registers
,使用volatile
关键字确保编译器不会对这些寄存器访问进行优化,因为它们的值可能会被硬件异步修改。 - 寄存器基地址定义:通过
#define
将0x40000000
地址强制转换为LED_Registers
类型的指针,方便后续对寄存器的访问。 - 初始化函数
LED_Init
:将控制寄存器CR
清零,使LED初始为灭。 - 控制函数
LED_Control
:根据传入的参数onOff
,通过位操作设置或清除控制寄存器CR
的第0位,从而控制LED的亮灭。 - 状态读取函数
LED_GetStatus
:读取状态寄存器SR
的第0位,返回LED当前的状态。