与现代传感器接口:轮询 ADC 驱动器

嵌入式技术

1367人已加入

描述

一篇文章中,我们研究了开发人员应如何在现代嵌入式应用程序中创建一个接口,将低级驱动程序实现细节与应用程序代码分离。该接口提供了一种架构抽象,通过减少对硬件的依赖来提高应用程序代码的可伸缩性和可移植性。

现在我们将根据我们在微控制器的 3 种驱动程序设计技术中讨论的技术,开始研究开发人员可以实现 ADC 驱动程序的几种不同方法。在本文中,我们将更详细地研究如何使用轮询技术并讨论阻塞驱动程序和非阻塞驱动程序之间的区别。

阻止还是不阻止,这是个问题

在为微控制器开发任何驱动程序时,开发人员必须决定他们的驱动程序是阻塞还是非阻塞。阻塞驱动程序实质上会暂停代码执行,直到驱动程序完成其任务。例如,映射到 UART 的printf的典型实现是阻塞的。

当您拨打以下电话时:

printf(“你好世界!”);

开发人员知道,该语句后面的任何代码行在整个“Hello World!”之前都不会执行。语句已打印出UART。“你好世界!” 包含 12 个字节,96 位,但语句阻塞的时间量取决于 UART 波特率。对于配置为 1 Mbps 的 UART,您预计大约需要 96 微秒。对于配置为 9600 bps 的 UART,您预计大约需要 10,000 微秒!这是一个很大的差异,具体取决于硬件的配置方式,并且在将 UART 驱动程序配置为阻塞驱动程序时,它会显着影响程序的执行。

非阻塞驱动程序是在驱动程序完成其任务时不会停止程序执行的驱动程序。例如,可以配置printf和上一个示例中的 UART 驱动程序,使其不会阻塞,而是允许应用程序在每个字节从 UART 发送出去时继续执行。这可以在适当的情况下提高应用程序的效率,但需要额外的设置,例如使用中断、DMA 或至少一个传输缓冲区。

决定采用哪种方式设计驱动程序取决于您的应用程序和硬件。例如,如果 UART 配置为 1 Mbps,则从效率的角度来看,编写非阻塞驱动程序可能不会获得太多收益,并且实际上可能会导致比通过额外的程序复杂性解决的问题更多。但是,如果应用程序要求 9600 bps,其中应用程序代码被阻塞 10 毫秒,则使用非阻塞驱动程序可以显着提高程序效率,并且额外时序复杂性问题的风险要小得多,而且更易于管理。

嵌入式 ADC 驱动程序概述

需要注意的是,在一篇博客中,我无法完成编写完整 ADC 驱动程序所需的所有步骤。我可以轻松地在其上写一篇 20 页的论文或提供一个完整的网络研讨会,但它可能仍无法涵盖所有​​细节,但我们至少可以查看一些核心部分。

我们可以通过多种方式组织 ADC 驱动程序,但我喜欢组织它们的方式需要三个组件:

  • 低级驱动
  • 申请代码
  • 一个配置模块

低级驱动程序在初始化期间获取配置模块,并根据配置设置硬件。低级驱动程序提供了一个通用硬件抽象层 (HAL),然后应用程序代码可以使用该层。ADC HAL 调用应该是通用的,以便高级应用程序可以以任何必要的方式配置硬件,从而使其可重用和可扩展。例如,我过去使用的一些 ADC HAL 调用包括:

  • AdcError_t Adc_Init(const AdcConfig_t * Config);
  • AdcError_t Adc_StartConversion(void);
  • bool Adc_ConversionComplete(void);
  • 无效 Adc_RegisterWrite(uint32_t 常量地址,uint32_t 常量值);
  • uint32_t Adc_RegisterRead(uint32_t 地址);
  • void Adc_CallbackRegister(AdcCallback_t const Function, TYPE (*CallbackFunction)(type));

前三个 API 提供了初始化 ADC 硬件、启动转换然后检查转换状态的能力。最后三个函数旨在允许低级硬件的可扩展性。例如,如果 HAL 不提供应用程序所需的选项(例如转换单个 ADC 通道),则可以使用Adc_RegisterReadAdc_RegisterWrite函数扩展 HAL。这提供了基于应用程序需求的灵活性,而不会创建压倒性的 API。

编写一个简单的阻塞 ADC 驱动程序

我们可以在硬件层之上编写一个非常简单的 ADC 驱动程序。例如,我们可以创建一个名为Adc_Sample的简单函数,它启动 ADC 硬件,然后将所有结果存储在缓冲区中,然后应用程序可以访问该缓冲区。存储模拟值计数值的缓冲区不一定只需要存储一个值,而是可以存储多个值,这些值以后可以根据应用程序的需要进行平均或过滤。采样函数的阻塞版本可能如下所示:

adc

adc

正如您在此代码中看到的,while 循环会阻止执行,直到 ADC 硬件完成其转换,然后它将值存储在应用程序缓冲区中。

编写一个简单的非阻塞 ADC 驱动程序

 

将阻塞驱动程序转换为非阻塞代码非常简单,但需要更改更高级别的应用程序代码。例如,现在,如果应用程序想要对传感器进行采样,开发人员调用:

Adc_Sample();

在非阻塞版本中,开发人员必须检查Adc_Sample的返回值,以查看样本是否已完成并准备好使用。这允许示例在后台运行,应用程序代码继续运行,并对我们的驱动程序代码进行以下更新:

adc

adc

结论

正如我们在这篇文章中看到的,有多种方法可以编写 ADC,并且根据我们的需要,实现可以是阻塞的,也可以是非阻塞的。阻塞驱动程序往往比非阻塞驱动程序更简单且不完整,但它们可能效率低下。非阻塞驱动程序允许其他代码在驱动程序工作时运行,但应用程序代码仍然需要检查状态,这在轮询实现中本身是低效的。

在本系列的下一篇文章中,我们将研究如何编写一个应用程序,通过使用中断的 ADC 外设对传感器进行采样。

审核编辑 黄昊宇

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 相关推荐
  • adc

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分