为了与硬件外设或系统模块进行交互,我们需要使用设备驱动程序(简称驱动程序),它是处理按需配置硬件的底层细节的软件。在 nRF Connect SDK 中,驱动程序的实现与其 API 是高度解耦的。这基本上意味着我们可以在不修改应用程序的情况下更换底层驱动实现,因为我们可以使用相同的通用 API。
这种解耦具有许多优点,包括高度的可移植性,因为它使得在不同的板卡上使用相同的代码成为可能,而无需手动修改底层的驱动实现。
应用程序通过通用 API 与硬件进行交互,方法是使用宏 DEVICE_DT_GET() 或相关宏获取相关硬件的设备指针。
虽然也可以通过 device_get_binding() 获取设备指针,但现在已不再推荐这种做法。
与之前使用 device_get_binding() 检索设备指针的做法相反,使用 DEVICE_DT_GET() 的好处是,如果驱动程序没有分配该设备(例如,如果该设备在设备树中不存在或状态为禁用),则会在编译时报错。
此外,与 device_get_binding() 不同,它不执行运行时字符串比较,这在某些情况下可能会影响性能。
Zephyr 设备模型负责通用 API 与设备驱动程序实现之间的关联。

宏 DEVICE_DT_GET() 的签名如下所示:

要获取设备指针,您需要传递设备树节点标识符。正如“设备树”部分所述,有多种方法可以获取节点标识符。两种常见的方法是通过宏使用节点标签 DT_NODELABEL() 以及通过宏使用别名 DT_ALIAS().
在使用设备指针之前,应使用 device_is_ready() 对其进行检查,其签名如下:

device_is_ready() 将检查设备是否已准备好使用,例如,是否已正确初始化。
以下代码片段将获取由 DT_NODELABEL() 返回的设备树节点标识符,并返回指向设备对象的指针。然后 device_is_ready() 验证设备是否已准备就绪,即处于可以使用其标准 API 的状态。
const struct device *dev;
dev = DEVICE_DT_GET(DT_NODELABEL(uart0));
if (!device_is_ready(dev)) {
return;
}C要使用设备驱动程序通用 API,您必须拥有一个 const struct device 类型的指针来指向其实现。您需要为每个外设实例执行此操作。例如,如果您有两个 UART 外设(&uart0 和 &uart1)并且想要同时使用它们,则必须拥有两个独立的 const struct device 类型指针。
换句话说,您需要对 DEVICE_DT_GET() 进行两次不同的调用。
大多数外设 API 都有特定于该外设的 DEVICE_DT_GET() 和 device_is_ready() 的等效项。例如,对于 GPIO 外设,有 GPIO_DT_SPEC_GET() 和 gpio_is_ready_dt()。
这些是使用外设的推荐方式,因为它们从设备树结构中收集了更多关于外设的信息,并减少了在应用程序代码中添加外设配置的需求。