数码之家

 找回密码
 立即注册
搜索
查看: 5190|回复: 17

arduino ESP32寄存器操作IO提升速度

[复制链接]
发表于 2022-8-13 00:31:01 | 显示全部楼层 |阅读模式
本帖最后由 飞向狙沙 于 2022-8-13 00:31 编辑

书接上回arduino的性能测试
mcu换成了ESP32S2,同样并口屏,直接用digitalWrite写速度依旧不尽人意,继续研究寄存器操作
相关代码借鉴TFT_eSPI中的代码,感谢b站"科启思维"给的提示https://www.bilibili.com/video/BV147411U7p3?spm_id_from=333.999.0.0

以下部分测试mcu为ESP32S2,其他型号应该同样适用,没做验证

S2的GPIO数量超过32,操作时分为两组,0-31,32-53,不同组的区别对待
小知识:部分寄存器介绍

GPIO_OUT_REG用来设置0-31的状态,用起来较麻烦,用GPIO_OUT_W1TS_REG和GPIO_OUT_W1TC_REG操作相对方便,简单来说就是需要设置高电平,就用GPIO_OUT_W1TS_REG把对应IO位写1,低电平就用GPIO_OUT_W1TC_REG把对应位写1,看不懂也没关系,跳过不看就省心了

不罗嗦,上代码
单IO操作
  1. //GPIO0-31设置高电平,如
  2. //GPIO6高电平
  3. GPIO.out_w1ts=1<<6
  4. //GPIO8高电平
  5. GPIO.out_w1ts=1<<8
  6. //GPIO32-53设置高电平,如
  7. GPIO36高电平
  8. GPIO.out1_w1ts.val=1<<(36-32)
  9. GPIO42高电平
  10. GPIO.out1_w1ts.val=1<<(42-32)
  11. /***************************/
  12. //设置低电平同上,把w1ts改成w1tc就OK了
  13. //GPIO6低电平
  14. GPIO.out_w1tc=1<<6
复制代码
要问为啥0-31用out_w1ts,32-53用out1_w1ts.val多了个val,因为gpio_dev_s这个头文件中把out_w1ts定义成了数值,把out1_w1ts定义成了结构体,那么有为啥要这么定义,没细研究,规定就是了

IO组操作
并口屏需要批量设置D0-D7或者更多IO,一位一位定义麻烦,批量操作
  1. //dir_mask 所有数据IO集合   
  2. #define dir_mask ((1 << D0) | (1 << D1) | (1 << D2) | (1 << D3) | (1 << D4) | (1 << D5) | (1 << D6) | (1 << D7))
  3. //计算写入寄存器数据
  4. #define set_mask(C) (((C)&0x80)>>7)<<D7 | (((C)&0x40)>>6)<<D6 | (((C)&0x20)>>5)<<D5 | (((C)&0x10)>>4)<<D4 | \
  5.                     (((C)&0x08)>>3)<<D3 | (((C)&0x04)>>2)<<D2 | (((C)&0x02)>>1)<<D1 | (((C)&0x01)>>0)<<D0
  6. //定义写操作,调用时直接通过tft_Write_8(C)执行
  7. #define tft_Write_8(C) GPIO.out_w1tc = dir_mask; GPIO.out_w1ts = set_mask((uint8_t)(C));
复制代码
添加以上宏定义后即可通过
tft_Write_8(C)直接进行并口操作
实际上以上宏定义还是进行了大量位移和与操作,牺牲了部分性能,如果还要加速可以空间换时间,提前计算所有数据对应的IO结果,存入数组,写数据时直接通过数组读取。
  1. //定义映射数组
  2. uint32_t xset_mask[256];
  3. //定义数组初始化宏,在初始化函数中执行PARALLEL_INIT_DATA_BUS;进行初始化
  4. #define PARALLEL_INIT_DATA_BUS               \
  5.   for (int32_t c = 0; c<256; c++)              \
  6.   {                                            \
  7.     xset_mask[c] = 0;                          \
  8.     if ( c & 0x01 ) xset_mask[c] |= (1 << D0); \
  9.     if ( c & 0x02 ) xset_mask[c] |= (1 << D1); \
  10.     if ( c & 0x04 ) xset_mask[c] |= (1 << D2); \
  11.     if ( c & 0x08 ) xset_mask[c] |= (1 << D3); \
  12.     if ( c & 0x10 ) xset_mask[c] |= (1 << D4); \
  13.     if ( c & 0x20 ) xset_mask[c] |= (1 << D5); \
  14.     if ( c & 0x40 ) xset_mask[c] |= (1 << D6); \
  15.     if ( c & 0x80 ) xset_mask[c] |= (1 << D7); \
  16.   }                                            \
  17. //查映射表
  18. #define set_mask(C) xset_mask[C];
  19. //定义写操作,调用时直接通过tft_Write_8(C)执行
  20. #define tft_Write_8(C)  GPIO.out_w1tc.val = clr_mask; GPIO.out_w1ts.val = set_mask((uint8_t)(C));
复制代码

注:D0-D7维宏定义的数据位GPIO,如:
  1. #define D0    6
  2.   #define D1    7
  3.   #define D2    8
  4.   #define D3    9
  5.   #define D4   10
  6.   #define D5   11
  7.   #define D6   12
  8.   #define D7   13
复制代码


本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
发表于 2022-8-13 00:50:24 | 显示全部楼层
收藏了,代码优化一直是弱项
回复 支持 反对

使用道具 举报

发表于 2022-8-13 09:42:22 | 显示全部楼层
不错啊,用IDF效率要高些,arduino 就是玩具级别的。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2022-8-13 10:32:27 | 显示全部楼层
junyuansun 发表于 2022-8-13 09:42
不错啊,用IDF效率要高些,arduino 就是玩具级别的。

不想学了,各种单片机各种编译工具各种库,各种打包下载方式,玩起来太累了,玩个通用的省心了
之前试过idf,各种cmd感觉太蛋疼
回复 支持 反对

使用道具 举报

发表于 2022-8-15 20:13:12 | 显示全部楼层
飞向狙沙 发表于 2022-8-13 10:32
不想学了,各种单片机各种编译工具各种库,各种打包下载方式,玩起来太累了,玩个通用的省心了
之前试过i ...

arduino 可不算玩具.
很多大佬写的库效率还行.

esp-idf 自已的库有些东西效率也不算高.
毕竟要兼容这么多产品线.

回复 支持 反对

使用道具 举报

 楼主| 发表于 2022-8-15 23:21:13 | 显示全部楼层
junyee 发表于 2022-8-15 20:13
arduino 可不算玩具.
很多大佬写的库效率还行.

不考虑代码水平的话arduino的整体效率还是偏低的,毕竟就像为了实现统一风格的功能调用,舍弃了像port之类的便捷操作。不过实际上再考虑代码水平的时候arduino甚至可能效率更高,毕竟arduino封装库的大佬一般水平也都可以,自己写也不一定能比库的效率高。

这个话题聊得多了容易引战,谁爱用啥用啥吧
回复 支持 反对

使用道具 举报

发表于 2022-8-16 00:02:46 来自手机浏览器 | 显示全部楼层
这个带rgb888的320240屏幕理论能刷多少帧?
回复 支持 反对

使用道具 举报

发表于 2022-8-16 08:28:00 | 显示全部楼层
飞向狙沙 发表于 2022-8-15 23:21
不考虑代码水平的话arduino的整体效率还是偏低的,毕竟就像为了实现统一风格的功能调用,舍弃了像port之类 ...


我以前也对 arduino 有偏见,(自从看了很多初学者入门没几天,用三方库用也能刷屏,而且帧率不低.
于是爬代码看了下,大多热门第三方库质量都非常高.

至于你说的 底层 port 操作, esp-idf 也不如 寄存器操作效率高哈.毕竟省掉了很多检测 判断.

esp-idf arduino



最简单的写io, 你看其实代码都差不太多.


本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复 支持 反对

使用道具 举报

 楼主| 发表于 2022-8-16 08:51:40 | 显示全部楼层
jpdd521 发表于 2022-8-16 00:02
这个带rgb888的320240屏幕理论能刷多少帧?

实测128160 RGB565一屏13.7ms,还有优化的空间
回复 支持 反对

使用道具 举报

发表于 2022-8-16 08:56:30 | 显示全部楼层
感谢分享,先学习学习
回复 支持 反对

使用道具 举报

发表于 2022-8-16 08:57:38 来自手机浏览器 | 显示全部楼层
飞向狙沙 发表于 2022-8-16 08:51
实测128160 RGB565一屏13.7ms,还有优化的空间

320*240的话一屏差不多就是50ms左右了。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2022-8-16 08:59:26 | 显示全部楼层
junyee 发表于 2022-8-16 08:28
我以前也对 arduino 有偏见,(自从看了很多初学者入门没几天,用三方库用也能刷屏,而且帧率不低.
于是爬代 ...

是的,arduino也是直接调用官方库,甚至跳过官方库直接调用寄存器,性能方面不一定差
以前对arduino最看不上的就是他的ide,想看个源码太难了,现在vscode加持后玩起来也挺顺手的
回复 支持 反对

使用道具 举报

发表于 2022-8-16 09:03:01 | 显示全部楼层
慧联A10+悦虎1562M+1562
回复 支持 反对

使用道具 举报

发表于 2022-8-16 09:03:17 | 显示全部楼层
代码水平的话arduino的整体效率还是偏低的,毕竟就像为了实现统一风格的功能调用,舍弃了像port之类的便捷操作。不过实际上再考虑代码水平的时候arduino甚至可能效率更高,毕竟arduino封装库的大佬一般水平也都可以,自己写也不一定能比库的效率高。
回复 支持 反对

使用道具 举报

发表于 2022-8-16 09:03:55 | 显示全部楼层
学习了,确实不如STM32好用
回复 支持 反对

使用道具 举报

发表于 2022-8-16 09:06:23 | 显示全部楼层
飞向狙沙 发表于 2022-8-16 08:59
是的,arduino也是直接调用官方库,甚至跳过官方库直接调用寄存器,性能方面不一定差
以前对arduino最看不上 ...


vscode 有个 platformIO 好像能玩 arduino.
我个人没有玩 arduino  
回复 支持 反对

使用道具 举报

 楼主| 发表于 2022-8-16 09:15:13 | 显示全部楼层
jpdd521 发表于 2022-8-16 08:57
320*240的话一屏差不多就是50ms左右了。

手里没大屏,一堆128160,这个速度够用了就没再研究,追求速度的话还有的优化
回复 支持 反对

使用道具 举报

 楼主| 发表于 2022-8-16 09:17:32 | 显示全部楼层
junyee 发表于 2022-8-16 09:06
vscode 有个 platformIO 好像能玩 arduino.
我个人没有玩 arduino

是的,我就是用的platformIO,可以玩arduino也可以玩esp-idf
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

APP|手机版|小黑屋|关于我们|联系我们|法律条款|技术知识分享平台

闽公网安备35020502000485号

闽ICP备2021002735号-2

GMT+8, 2025-5-11 03:41 , Processed in 0.358800 second(s), 11 queries , Redis On.

Powered by Discuz!

© 2006-2025 MyDigit.Net

快速回复 返回顶部 返回列表