数码之家

 找回密码
 立即注册
搜索
查看: 10791|回复: 31

[Arduino] 分享一个RAV4和卡罗拉车机VFD屏的U8g2驱动(Arduino / STM32)

[复制链接]
发表于 2020-1-21 20:41:07 | 显示全部楼层 |阅读模式

爱科技、爱创意、爱折腾、爱极致,我们都是技术控

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

x
2020/1/23更新:增加支持U8x8(请重新下载压缩文件)

先上两张卡罗拉VFD屏的效果图,是U8g2和U8x8自带的示例。(点击可查看大图)

U8g2 Logo:
0.jpg
IMG_2871(20200122-102835).JPG

U8x8 GraphicsTest:
1.jpg

Arduino

一、安装:
这里是已经修改好的u8g2库,版本是2.27.5,直接下载然后在Arduino里选“项目->加载库->添加.zip库”就能安装,记得先删掉原来的U8g2。
U8g2-2.27.5.zip

安装好库以后,像其他屏幕一样使用就行。

二、构造函数:
1页缓冲占用256Byte内存,2页缓冲占用512Byte内存,全缓冲卡罗拉的需要1792Byte、RAV4的需要2048Byte。对于有多个SPI口的Arduino板,可以使用带2ND符号的构造函数来使用第二个SPI。
  1. /* 卡罗拉 U8g2 SPI0 */
  2. U8G2_GP1287AI_256X50_1_3W_HW_SPI u8g2(U8G2_R0, /* cs=*/ 10, /* reset=*/ 9);
  3. U8G2_GP1287AI_256X50_2_3W_HW_SPI u8g2(U8G2_R0, /* cs=*/ 10, /* reset=*/ 9);
  4. U8G2_GP1287AI_256X50_F_3W_HW_SPI u8g2(U8G2_R0, /* cs=*/ 10, /* reset=*/ 9);
  5. /* 卡罗拉 U8g2 SPI1 */
  6. U8G2_GP1287AI_256X50_1_2ND_3W_HW_SPI u8g2(U8G2_R0, /* cs=*/ 10, /* reset=*/ 9);
  7. U8G2_GP1287AI_256X50_2_2ND_3W_HW_SPI u8g2(U8G2_R0, /* cs=*/ 10, /* reset=*/ 9);
  8. U8G2_GP1287AI_256X50_F_2ND_3W_HW_SPI u8g2(U8G2_R0, /* cs=*/ 10, /* reset=*/ 9);

  9. /* RAV4 U8g2 SPI0 */
  10. U8G2_RAV4_253X63_1_3W_HW_SPI u8g2(U8G2_R0, /* cs=*/ 10, /* reset=*/ 9);
  11. U8G2_RAV4_253X63_2_3W_HW_SPI u8g2(U8G2_R0, /* cs=*/ 10, /* reset=*/ 9);
  12. U8G2_RAV4_253X63_F_3W_HW_SPI u8g2(U8G2_R0, /* cs=*/ 10, /* reset=*/ 9);
  13. /* RAV4 U8g2 SPI1 */
  14. U8G2_RAV4_253X63_1_2ND_3W_HW_SPI u8g2(U8G2_R0, /* cs=*/ 10, /* reset=*/ 9);
  15. U8G2_RAV4_253X63_2_2ND_3W_HW_SPI u8g2(U8G2_R0, /* cs=*/ 10, /* reset=*/ 9);
  16. U8G2_RAV4_253X63_F_2ND_3W_HW_SPI u8g2(U8G2_R0, /* cs=*/ 10, /* reset=*/ 9);

  17. /* 卡罗拉 U8x8 SPI0 */
  18. U8X8_GP1287AI_256X50_3W_HW_SPI u8x8( /* cs=*/ 10, /* reset=*/ 9);
  19. /* 卡罗拉 U8x8 SPI1 */
  20. U8X8_GP1287AI_256X50_2ND_3W_HW_SPI u8x8( /* cs=*/ 10, /* reset=*/ 9);

  21. /* RAV4 U8x8 SPI0 */
  22. U8X8_RAV4_253X63_3W_HW_SPI u8x8( /* cs=*/ 10, /* reset=*/ 9);
  23. /* RAV4 U8x8 SPI1*/
  24. U8X8_RAV4_253X63_2ND_3W_HW_SPI u8x8( /* cs=*/ 10, /* reset=*/ 9);
复制代码



三、亮度调节:
这两个型号的屏幕原本支持1024级亮度,但是U8g2最多只能输入255,所以setContrast()每增加1级的亮度实际是增加了4级的亮度。
  1. /* 亮度调节 */
  2. u8g2.setContrast(255);
复制代码



四、节能模式:

在退出节能模式时会自动有1毫秒延时,等待屏幕内部振荡器稳定。
  1. /* 进入节能模式 */
  2. u8g2.setPowerSave(1);

  3. /* 退出节能模式 */
  4. u8g2.setPowerSave(0);
复制代码



五、注意事项:
1、这两种屏幕的逻辑供电和所有io均为3.3V,如果用5V的Arduino板(UNO、Leonardo之类的)驱动的话需要加电平转换(因为默认是推挽输出,所以最好是使用转换芯片或三极管,也可以自己修改程序为开漏输出,然后用两个电阻做电平转换)。
2、高压使能(屏幕PCB上的SLEEP或HVEN测试点)在U8g2里没有去控制,自己用一个io口去控制就行,高电平是开启,低电平是关闭。在打开以后建议等700毫秒左右,待灯丝完全加热以后再发显示数据,不然显示内容会有从暗变亮的过程,视觉效果会不太好。

EX、Arduino自己修改库的操作步骤:
1、首先下载这个压缩包,然后解压一下,得到“src”文件夹
arduino_u8g2_vfd驱动.zip
2、将“src\追加\U8g2lib.h”里的内容全部添加到库中“U8g2\src\U8g2lib.h”的最后:
(点击可查看大图)
2.png

3、将“src\追加\U8x8lib.h”里的内容全部添加到库中“U8g2\src\U8x8lib.h”的最后:
3.png

4、用“src\修改\U8x8lib.cpp”里的相应内容替换库中“U8g2\src\U8x8lib.cpp”内相应的行:
(第一组)
4.png
(第二组)
5.png
(第三组)
6.png
(第四组)
7.png

5、将“src\clib\直接放入\u8x8_d_futaba_vfd.c”复制到库中“U8g2\src\clib”文件夹内:
8.png

6、将“src\clib\追加\u8g2.h”里的相应内容添加到库中“U8g2\src\clib\u8g2.h”文件的相应位置:

(第一组)
9.png
(第二组)
10.png

7、将“src\clib\追加”文件夹里剩余几个文件的内容添加到库中“U8g2\src\clib”文件内相同文件名文件的最后:
(u8g2_d_memory.c)
11.png
(u8g2_d_setup.c)
12.png
(u8x8.h)
13.png

8、最后将库中“U8g2\src\clib\u8g2.h”开头的 //#define U8G2_16BIT 注译去掉,变为#define U8G2_16BIT,启用16bit模式支持大尺寸屏幕。 14.png


STM32

一、移植U8g2:


这里是官方的移植和使用示例:
https://github.com/olikraus/u8g2/wiki/Porting-to-new-MCU-platform
https://github.com/olikraus/u8g2/wiki/u8g2setupc


最后附件里也有移植好并添加了VFD驱动的整个Keil工程

移植比较简单在这里就不细说了,不用修改什么东西,只需要添加就行。在编译的时候出现Error: L6406E: No space in execution regions with .ANY xxxxxxx的话建议切换到version6的编译器(如果是GCC可以启用垃圾收集):
15.png

不想使用version6编译器的话就需要手动删掉不需要的函数和字体,详细方法网上都有,在删除时需要注意保留u8g2_d_memory.c内下面这三个:
  1. uint8_t *u8g2_m_32_8_1(uint8_t *page_cnt);
  2. uint8_t *u8g2_m_32_8_2(uint8_t *page_cnt);
  3. uint8_t *u8g2_m_32_8_f(uint8_t *page_cnt);
复制代码



最后还需要添加SPI和GPIO回调函数(直接加到main.c里或新建一个文件都行):
  1. /* SPI回调 */
  2. uint8_t u8x8_byte_hw_spi_futaba_vfd(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
  3. {
  4.   uint8_t *data;
  5.   switch (msg)
  6.   {
  7.   case U8X8_MSG_BYTE_SEND: // 每次需要SPI发送数据时会进入这里,arg_ptr为数据指针,arg_int为数据大小
  8.     data = (uint8_t *)arg_ptr;
  9.     for (uint8_t i = 0; i < arg_int; i++)
  10.     {
  11.       while (LL_SPI_IsActiveFlag_TXE(SPI1) == RESET)
  12.       {
  13.         //__NOP();
  14.       }
  15.       LL_SPI_TransmitData8(SPI1, *data);
  16.       data += 1;
  17.     }
  18.     while (LL_SPI_IsActiveFlag_BSY(SPI1) == SET)
  19.     {
  20.       //__NOP();
  21.     }
  22.     break;
  23.   case U8X8_MSG_BYTE_START_TRANSFER:
  24.     LL_GPIO_ResetOutputPin(SPI1_CS_GPIO_Port, SPI1_CS_Pin);
  25.     break;
  26.   case U8X8_MSG_BYTE_END_TRANSFER:
  27.     LL_GPIO_SetOutputPin(SPI1_CS_GPIO_Port, SPI1_CS_Pin);
  28.     break;
  29.   default:
  30.     return 0;
  31.   }
  32.   return 1;
  33. }
  34. /* GPIO回调 */
  35. uint8_t u8x8_gpio_and_delay_futaba_vfd(U8X8_UNUSED u8x8_t *u8x8, U8X8_UNUSED uint8_t msg, U8X8_UNUSED uint8_t arg_int, U8X8_UNUSED void *arg_ptr)
  36. {
  37.   switch (msg)
  38.   {
  39.   case U8X8_MSG_GPIO_AND_DELAY_INIT:
  40.     LL_SPI_Enable(SPI1);
  41.     break;
  42.   case U8X8_MSG_DELAY_MILLI:
  43.     LL_mDelay(arg_int);
  44.     break;
  45.   case U8X8_MSG_GPIO_RESET:
  46.     if (arg_int)
  47.       LL_GPIO_SetOutputPin(RST_GPIO_Port, RST_Pin);
  48.     else
  49.       LL_GPIO_ResetOutputPin(RST_GPIO_Port, RST_Pin);
  50.     break;
  51.   default:
  52.     u8x8_SetGPIOResult(u8x8, 1);
  53.     break;
  54.   }
  55.   return 1;
  56. }
复制代码




二、添加VFD驱动:
1、首先下载这个压缩包,然后解压一下,得到“csrc”文件夹
stm32_u8g2_vfd驱动.zip
2、之后的步骤和“Arduino自己修改库”的 5 到 8 步是相同的

三、支持的Setup函数:
1页缓冲占用256Byte内存,2页缓冲占用512Byte内存,全缓冲卡罗拉的需要1792Byte、RAV4的需要2048Byte。
  1. /* 卡罗拉 U8g2 */
  2. u8g2_Setup_futaba_vfd_gp1287ai_256x50_1(&u8g2, U8G2_R0, u8x8_byte_hw_spi_futaba_vfd, u8x8_gpio_and_delay_futaba_vfd);
  3. u8g2_Setup_futaba_vfd_gp1287ai_256x50_2(&u8g2, U8G2_R0, u8x8_byte_hw_spi_futaba_vfd, u8x8_gpio_and_delay_futaba_vfd);
  4. u8g2_Setup_futaba_vfd_gp1287ai_256x50_f(&u8g2, U8G2_R0, u8x8_byte_hw_spi_futaba_vfd, u8x8_gpio_and_delay_futaba_vfd);

  5. /* RAV4 U8g2 */
  6. u8g2_Setup_futaba_vfd_rav4_253x63_1(&u8g2, U8G2_R0, u8x8_byte_hw_spi_futaba_vfd, u8x8_gpio_and_delay_futaba_vfd);
  7. u8g2_Setup_futaba_vfd_rav4_253x63_2(&u8g2, U8G2_R0, u8x8_byte_hw_spi_futaba_vfd, u8x8_gpio_and_delay_futaba_vfd);
  8. u8g2_Setup_futaba_vfd_rav4_253x63_f(&u8g2, U8G2_R0, u8x8_byte_hw_spi_futaba_vfd, u8x8_gpio_and_delay_futaba_vfd);

  9. /* 卡罗拉 U8x8 */
  10. u8x8_Setup(&u8x8, u8x8_d_futaba_vfd_gp1287ai_256x50, u8x8_cad_empty, u8x8_byte_hw_spi_futaba_vfd, u8x8_gpio_and_delay_futaba_vfd);

  11. /* RAV4 U8x8 */
  12. u8x8_Setup(&u8x8, u8x8_d_futaba_vfd_rav4_256x50, u8x8_cad_empty, u8x8_byte_hw_spi_futaba_vfd, u8x8_gpio_and_delay_futaba_vfd);
复制代码



四、亮度调节:这两个型号的屏幕原本支持1024级亮度,但是U8g2最多只能输入255,所以SetContrast()每增加1级的亮度实际是增加了4级的亮度。
  1. /* 亮度调节 */
  2. u8g2_SetContrast(&u8g2, 255);
复制代码



五、节能模式:
在退出节能模式时会自动有1毫秒延时,等待屏幕内部振荡器稳定。注意:在调用InitDisplay()之后默认状态为进入节能模式,需要手动使用SetPowerSave(0)退出(参见上面的官方使用示例)
  1. /* 进入节能模式 */
  2. u8g2_SetPowerSave(&u8g2, 1);

  3. /* 退出节能模式 */
  4. u8g2_SetPowerSave(&u8g2, 0);
复制代码




六、注意事项:
1、高压使能(屏幕PCB上的SLEEP或HVEN测试点)在U8g2里没有去控制,自己用一个io口去控制就行,高电平是开启,低电平是关闭。在打开以后建议等700毫秒左右,待灯丝完全加热以后再发显示数据,不然显示内容会有从暗变亮的过程,视觉效果会不太好。





附件:
1、卡罗拉的显示面板PCB测试点和逻辑分析仪数据: 卡罗拉VFD.zip (8.75 MB, 下载次数: 58)
2、RAV4的逻辑分析仪数据: RAV4 VFD逻辑分析仪数据.zip (1005.61 KB, 下载次数: 22)
3、在103C8上移植好U8g2的Keil(V5.29)示例工程: 103C8T6_U8g2_VFD.zip (9.57 MB, 下载次数: 55)



萌新第一次发帖,如果有什么问题欢迎指出~


补充内容 (2020-1-23 15:54):
2020/1/23更新:增加支持U8x8,链接地址:https://docs.qq.com/doc/DTlp1akJUVlFVQW5r(原贴不能编辑了,就在文档里更新了)





相关阅读:玩点不一样的!卡罗拉车机VFD屏实现灰度显示:
https://www.mydigit.cn/forum.php?mod=viewthread&tid=196643

打赏

参与人数 2家元 +40 收起 理由
人艰不拆了 + 20
jpdd521 + 20 打赏萌新,好评x2

查看全部打赏

发表于 2020-1-21 21:27:21 | 显示全部楼层
还没更好?我的是17款卡罗拉VFD屏。
回复 支持 反对

使用道具 举报

发表于 2020-2-5 09:18:09 | 显示全部楼层
本帖最后由 深渫 于 2020-2-6 23:12 编辑

好东西!  谢谢分享!

请教大神几个问题:
1.卡罗拉VFD,我用你的u8g2  demo移植到了STM32F030C8, 无法点亮,用逻辑分析仪检查了SPI数据,未找到原因。
   今天下午使用你的《F103C8图片测试程序》移植到了同一块电路板(F030C8),已经点亮屏幕。
    准备空了看看你附件里面的文件,分析下具体指令。


2.关于 VFD 初始化函数——u8g2_InitDisplay(&u8g2);
我在VScode下跟踪到这是指向 u8x8_display.c 下的一个函数,而此函数的内容是一个结构体,该函数是如何执行到u8x8_d_futaba_vfd_gp1287ai_256x50 的?  C语言基础不够,看不懂这种操作:mad:,还望大神不吝赐教。谢谢!

  1. /*文件 u8x8_display.c 下的初始化函数 */
  2. void u8x8_InitDisplay(u8x8_t *u8x8)
  3. {
  4.   u8x8->display_cb(u8x8, U8X8_MSG_DISPLAY_INIT, 0, NULL);  
  5. }


  6. /*u8x8.h 结构体定义*/
  7. struct u8x8_struct
  8. {
  9.   const u8x8_display_info_t *display_info;
  10.   u8x8_char_cb next_cb; /*  procedure, which will be used to get the next char from the string */
  11.   u8x8_msg_cb display_cb;
  12.   u8x8_msg_cb cad_cb;
  13.   u8x8_msg_cb byte_cb;
  14.   u8x8_msg_cb gpio_and_delay_cb;
  15.   uint32_t bus_clock;        /* can be used by the byte function to store the clock speed of the bus */
  16.   const uint8_t *font;


  17. /*最终调用的VFD指令发送函数*/
  18. uint8_t u8x8_d_futaba_vfd_gp1287ai_256x50(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
  19. {
复制代码







补充内容 (2020-2-9 12:11):
第一个问题已经解决,已经点亮了    是我硬件初始化的问题
回复 支持 反对

使用道具 举报

发表于 2020-2-5 20:03:09 | 显示全部楼层
好东西,学习了
回复 支持 反对

使用道具 举报

发表于 2020-2-8 14:03:21 | 显示全部楼层
深渫 发表于 2020-2-5 09:18
好东西!  谢谢分享!

请教大神几个问题:

兄弟有联系方式吗?请教一下
回复 支持 反对

使用道具 举报

发表于 2020-2-9 15:58:11 | 显示全部楼层
ts608 发表于 2020-2-8 14:03
兄弟有联系方式吗?请教一下

壮士! 有话请讲!
回复 支持 反对

使用道具 举报

 楼主| 发表于 2020-2-12 21:24:17 | 显示全部楼层
深渫 发表于 2020-2-5 09:18
好东西!  谢谢分享!

请教大神几个问题:

你好,不好意思一直没有上线,关于第二个问题用专业术语的话我有点解释不来... 不过通俗地讲就是在程序开头调用
  1. u8g2_Setup_futaba_vfd_gp1287ai_256x50_1(&u8g2, U8G2_R0, ......);
复制代码

的时候,通过里面的
  1. u8g2_SetupDisplay(u8g2, u8x8_d_futaba_vfd_gp1287ai_256x50, u8x8_cad_empty, byte_cb, gpio_and_delay_cb);
复制代码


  1. u8x8_d_futaba_vfd_gp1287ai_256x50
复制代码

这个函数的指针放到了u8g2_t这个结构体里面的u8x8结构体里的display_cb里面,然后在需要的时候直接调用display_cb并传入相应的消息(msg)和参数(arg)就可以执行相应的功能。
比如
  1. void u8x8_InitDisplay(u8x8_t *u8x8)
  2. {
  3.   u8x8->display_cb(u8x8, U8X8_MSG_DISPLAY_INIT, 0, NULL);  
  4. }
复制代码

翻译一下其实就是
  1. void u8x8_InitDisplay(u8x8_t *u8x8)
  2. {
  3.   u8x8_d_futaba_vfd_gp1287ai_256x50(u8x8, U8X8_MSG_DISPLAY_INIT, 0, NULL);  
  4. }
复制代码
回复 支持 反对

使用道具 举报

发表于 2020-2-13 10:58:50 来自手机浏览器 | 显示全部楼层
厉害,最佩服实干家
回复 支持 反对

使用道具 举报

发表于 2020-2-22 20:46:17 | 显示全部楼层
楼主厉害。
我手上一个非标分辨率的SSD1322驱动的OLED,可以用标准分辨率的配置点亮,但显示的坐标就有便宜。可否请教一下。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2020-2-24 10:59:29 | 显示全部楼层
lhn1324 发表于 2020-2-22 20:46
楼主厉害。
我手上一个非标分辨率的SSD1322驱动的OLED,可以用标准分辨率的配置点亮,但显示的坐标就有便宜 ...

你好,是x方向的偏移吗,如果是的话你看下在u8x8_d_ssd1322.c里有一个u8x8_ssd1322_128x64_display_info或者是u8x8_ssd1322_256x64_display_info,可以修改一下里面的default_x_offset和flipmode_x_offset试试,它现在里面默认有一点偏移。
如果是y方向的话可能要在初始化序列里面或者是在U8X8_MSG_DISPLAY_DRAW_TILE里改,具体怎么弄还需要你自己摸索一下,因为我也不是太懂(尴尬)
回复 支持 反对

使用道具 举报

发表于 2020-3-1 11:21:19 | 显示全部楼层
确实厉害,我也买了科罗拉,以后研究吧,资料先收藏,谢谢了
回复 支持 反对

使用道具 举报

发表于 2020-4-28 11:25:43 | 显示全部楼层
太牛逼了,原来分析纯的数据有点小错,还是楼主的完美!
回复 支持 反对

使用道具 举报

发表于 2020-4-29 08:29:12 | 显示全部楼层
楼主,1页缓冲占用256Byte内存,2页缓冲占用512Byte内存,这个什么意思?怎么算1页呢?
回复 支持 反对

使用道具 举报

发表于 2020-4-30 09:59:47 | 显示全部楼层
不错,车机的VFD屏可以用在arduino上面。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2020-6-3 22:27:10 | 显示全部楼层
nonzhe 发表于 2020-4-29 08:29
楼主,1页缓冲占用256Byte内存,2页缓冲占用512Byte内存,这个什么意思?怎么算1页呢? ...

对于256x50的屏幕来说,竖着8个像素、横着256像素这是一页,就是8x256/8=256Byte。u8g2可以选择每次绘制几页的内容,如果是_1的选项的话每次只绘制一页的内容,然后发送到屏幕,接着的绘制下一页再发送,重复7次,这样就可以节省内存,只用256Byte。_2同理,每次绘制2页,重复4次,占用512byte。如果是_f的话就是直接绘制一整屏,也就是占用1792Byte内存,但是这样速度是最快的。
回复 支持 反对

使用道具 举报

发表于 2020-7-20 21:53:18 来自手机浏览器 | 显示全部楼层
本帖最后由 suwill 于 2020-7-21 08:33 编辑

大神搞过185a车机的屏么?有pcb引脚定义,有51的例程,我想用esp8266+u8g2点亮它,请赐教

-3095031fc84502cd.jpg

大众185A LCD.rar

46.67 KB, 下载次数: 2, 下载积分: 家元 -55

回复 支持 反对

使用道具 举报

发表于 2020-8-6 09:21:41 | 显示全部楼层
大神,能给一个完整的接线图和代码吗?我用的是mega2560的板子,可以吗?
回复 支持 反对

使用道具 举报

发表于 2020-8-6 09:29:34 | 显示全部楼层
大神,能发一下完整的代码和接线方法吗?我用的是arduino 2560板子,rav4屏
回复 支持 反对

使用道具 举报

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

本版积分规则

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

闽公网安备35020502000485号

闽ICP备2021002735号-2

GMT+8, 2024-4-20 00:33 , Processed in 0.405600 second(s), 14 queries , Redis On.

Powered by Discuz!

© 2006-2023 smzj.net

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