本文主要是介绍在mm32f3270上为micropython创建ADC模块(1),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
在mm32f3270上为micropython创建ADC模块
苏勇,2021年10月
文章目录
- 在mm32f3270上为micropython创建ADC模块
- micropython中对ADC模块的接口定义
- 设计实现
- F3270片上资源
micropython中对ADC模块的接口定义
ADC是模拟到数字转换器。
micropython的官方说明文档中,有明确的对ADC模块的接口定义,见:
https://docs.micropython.org/en/latest/library/machine.ADC.html
ADC模块同其它硬件相关外设模块一样,归属于machine模块。它的用法是:
from machine import ADCadc0 = ADC(pin)
val0 = adc.read_u16()
其中,
- 构造函数machine.ADC(id)的输入参数id,可以是一个ADC转换的通道号,也可以是一个引脚对象。
- machine.read_u16()函数返回当前通道ADC的采样结果,有效数据宽度16位。
设计实现
- 关于ADC模块的实例化参数“id”,如果传通道号,倒是容易实现,但如果是传入引脚号,可能会面临一些麻烦:
- 指定的IO引脚可能没有ADC的功能,要考虑一种报错的机制,比如抛异常神马的。
- 通过IO引脚要倒排查询到ADC的通道号,最后执行转换,还是要用ADC通道的。或者可以使用micropython中的map实现。
我感觉第二种方法对用户更友好。从面向对象的角度,用户看到的是引脚,才不关心内部是怎么分配的引脚号,实际转换的时候,用户也看不到分配的通道号,操作的是引脚对象而已。
pin0 = Pin('PA2', mode=Pin.IN_ANALOG)
adc0 = ADC(pin0)val0 = adc0.read_u16()
此时需要在代码中建立第一张表格,通过引脚找通道。
同时,ADC()也可以支持直接传入通道号,这就需要在代码中建立第二张表格,通过通道找引脚。
总之,经过ADC()函数之后,要确保初始化引脚和ADC通道入队都要搞定。
另外,在import ADC时,要执行启用ADC转换器时钟的操作。额,算了,ADC可能不是一个单独的模块。但这里还是要看一下,有没有import本身就可以执行的函数。再算了,可能micropython中没有提供这样的接口。至于启动队列,可以在每次调用ADC()添加新引脚的时候查看,默认是关闭转换的,只有当扫描队列中有数时,才初始化ADC(启动ADC时钟,初始化转换器),并启动转换,当通过审查发现扫描队列没有数,则关停扫描队列。
- 关于read_u16读数的操作
硬件上每次启动ADC转换,都是要等一小会才能拿到转换结果。如果想立刻拿到数,可以用周期触发并缓存最近转换结果的做法,但这要求预先就要指定好转换通道,让转换器后台运行。
当然,预先指定通道的事情,可以让ADC()实例化函数搞一下,当实例化一个ADC采样通道时,实际上后台已经开始转换了,并且周期地将最近一次转换结果保存到一个缓冲区中,这样当启动read_u16函数时,可以直接从缓冲区中读到最近的采样结果,这样做可以保证读数时直接拿到结果,不等待,但特别费电,ADC转换器在后台一直不停地工作。
考虑到可能同时启用多个ADC通道,需要在软件上将转换通道串成一个队列,最好硬件上也仅使用一个ADC转换器,这样刚好结合硬件的转换队列实现这个功能。
要以最快速度进行转换,只能用DMA。如果用中断,会严重影响CPU执行正常语句的效率。硬件提供了连续转换模式,不错不错。
另一种实现方法比较简单,在read_u16()函数执行时才启动转换,如此这样,就要等转换完成之后才能返回转换结果。这样实现比较简单,也比较省电,就是会卡住主程序,这样不好。
- 关于read_u16读数的结果
官网文档中明确说明,最小值为0,最大值为65525,这是16位ADC的区间。如果是12位ADC,就左对齐,从而满足有效数据表示范围的边界条件。
- 关于引脚复用功能设定
当在ADC模块的实例化函数中获得指定引脚之后,程序需要找到对应的IO引脚,并重新将其AF功能设定成指定ADC。
F3270片上资源
以仅使用ADC1为例。
- 关于引脚资源
- ADC1 有 14 路外部输入通道和 2 路内部通道,总计16个通道
- ADC1 有 14 路外部输入通道 0 - 13、内部温度传感器通道 14 和内部 1.2V 参考电压通道 15
ADC Channel ID | IO Pin |
---|---|
ADC1_CH0 | PA0 |
ADC1_CH1 | PA1 |
ADC1_CH2 | PA2 |
ADC1_CH3 | PA3 |
ADC1_CH4 | PA4 |
ADC1_CH5 | PA5 |
ADC1_CH6 | PA6 |
ADC1_CH7 | PA7 |
ADC1_CH8 | PB0 |
ADC1_CH9 | PB1 |
ADC1_CH10 | PC0 |
ADC1_CH11 | PC1 |
ADC1_CH12 | PC2 |
ADC1_CH13 | PC3 |
ADC1_CH14 | Sensor |
ADC1_CH15 | 1.2V reference voltage |
其实只要做一个表格就好,字符串队列:
const char *mp_map_adc_pin[] = { "PA0", "PA1", "PA2", ... };
大不了传引脚编号的时候,做一下倒排查询就好。
- 关于ADC值转换器
F3270上的ADC支持“扫描队列”和“连续扫描模式”。
从手册上看到,在硬件上为每个转换通道预留了寄存器,那么软件就不用准备缓冲区了。
这篇关于在mm32f3270上为micropython创建ADC模块(1)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!