利用mem数组在MM32 MicroPython中实现COMP的功能

举报
tsinghuazhuoqing 发表于 2021/12/26 01:33:37 2021/12/26
【摘要】 简 介: 通过MicroPython中的数组mem对于MM32F3277内部的模拟比较器进行初步测试,验证了它的最基本的设置和工作关系。测试过程中也发现了MM32F3277的数据手册与对应的内部功能...

简 介: 通过MicroPython中的数组mem对于MM32F3277内部的模拟比较器进行初步测试,验证了它的最基本的设置和工作关系。测试过程中也发现了MM32F3277的数据手册与对应的内部功能方面的问题:对于COMP控制寄存器偏移量描述错误,以及对于比较器的输出端口如何选择的问题。

关键词 MM32F3277memCOMP

mem操作COMP
文章目录
mem数组
初步测试
测试CRV
总 结
存在问题
实验程序

§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 时钟

▲ 图1.1.1 COMP1,2 时钟

  COMP的输入时钟与APB2_CLK同步。在使用比较器之前,要先使能RCC控制器中的时钟使能控制位。配置RCC控制器中的软件复位请求可进行软件复位操作。

▲ 图1.1.2 APB2 中的COMP1,2使能

▲ 图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 数据手册上的寄存器地址

▲ 图1.1.3 数据手册上的寄存器地址

(3)功能框图

  如下是MM32F3277数据手册上的COMP1,2功能框图。

▲ 图1.1.4 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.1 APB2时钟允许位置

▲ 图1.2.2 APB1时钟允许位

▲ 图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时钟允许位置

▲ 图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.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

▲ 图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 输出选择控制

▲ 图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.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.1.1 数据手册中对于COMP偏移量描述错误

2、比较器输出

  手册中,对于比较器的输出为PA6,PA2,可是如何能够设置。现在无法测试到这个输出信号。

▲ 图2.1.3 如何能够设置比较器的输出为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


■ 相关文献链接:

● 相关图表链接:

文章来源: zhuoqing.blog.csdn.net,作者:卓晴,版权归原作者所有,如需转载,请联系作者。

原文链接:zhuoqing.blog.csdn.net/article/details/121734344

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。