基于MAX78000的显示系统
本文使用MAX78000 FTHR开发板,在开发板上外接了一块TFT显示屏和OLED显示屏,对显示功能进行了测试。此外,对板载指示灯的显示控制,也进行了测试。最终,显示屏及指示灯可以在红、绿、蓝三种状态进行切换显示。
标签
SPI
OLED
U8G2
MAX78000
TFT
I2C
chinaking
更新2023-01-31
上海大学
923

一、系统概述

        本文使用MAX78000 FTHR开发板,在开发板上外接了一块TFT显示屏和OLED显示屏,对显示功能进行了测试。此外,对板载指示灯的显示控制,也进行了测试。最终,显示屏及指示灯可以在红、绿、蓝三种状态进行切换显示。

        针对TFT显示屏,测试了屏幕的SPI接口,实现了字符显示和图形显示。

        针对OLED显示屏,测试了屏幕的I2C接口,移植了U8g2显示驱动库,实现了中英文及特殊图形显示。

        针对LED指示灯,测试了红绿蓝不同颜色的切换显示。

        总之,通过此次显示系统的开发,掌握了MAX78000的SPI、I2C等接口的使用方法,熟悉了显示屏的驱动功能,为后续项目开发打下了基础。

二、硬件设计

下图是本系统的硬件接线图。主要分为TFT屏的连接和OLED屏的连接。

Fjm-Jj2rfKGKJBqw_HEBh_dbz4zF

                                                  图1 系统硬件接线图

TFT屏的接线主要分为三部分,电源线、通讯线和其它线。

下图是官方推荐屏幕的连接效果。

Fnjp8uPh4VdRFOTXt4xNuQ4_XE_U
因官方推荐的Adafruit屏幕排母和MAX78000FTHR的排针是兼容的,直接对插即可。而我们采用的屏幕与它硬件不完全一致,需要对照Adafruit屏幕用到的引脚自己引线。

下图是Adafruit屏幕的引脚图,只要在图中找出电源(Vcc、GND),SPI接口(SCLK、MOSI) ,控制接口(CS 、DC、 Reset)等7个引脚的对应开发板上接口的位置即可。

Fip3YG5tqE-OSzDg_9O3W-iLMveI

电源线为VCC和GND分别连接开发板的3V3和GND即可,此外将屏幕的LED背光脚也接到3V3。

通讯线为SPI通讯,这次只用到了SCK和MOSI两根线。因为主要是屏幕接收数据,所有MISO线可以不接。

其它线包括RESET、CS、DC等几根线。其中RESET线连接开发板的硬件RESET脚即可,这样比较方便,无需再对GPIO进行指定。

OLED屏的接线是两根电源线,两根通讯线。电源也是3.3V,通讯线连接到图1开发板右下角的I2C接口。

三、软件设计

首先要熟悉MAX78000的开发环境,

Eclipse开发环境使用

双击图标,运行Eclipse

Fu6rkE2M9gqOiGkliFrif5jgPwCW

等待检查升级,检查完成后即进入IDE编程环境。

点击File---New菜单,如果菜单下能看到Maxim图标则点击该图标,如果看不到,则点击File---New---Project。选择Maxim Microcontrollers,点击Next。

Fv-J9eCalQyoy-4uPLr-P-P7NNQU

输入工程名称,如abc,点击Next

FjHAPfzszf8zkIrN7TVVqsxeKzpt

按照下图,选择芯片型号、开发板型号、示例工程、下载器类型。

FjOexYlyggkJoTyamR8C_TMCKyWc

点击完成即可。

开发环境准备好后,即可测试几个示例程序。

软件功能的开发可分为三部分:LED指示灯控制、TFT显示功能开发、OLED显示功能开发。

LED指示灯控制,这一部分最简单,参考官方的“Hello World”例程即可。

/*LED灯控制函数*/
void ctrlLED()
{
	if (page_id==0)
	{
	  LED_On(LED1);
	  LED_Off(LED2);
	  LED_Off(LED3);
}
	else if (page_id==1)
	{
	  LED_Off(LED1);
	  LED_On(LED2);
	  LED_Off(LED3);
	}
	else if (page_id==2)
	{
	   LED_Off(LED1);
	   LED_Off(LED2);
	   LED_On(LED3);}
}

TFT显示功能开发,这一部分可参考“TFT_Demo”例程,在此基础上理解TFT屏绘制矩形图案、绘制线条等函数的使用。

/*TFT屏打印字符串函数*/
void TFT_Print(char *str, int x, int y, int font)
{
    // fonts id
    text_t text;
    text.data = str;
    text.len = 20;
    MXC_TFT_PrintFont(x, y, font, &text, NULL);
}

/*TFT屏显示函数*/
void drawTFT(void)
{
    area_t _area;
    area_t *area;
    char buff[TFT_BUFF_SIZE];

    MXC_TFT_SetBackGroundColor(LIGTH_GREY);//设置屏幕背景色

    area = &_area;
    area->x = 100;
    area->y = 50;
    area->w = 60;
    area->h = 30;
    if (page_id==0)
    	{RectColor=RED;
    	 sprintf(buff, "RED  ");
    	 TFT_Print(buff, 100, 10, (int)&Arial28x28[0]);//屏幕显示字符串
    	}
    else if (page_id==1)
    	{RectColor=GREEN;
    	sprintf(buff, "GREEN");
    	TFT_Print(buff, 90, 10, (int)&Arial28x28[0]);
    	}
    else if (page_id==2)
    	{ RectColor=BLUE;
    	sprintf(buff, "BLUE ");
    	TFT_Print(buff, 100, 10, (int)&Arial28x28[0]);
    	}
    MXC_TFT_FillRect(area, RectColor);//绘制填充矩形

    MXC_TFT_Line(100, 100,160,100,RectColor);//绘制矩形框
	MXC_TFT_Line(160, 100,160,200,RectColor);
	MXC_TFT_Line(160, 200,100,200,RectColor);
	MXC_TFT_Line(100, 200,100,100,RectColor);

}

OLED显示功能开发,这是此项目中最复杂的部分。首先,参考I2C相关的例程,理解MAX78000的I2C函数的使用方法。然后,借助以前项目经验,自己写驱动程序,测试基础的OLED显示功能。最后,参考STM32对U8G2显示库的移植过程,完成MAX78000的U8g2显示。

U8g2的移植过程

移植过程主要借鉴了下面一篇博文

https://blog.csdn.net/qq_43862401/article/details/121809470

该文章是针对STM32移植u8g2,但过程是相似的。

  1. 下载U8g2源文件

https://github.com/olikraus/u8g2

  1. 精简文件。

新建一个u8g2的文件夹,将U8g2源文件的csrc夹复制到新建的文件夹下。

去掉无用的驱动文件

u8x8_d_ 开头的文件,只保留u8x8_ssd1306_128x64_noname.c

精简精简u8g2_d_setup.c

只保留 u8g2_Setup_ssd1306_i2c_128x64_noname_2相关函数,其它都删掉。

精简u8g2_d_memory.c

只保留u8g2_m_16_8_2相关内容。

  1. 创建两个回调函数。即I2C通讯部分的函数需要参考MAX78000的demo来重新创建。

即在driver_oled_ssd1306.c文件中,创建u8x8_byte_hw_i2c_max78000和u8g2_gpio_and_delay_max78000两个函数。

下面是回调函数主要代码:

#include <string.h>
#include "stdint.h"
#include "driver_oled_ssd1306.h"
#include "u8x8.h"
#include <stdio.h>
#include "i2c.h"
#include "mxc_delay.h"
#include "tmr.h"
static mxc_i2c_req_t reqMaster;

uint8_t u8x8_byte_hw_i2c_max78000(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
  static uint8_t buffer[32];		/* u8g2/u8x8 will never send more than 32 bytes between START_TRANSFER and END_TRANSFER */
  static uint8_t buf_idx;
  uint8_t *data;

  switch(msg){

    case U8X8_MSG_BYTE_SEND:
      data = (uint8_t *)arg_ptr;
      while( arg_int > 0 ){
				buffer[buf_idx++] = *data;
				data++;
				arg_int--;
			}
    break;

    case U8X8_MSG_BYTE_INIT:
      /* add your custom code to init i2c subsystem */
    break;

    case U8X8_MSG_BYTE_START_TRANSFER:
      buf_idx = 0;
    break;

    case U8X8_MSG_BYTE_END_TRANSFER:
    	 reqMaster.i2c     = OLED_I2C;
		 reqMaster.addr    = OLED_I2C_ADDR;
		 reqMaster.tx_buf  = buffer;
		 reqMaster.tx_len  = buf_idx;
		 reqMaster.rx_buf  = NULL;
		 reqMaster.rx_len  = 0;
		 reqMaster.restart = 0;
    	 MXC_I2C_MasterTransaction(&reqMaster);
    break;

    default:
      return 0;
  }
  return 1;
}

uint8_t u8g2_gpio_and_delay_max78000(U8X8_UNUSED u8x8_t *u8x8, U8X8_UNUSED uint8_t msg, U8X8_UNUSED uint8_t arg_int, U8X8_UNUSED void *arg_ptr)
{
	switch(msg){

	case U8X8_MSG_GPIO_AND_DELAY_INIT:
	    break;

	case U8X8_MSG_DELAY_MILLI:
		MXC_Delay(MXC_DELAY_MSEC(arg_int));
	    break;

	case U8X8_MSG_GPIO_I2C_CLOCK:
        break;

    case U8X8_MSG_GPIO_I2C_DATA:
        break;

	default:
		return 0;
	}
	return 1; // command processed successfully.
}

下面是U8g2的应用程序,实现3个画面显示不同内容。

/*u8g2显示函数*/
void drawOLED(u8g2_t *u8g2)
{
	if (page_id==0)
	{
		u8g2_SetFontMode(u8g2, 1);

		u8g2_SetFont(u8g2, u8g2_font_inr16_mr);
		u8g2_DrawStr(u8g2,5,40,"I");;

		u8g2_SetFont(u8g2, u8g2_font_open_iconic_human_4x_t);
		u8g2_DrawGlyph(u8g2,20,50,66);

		u8g2_SetFont(u8g2, u8g2_font_inr16_mr);
		u8g2_DrawStr(u8g2,55,40,"CHINA");}

	else if (page_id==1)
	{
		u8g2_SetFontMode(u8g2, 1);
		u8g2_SetFont(u8g2, u8g2_font_wqy16_t_gb2312);

		u8g2_DrawGlyph(u8g2,30,20,9733);
		u8g2_DrawGlyph(u8g2,50,20,9734);
		u8g2_DrawGlyph(u8g2,70,20,9733);
		u8g2_DrawGlyph(u8g2,90,20,9734);

		u8g2_DrawUTF8(u8g2,25,40,"自 强 不 息");

		u8g2_DrawGlyph(u8g2,30,60,9733);
		u8g2_DrawGlyph(u8g2,50,60,9734);
		u8g2_DrawGlyph(u8g2,70,60,9733);
		u8g2_DrawGlyph(u8g2,90,60,9734); }
	else if (page_id==2)
	{
		u8g2_SetFontMode(u8g2, 1);

		u8g2_SetFont(u8g2, u8g2_font_open_iconic_weather_4x_t);
		u8g2_DrawGlyph(u8g2,10,50,66);
		u8g2_DrawGlyph(u8g2,50,50,68);
		u8g2_DrawGlyph(u8g2,90,50,69);}
}

程序都完成后,将三部分程序都完成后,将几个程序进行整合与测试。

int main()
{
    MXC_Delay(MXC_DELAY_MSEC(500)); //Wait for PMIC to power-up

    /* Enable cache */
      MXC_ICC_Enable(MXC_ICC0);

      /* Set system clock to 100 MHz */
      MXC_SYS_Clock_Select(MXC_SYS_CLOCK_IPO);
      SystemCoreClockUpdate();
      MXC_TFT_Init(MXC_SPI0, 1, NULL, NULL);//TFT屏初始化


    int error;
    error = MXC_I2C_Init(OLED_I2C, 1, 0);//I2C初始化

    if (error != E_NO_ERROR) {
        printf("-->Failed master\n");
        while (1)
            ;
    } else {
        printf("\n-->I2C Initialization Complete");
    }
    MXC_I2C_SetFrequency(OLED_I2C, I2C_FREQ);


    #ifdef SSD1306_USE_I2C_HW
    u8g2_Setup_ssd1306_i2c_128x64_noname_2(&u8g2, U8G2_R0, u8x8_byte_hw_i2c_max78000, u8g2_gpio_and_delay_max78000);
    #endif

   u8g2_InitDisplay(&u8g2);
   u8g2_SetPowerSave(&u8g2, 0);

    while (1)
   	    {
    	    MXC_Delay(MXC_DELAY_SEC(3));
   	    	  /* 延时 3s */
   	        u8g2_FirstPage(&u8g2);

   	        ctrlPageID();//控制界面自动切换

   	        ctrlLED();  //控制指示灯显示
   	        drawTFT();//控制TFT屏显示

   	        do
   	        {
   	          drawOLED(&u8g2);//u8g2控制OLED显示
   	        } while( u8g2_NextPage(&u8g2) );
   	    }
}

 

三、效果演示

系统上电后,TFT屏、OLED屏、指示灯等都会在三个状态间进行自动切换。下面是演示效果。

Fi81bUaFXX8Q8yiFzaflPxNhwGZs

Fv9lyGsKQVCjhroidh1nCjCYaleu

FsgPtRaQehs7gHjqwYhmvKRkKBTa

四、心得体会

因种种原因,没有进行AI相关项目。

此显示系统仅完成初步功能,后续计划和摄像头结合,完成颜色识别追踪等功能。

 

附件下载
DiscoverMAX78000.rar
团队介绍
老胡,自动化工程师,电子爱好者
评论
0 / 100
查看更多
目录
硬禾服务号
关注最新动态
0512-67862536
info@eetree.cn
江苏省苏州市苏州工业园区新平街388号腾飞创新园A2幢815室
苏州硬禾信息科技有限公司
Copyright © 2024 苏州硬禾信息科技有限公司 All Rights Reserved 苏ICP备19040198号