利用mem数组在MM32 MicroPython中实现COMP的功能
简 介: 通过MicroPython中的数组mem对于MM32F3277内部的模拟比较器进行初步测试,验证了它的最基本的设置和工作关系。测试过程中也发现了MM32F3277的数据手册与对应的内部功能方面的问题:对于COMP控制寄存器偏移量描述错误,以及对于比较器的输出端口如何选择的问题。
关键词
: MM32F3277,mem,COMP
§01 mem操作COMP
一、mem数组
在MicroPython中存在一组数组可以直接访问MCU的内存,这组数组为:
- mem32
- mem16
- mem8
它们分别通过4字节,2字节,1字节访问MCU的RAM空间。使用他们可以按照 list的模式进行访问MCU内部的RAM。 对于mem32[addr]中的地址参数addr必须是4的整数倍数,mem16的地址参数则必须是2的整数倍数,mem8没有限制。
1、mem数组作用
前期,分别通过mem数字完成了对于MicroPython中的一些模块寄存器的访问。
通过实验可以看到,使用mem完成对于内存操作,可以在一定程度上加快运行速度,但是速度提高并不明显。
尽管如此,对于MicroPython内核中没有支持的功能,通过mem数组访问可以完成MCU内部的模块的操作。比如对于其中的CRC,UART,GPIO的直接操作。
下面,对于MM32F3277内部的模拟比较器COMP模块进行直接访问。
2、COMP模块
(1)COMP时钟
在MM32F3277内部具有两个模拟比较器,COMP1,COMP2,它们挂载在内部APB2上。
▲ 图1.1.1 COMP1,2 时钟
COMP的输入时钟与APB2_CLK同步。在使用比较器之前,要先使能RCC控制器中的时钟使能控制位。配置RCC控制器中的软件复位请求可进行软件复位操作。
▲ 图1.1.2 APB2 中的COMP1,2使能
/// @brief RCC Base Address Definition
#define RCC_BASE (AHBPERIPH_BASE + 0x1000) ///< Base Address: 0x40021000
/// @brief RCC Register Structure Definition
typedef struct {
__IO u32 CR; ///< Control Register offset: 0x00
__IO u32 CFGR; ///< Configuration Register offset: 0x04
__IO u32 CIR; ///< Clock Interrupt Register offset: 0x08
__IO u32 AHB3RSTR; ///< Advanced High Performance Bus 3 Reset Register offset: 0x0C
__IO u32 AHB2RSTR; ///< Advanced High Performance Bus 2 Reset Register offset: 0x10
__IO u32 AHBRSTR; ///< Advanced High Performance Bus 1 Reset Register offset: 0x14
__IO u32 APB2RSTR; ///< Advanced Peripheral Bus 2 Reset Register offset: 0x18
__IO u32 APB1RSTR; ///< Advanced Peripheral Bus 1 Reset Register offset: 0x1C
__IO u32 AHB3ENR; ///< Advanced High Performance Bus 3 Enable Register offset: 0x20
__IO u32 AHB2ENR; ///< Advanced High Performance Bus 2 Enable Register offset: 0x24
union {
__IO u32 AHBENR; ///< Advanced High Performance Bus 1 Enable Register offset: 0x28
__IO u32 AHB1ENR;
};
__IO u32 APB2ENR; ///< Advanced Peripheral Bus 2 Enable Register offset: 0x2C
__IO u32 APB1ENR; ///< Advanced Peripheral Bus 1 Enable Register offset: 0x30
__IO u32 BDCR; ///< Backup Domain Control Register offset: 0x34
__IO u32 CSR; ///< Control Status Register offset: 0x38
__IO u32 SYSCFGR; ///< System Configuration Register offset: 0x3C
__IO u32 CFGR2; ///< System Configuration Register offset: 0x40
__IO u32 ICSCR; ///< Internal clock source calibration register offset: 0x44
__IO u32 PLLCFGR; ///< PLL configures registers offset: 0x48
u32 Reserved1[13]; ///< Reserved space
__IO u32 HSIDLY; ///< HSI delay register offset: 0x80
__IO u32 HSEDLY; ///< HSE delay register offset: 0x84
__IO u32 PLLDLY; ///< PLL delay register offset: 0x88
} RCC_TypeDef;
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
对于RCC中的APB2的地址为:
RCC_BASE = 0x40021000
APB2ENR = 11*4
APB1ENR = 12*4
- 1
- 2
- 3
(2)COMP BASE
/// @brief COMP Base Address Definition
#define COMP_BASE (APB2PERIPH_BASE + 0x4000) ///< Base Address: 0x40014000
/// @brief Comparators Register Structure Definition
typedef struct {
__IO u32 RESERVED1; ///< offset: 0x00
__IO u32 RESERVED2; ///< offset: 0x04
__IO u32 RESERVED3; ///< offset: 0x08
union {
__IO u32 CSR1; ///< COMP1 Control Status Register offset: 0x0C
__IO u32 COMP1_CSR;
};
union {
__IO u32 CSR2; ///< COMP2 Control Status Register offset: 0x10
__IO u32 COMP2_CSR;
};
__IO u32 RESERVED4; ///< offset: 0x14
union {
__IO u32 CRV; ///< COMP external reference voltage register offset: 0x18
__IO u32 COMP_CRV;
};
union {
__IO u32 POLL1; ///< COMP1 polling register offset: 0x1C
__IO u32 COMP1_POLL;
};
union {
__IO u32 POLL2; ///< COMP2 polling register offset: 0x20
__IO u32 COMP2_POLL;
};
} COMP_TypeDef;
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
注意到,上述结构定义中,对于比较器的地址与数据手册上的定义不一样!
▲ 图1.1.3 数据手册上的寄存器地址
(3)功能框图
如下是MM32F3277数据手册上的COMP1,2功能框图。
▲ 图1.1.4 COMP1,2功能框图
通过系统框图可以看到,两个模拟比较器的INP可以选择: PA[0], PA[1],PA[2],PA[3]
INM可以输入:CRV,PA[0]/PA[2], PA[5],PA[4]
二、初步测试
1、时钟操作
(1)基本操作
from machine import Pin,mem32
import utime
from micropython import const
RCC_BASE = const(0x40021000)
APB2ENR = const(RCC_BASE+11*4)
APB1ENR = const(RCC_BASE+12*4)
print('%08x'%mem32[APB2ENR])
print('%08x'%mem32[APB1ENR])
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
输出结果:
00000113
10000036
- 1
- 2
▲ 图1.2.1 APB2时钟允许位置
▲ 图1.2.2 APB1时钟允许位
(2)增加UART2
增加了一个对于UART2初始化。
uart2 = UART(1, 115200)
print('%08x'%mem32[APB2ENR])
print('%08x'%mem32[APB1ENR])
- 1
- 2
- 3
- 4
程序运行结果:
00000113
10020036
- 1
- 2
可以看到对应的APB1中的多了对应的UART2的初始化。
▲ 图1.2.3 APB1时钟允许位置
(3)允许COMP1,2
RCC_BASE = const(0x40021000)
APB2ENR = const(RCC_BASE+11*4)
APB1ENR = const(RCC_BASE+12*4)
mem32[APB2ENR] |= 0x8000
print('%08x'%mem32[APB2ENR])
print('%08x'%mem32[APB1ENR])
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
运行的结果为:
00008113
10020036
- 1
- 2
此时对应COMP1,2时钟被允许。
2、COMP寄存器
▲ 图1.2.4 控制寄存器
(1)读取初始值
COMP_BASE = const(0x40014000)
COMP_CSR1 = const(COMP_BASE+0xc)
COMP_CSR2 = const(COMP_BASE+0x10)
COMP_CRV = const(COMP_BASE+0x18)
COMP_POLL1 = const(COMP_BASE+0x1c)
COMP_POLL2 = const(COMP_BASE+0x20)
print('%08x'%mem32[COMP_CSR1])
print('%08x'%mem32[COMP_CSR2])
print('%08x'%mem32[COMP_CRV])
print('%08x'%mem32[COMP_POLL1])
print('%08x'%mem32[COMP_POLL2])
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
初始的值:
00000000
00000000
00000000
00000000
00000000
- 1
- 2
- 3
- 4
- 5
(2)使能COMP12
mem32[COMP_CSR1] |= 0x1
mem32[COMP_CSR2] |= 0x1
print('%08x'%mem32[COMP_CSR1])
print('%08x'%mem32[COMP_CSR2])
- 1
- 2
- 3
- 4
00000001
40000001
- 1
- 2
比较奇怪的是,现在两个比较器的设置都是一样的,但是它们的OUT却不一致!
3、设置外部电压
(1)分别将PA0,PA4置成高低电平
▲ 图1.2.5 将PA0
输出结果:
40000001
40000001
- 1
- 2
(2)分别将PA0,PA4置成低、高电平
输出结果:
00000001
00000001
- 1
- 2
以上在CSR中的OUT位置反映的结果是外部电压变化的结果。
4、COMP输出信号
通过COMP内部结构,可以看到OUT的输出管脚对应PA[6]/PA[2]。但是在CSR控制OUT_SEL中并没有给出输出到PA6,PA2的选项。
▲ 图1.2.6 输出选择控制
下面只能通过软件来测试。
通过软件对于OUT_SEL设置从0 ~ 15,但是对应的PA6,没有任何变化。无论检测OUT如何声明:
out = Pin('PA6', Pin.AF_PUSHPULL)
- 1
三、测试CRV
将比较器的INM的输入设置为CRV,可以将比较器的负输入端设置为内部参考电压。
1、寄存器设置
mem32[COMP_CSR1] = (0x1 | 0x30)
mem32[COMP_CSR2] = (0x1 | 0x30)
mem32[COMP_CRV] = (0x3F)
print('%08x'%mem32[COMP_CSR1])
print('%08x'%mem32[COMP_CSR2])
print('%08x'%mem32[COMP_CRV])
- 1
- 2
- 3
- 4
- 5
- 6
此时对应的:
- SRV-SRC: 1 : 对应VDDA;
- CRV_EN: 为1:,使能参考电压。
如果设置PA0为3.3V,此时输出为:
40000031
40000031
0000003f
- 1
- 2
- 3
如果设置PA0为0V,此时输出为:
00000031
00000031
0000003f
- 1
- 2
- 3
这说明比较器大体工作正常。
2、设置PA0位1/2 VCC
通过电位器设置PA0为1.66V。
▲ 图1.3.1 使用电位器将PA0设置为1.66V
(1)设置CRV
陆续设置CRV从0 ~ 0xf,分别读出OUT的值。
for i in range(16):
mem32[COMP_CRV] = 0x30 | i
print('%d, %08x'%(i, mem32[COMP_CSR1]))
- 1
- 2
- 3
(2)测试结果
0, 40000031
1, 40000031
2, 40000031
3, 40000031
4, 40000031
5, 40000031
6, 40000031
7, 40000031
8, 40000031
9, 00000031
10, 00000031
11, 00000031
12, 00000031
13, 00000031
14, 00000031
15, 00000031
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
可以看到此时,对应的CRV在8 至9 之间发生了转变。此时它们分别对应:
- 9/20×VDDA = 1.484V
- 10/20×VDDA=1.65V
这的确是在设置中电电位附近。
3、设置PA0为2V
使用电位器设置PA0位2V。运行上面程序,输出为:
0, 40000031
1, 40000031
2, 40000031
3, 40000031
4, 40000031
5, 40000031
6, 40000031
7, 40000031
8, 40000031
9, 40000031
10, 40000031
11, 00000031
12, 00000031
13, 00000031
14, 00000031
15, 00000031
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
※ 总 结 ※
通过MicroPython中的数组mem对于MM32F3277内部的模拟比较器进行初步测试,验证了它的最基本的设置和工作关系。
测试过程中也发现了MM32F3277的数据手册与对应的内部功能方面的问题:对于寄存器偏移量描述错误,以及对于比较器的输出端口如何选择的问题。
一、存在问题
1、比较器偏移量
在数据手册 29.5 比较器寄存器描述中,对于CSR的Offset描述是错误的。
▲ 图2.1.1 数据手册中对于COMP偏移量描述错误
2、比较器输出
手册中,对于比较器的输出为PA6,PA2,可是如何能够设置。现在无法测试到这个输出信号。
▲ 图2.1.3 如何能够设置比较器的输出为PA6,PA2
■ 实验程序
#!/usr/local/bin/python
# -*- coding: gbk -*-
#============================================================
# TEST1.PY -- by Dr. ZhuoQing 2021-12-05
#
# Note:
#============================================================
from machine import Pin,mem32,UART
import utime
from micropython import const
#------------------------------------------------------------
led = Pin('PB2', Pin.OUT_PUSHPULL)
out1 = Pin('PA6', Pin.AF_PUSHPULL)
out1 = Pin('PA2', Pin.AF_PUSHPULL)
#------------------------------------------------------------
RCC_BASE = const(0x40021000)
APB2ENR = const(RCC_BASE+11*4)
APB1ENR = const(RCC_BASE+12*4)
mem32[APB2ENR] |= 0x8000
#print('%08x'%mem32[APB2ENR])
#print('%08x'%mem32[APB1ENR])
#------------------------------------------------------------
COMP_BASE = const(0x40014000)
COMP_CSR1 = const(COMP_BASE+0xc)
COMP_CSR2 = const(COMP_BASE+0x10)
COMP_CRV = const(COMP_BASE+0x18)
COMP_POLL1 = const(COMP_BASE+0x1c)
COMP_POLL2 = const(COMP_BASE+0x20)
#print('%08x'%mem32[COMP_CSR1])
#print('%08x'%mem32[COMP_CSR2])
#print('%08x'%mem32[COMP_CRV])
#print('%08x'%mem32[COMP_POLL1])
#print('%08x'%mem32[COMP_POLL2])
#------------------------------------------------------------
mem32[COMP_CSR1] = (0x1 | 0x30)
mem32[COMP_CSR2] = (0x1 | 0x30)
mem32[COMP_CRV] = (0x3F)
#print('%08x'%mem32[COMP_CSR1])
#print('%08x'%mem32[COMP_CSR2])
#print('%08x'%mem32[COMP_CRV])
#------------------------------------------------------------
for i in range(16):
mem32[COMP_CRV] = 0x30 | i
print('%d, %08x'%(i, mem32[COMP_CSR1]))
while True:
led.high()
utime.sleep_ms(50)
led.low()
utime.sleep_ms(50)
#------------------------------------------------------------
# END OF FILE : TEST1.PY
#============================================================
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
■ 相关文献链接:
● 相关图表链接:
- 图1.1.1 COMP1,2 时钟
- 图1.1.2 APB2 中的COMP1,2使能
- 图1.1.3 数据手册上的寄存器地址
- 图1.1.4 COMP1,2功能框图
- 图1.2.1 APB2时钟允许位置
- 图1.2.2 APB1时钟允许位
- 图1.2.3 APB1时钟允许位置
- 图1.2.4 控制寄存器
- 图1.2.5 将PA0
- 图1.2.6 输出选择控制
- 图1.3.1 使用电位器将PA0设置为1.66V
- 图2.1.2 数据手册描述错误
- 图2.1.3 如何能够设置比较器的输出为PA6,PA2
文章来源: zhuoqing.blog.csdn.net,作者:卓晴,版权归原作者所有,如需转载,请联系作者。
原文链接:zhuoqing.blog.csdn.net/article/details/121734344
- 点赞
- 收藏
- 关注作者
评论(0)