嵌入式开发工程师如何在现代嵌入式应用程序中创建一个接口,该接口将低级驱动程序实现细节与应用程序代码分离。该接口提供了一种体系结构抽象,它通过减少对硬件的依赖来提高应用程序代码的可伸缩性和可移植性。
现在,我们将基于在3种微控制器驱动器设计技术中讨论的技术,开始研究嵌入式开发工程师实现ADC驱动器的几种不同方式。在本文中,我们将更详细地研究如何使用轮询技术,并讨论阻塞驱动程序和非阻塞驱动程序之间的区别。
要阻止还是不阻止,这就是问题
在为微控制器开发任何驱动程序时,嵌入式开发工程师必须决定其驱动程序是阻塞还是非阻塞。阻塞驱动程序实质上会暂停代码执行,直到驱动程序完成其任务为止。例如,映射到UART的printf的典型实现是阻塞。
当您拨打电话时,例如:
printf(“ Hello World!”);
嵌入式开发工程师知道,该语句之后的任何代码行都不会执行,直到整个“ 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);
void Adc_RegisterWrite(uint32_t const Address,uint32_t const Value);
uint32_t Adc_RegisterRead(uint32_t地址);
void Adc_CallbackRegister(AdcCallback_t const Function,TYPE(* CallbackFunction)(type));
前三个API提供了以下功能:初始化ADC硬件,开始转换,然后检查转换状态。最后三个功能旨在允许扩展到低级硬件。例如,如果HAL不提供应用程序所需的选项,例如转换单个ADC通道,则可以使用Adc_RegisterRead和Adc_RegisterWrite函数扩展HAL 。这提供了基于应用程序需求的灵活性,而无需创建压倒性的API。
编写一个简单的阻塞ADC驱动器
我们可以编写一个在硬件层之上的非常简单的ADC驱动程序。例如,我们可以创建一个名为Adc_Sample的简单函数,该函数启动ADC硬件,然后将所有结果存储在缓冲区中,然后可由应用程序访问。存储模拟值计数值的缓冲区不必只存储一个值,而是可以存储多个值,这些值以后可以根据应用程序的需要进行平均或过滤。采样功能的阻塞版本可能类似于以下内容:
如您在此代码中所见,while循环阻塞执行,直到ADC硬件完成其转换,然后将值存储在应用程序缓冲区中。
编写一个简单的非阻塞ADC驱动器
将阻塞驱动程序转换为非阻塞代码非常简单,但是这需要更改更高级别的应用程序代码。例如,现在,如果应用程序要对传感器进行采样,则嵌入式开发工程师将调用:
Adc_Sample();
在非阻塞版本中,嵌入式开发工程师必须检查Adc_Sample的返回值,以查看样本是否已完成并可以使用。这使示例可以在后台运行,应用程序代码可以在对我们的驱动程序代码进行以下更新后继续运行:
结论
正如我们在这篇文章中所看到的,有多种编写ADC的方法,并且根据我们的需要,实现可以是阻塞的或非阻塞的。与非阻塞驱动程序相比,阻塞驱动程序往往更简单且不完整,但是它们可能效率不高。非阻塞驱动程序允许其他代码在驱动程序运行时运行,但是应用程序代码仍然需要检入本身在轮询实现中效率低下的状态。