本帖最后由 catnull 于 2022-3-6 15:00 编辑
在N32G457VEL (n32g45xvl-stb)开发板上试验RT_Thread microPython
论坛上有一个RT_Thread 的比赛,也是基于N32G45xvl-stb板卡的,有一些关于RT-Thread操作系统下面制作的项目的**,感觉很高阶,也很好用,因为会把底层的细节包装起来,不用太费劲看手册就能完成一些基本的操作。安装了Rt-Thread ,也跑了一个Blink程序,估计可行。浏览了一下手册,RT-Thread 是嵌入式操作系统的乐高,很多丰富的组件和功能都已经移植好了。N32G45x也有板级支持包,于是决定入坑。题目就选择比较有意思的microPython. microPython适合做调试,很灵活,几个语句就可以完成很多工作。比如ADC,读个电压,用嵌入式得有库代码,还要安装工具链,然后找手册,调参数,学习曲线很弯曲。但是搞了一个microPython,这些都省了,然后连刷机都不用,就是弄一个串口连上就可以。有点遗憾的是开发板没有板载的flash扩展,板级支持包中没有flash存储和文件系统的实现,所以不能把代码存在板上。但是这个问题不影响核心。小时候玩的小霸王学习机(不是游戏机),里面敲了半天的计算正弦积分的FBASIC程序,不是掉了电之后就没有了么?小霸王学习机还费电视,家里黑白电视被搞坏了,母亲还特意去阿姨家借了一台旧电视回来。。。。。。好吧,回到正题,我们怎么搞定microPython? [size=11.0000pt]一、初战失败,flash空间和内存都不够 一顿操作猛如虎,安装好RT-Thread 2.1.5,然后安装N32G45x 板级支持包,设置组件,设置一些参数,然后更新,编译。链接的时候晕了,空间不够,flash和ram 双双告急。 当时工程师姐姐特意支持发了顶配的457vel,有512kBflash ,还有144kb ram,不应该的。 想了半天明白了,是默认定义的问题。于是找资料,顺着目录看到board.h文件,内有定义。
图1 修改board.c文件,适配N32G457VEL 从注释里面,发现编写RT-Thread支持库的大牛,开发的环境是N32G452XX,内存SRAM原先只有80kB , FLASH也少得很,不够microPython最小的200kB的身材。 当然得改好了,立马可以链接成功了,不再报错,稍微报点警告,不管。 图2 编译的过程 二、初试microPython,感受神器的kiss之美,简单,简单,简单。Keep It Simple and Stupid. 下载到开发板上,一切安好。 先来一个putty.exe打开开发板的mp之门。 图3 链接开发板使用 putty终端,用得顺手
可以跑个数学程序,问问开发板1+1=?,看看它是否工作正常。 图4 小试 1+1 让microPython显神威 三、明确N32G45XVL-STB开发板的RT_Thread 引脚定义,使用microPython不迷糊 数学太烧脑,hello World一起搞。 接下来去点个灯。Blink走起。 但是板载的灯在PB5上,还有一个在PA8. microPython已经把细节封装了,您只需要知道是第几个引脚就可以了。 实际上RT-RThread也封装了。看文件/Libraries/drivers/drv_gpio.h。原先是452,是QF64封装,PB5对应的是57,恰好也能跑默认的闪灯。但是457vel比较阔气,有100引脚,所以修改一下引脚定义。 图5 修改引脚数为100,适配457vel #if (N32F10X_PIN_NUMBERS == 100) __N32_PIN_DEFAULT, __N32_PIN(1, APB2, E, 2), __N32_PIN(2, APB2, E, 3), __N32_PIN(3, APB2, E, 4), __N32_PIN(4, APB2, E, 5), __N32_PIN(5, APB2, E, 6), __N32_PIN_DEFAULT, __N32_PIN(7, APB2, C, 13), __N32_PIN(8, APB2, C, 14), __N32_PIN(9, APB2, C, 15), __N32_PIN_DEFAULT, __N32_PIN_DEFAULT, __N32_PIN_DEFAULT, __N32_PIN_DEFAULT, __N32_PIN_DEFAULT, __N32_PIN(15, APB2, C, 0), //ADC1 PC0 __N32_PIN(16, APB2, C, 1), __N32_PIN(17, APB2, C, 2), __N32_PIN(18, APB2, C, 3), __N32_PIN_DEFAULT, __N32_PIN_DEFAULT, __N32_PIN_DEFAULT, __N32_PIN_DEFAULT, __N32_PIN(23, APB2, A, 0),//SOFT I2C SCL __N32_PIN(24, APB2, A, 1),//SOFT I2C SDA __N32_PIN(25, APB2, A, 2), __N32_PIN(26, APB2, A, 3), __N32_PIN_DEFAULT, __N32_PIN_DEFAULT, __N32_PIN(29, APB2, A, 4), // Key1 PA4 __N32_PIN(30, APB2, A, 5), //Key2 PA5 __N32_PIN(31, APB2, A, 6), //key3 PA6 __N32_PIN(32, APB2, A, 7), __N32_PIN(33, APB2, C, 4), __N32_PIN(34, APB2, C, 5), __N32_PIN(35, APB2, B, 0), __N32_PIN(36, APB2, B, 1), __N32_PIN(37, APB2, B, 2), __N32_PIN(38, APB2, E, 7), __N32_PIN(39, APB2, E, 8), __N32_PIN(40, APB2, E, 9), __N32_PIN(41, APB2, E, 10), __N32_PIN(42, APB2, E, 11), __N32_PIN(43, APB2, E, 12), __N32_PIN(44, APB2, E, 13), __N32_PIN(45, APB2, E, 14), __N32_PIN(46, APB2, E, 15), __N32_PIN(47, APB2, B, 10), __N32_PIN(48, APB2, B, 11), __N32_PIN_DEFAULT, __N32_PIN_DEFAULT, __N32_PIN(51, APB2, B, 12), __N32_PIN(52, APB2, B, 13), __N32_PIN(53, APB2, B, 14), __N32_PIN(54, APB2, B, 15), __N32_PIN(55, APB2, D, 8), __N32_PIN(56, APB2, D, 9), __N32_PIN(57, APB2, D, 10), __N32_PIN(58, APB2, D, 11), __N32_PIN(59, APB2, D, 12), __N32_PIN(60, APB2, D, 13), __N32_PIN(61, APB2, D, 14), __N32_PIN(62, APB2, D, 15), __N32_PIN(63, APB2, C, 6), __N32_PIN(64, APB2, C, 7), __N32_PIN(65, APB2, C, 8), __N32_PIN(66, APB2, C, 9), __N32_PIN(67, APB2, A, 8), //led1 PA8 __N32_PIN(68, APB2, A, 9), __N32_PIN(69, APB2, A, 10), __N32_PIN(70, APB2, A, 11), __N32_PIN(71, APB2, A, 12), __N32_PIN(72, APB2, A, 13), __N32_PIN_DEFAULT, __N32_PIN_DEFAULT, __N32_PIN_DEFAULT, __N32_PIN(76, APB2, A, 14), __N32_PIN(77, APB2, A, 15), __N32_PIN(78, APB2, C, 10), __N32_PIN(79, APB2, C, 11), __N32_PIN(80, APB2, C, 12), __N32_PIN(81, APB2, D, 0), __N32_PIN(82, APB2, D, 1), __N32_PIN(83, APB2, D, 2), __N32_PIN(84, APB2, D, 3), __N32_PIN(85, APB2, D, 4), __N32_PIN(86, APB2, D, 5), __N32_PIN(87, APB2, D, 6), __N32_PIN(88, APB2, D, 7), __N32_PIN(89, APB2, B, 3), __N32_PIN(90, APB2, B, 4), __N32_PIN(91, APB2, B, 5), //led0 __N32_PIN(92, APB2, B, 6), __N32_PIN(93, APB2, B, 7), __N32_PIN_DEFAULT, __N32_PIN(95, APB2, B, 8), __N32_PIN(96, APB2, B, 9), __N32_PIN(97, APB2, E, 0), __N32_PIN(98, APB2, E, 1), __N32_PIN_DEFAULT, __N32_PIN_DEFAULT, #endif 引脚定义是完成 mp 的引脚初始化的重要参考,例如板载的LED灯是接在PB5,那么就需要采用如下的测试程序: microPython: from machine import Pin PIN_OUT = 91 PIN_IN = 29 p_out = Pin(("PB15", PIN_OUT), Pin.OUT_PP) p_out.value(1) # set io high p_out.value(0) # set io low p_in = Pin(("key_0", PIN_IN), Pin.IN, Pin.PULL_UP) print(p_in.value() ) # get value, 0 or 1 点亮灯,使用按键,都是用一两句语句就完事了。 四 在MicroPython的世界里,如何测量电压——ADC通道引脚的使用 2.1 找了10小时的bug,还是搞出来了。。。 数字引脚比较简单。但是ADC的调试比较费劲。本来也费劲,因为ADC的板级代码,逻辑很多,涉及GPIO模式设定为模拟输入,时钟设置和启用,DMA选项,触发,采样时间等等。microPython只是做最简单的ADC,但也比较费劲。 因为1.0.1的板级支持包,和1.0.0一样,在RT-Thread的Fish命令行下面,都跑不通ADC。原来是代码里面有一些bug,忘记包含了一个<drivers/drv_adc.h>引起的。感觉应该改了就行了,但是还是郁闷,没反应。发现是傻瓜化配置生成的rtconfig.h的文件里面,会默认设置简单的 #define BSP_USING_ADC, 而只有再加上 #define BSP_USING_ADC1, #define BSP_USING_ADC2, #define BSP_USING_ADC3 才会触发drv_adc.c里面的关键代码的编译。可能452的ADC 比较简单,默认就行。这个问题解决了之后,ADC就可以在mp里面工作了。
图6 RT_Thread傻瓜设置不灵活,手动修改解决 2.2 通道和引脚之间有一座暗桥,值得探索。 通道6 ADC1 或 ADC2 对应的引脚是PC0 通道7 ADC1 或 ADC2 对应的引脚是pC1
图7 ADC通道的配置
明确这个细节,可以比较好的使用microPython 的ADC读取模拟电压功能。 举例: >>> from machine import ADC # 从 machine 导入 ADC 类 >>> adc = ADC(1, 6) # 创建 ADC 对象,当前使用编号为 1 的 ADC 设备的 通道,就是以PC0引脚对应测试输入引脚。 >>> adc.read() # 获取 ADC 对象采样值 4095 >>> adc.deinit() # 关闭 ADC 对象 >>> adc.init(6) # 开启并重新配置 ADC 对象 图 8 machine.ADC功能测试——前巅峰之作
五、致谢 2012年制作Arduino Atmega8控制板开始,入圈开源硬件很多年了。看着《无线电》杂志从stm32主打,到Arduino霸麦,如今我们在21ic.com继续追梦。感谢Nations公司的开发板,是从硬件到固件库几乎全部开源,也感谢制作RT-Thread操作系统的很多大师。作为天然的极客,可以说很菜,但很好玩。Just For Fun。
附:代码包。 源代码太大,放在gitee.com https://gitee.com/xiaohezyd/rt_-thread_micro-python_-n32-g457-vel_stb
|