发作品签到
专业版

基于立创·梁山派的智能LED灯带遥控器设计

工程标签

1.5k
0
0
0

简介

基于立创·梁山派的智能LED灯带遥控器,跟我的毕设一脉相承,但搭载更顶级的触摸屏

简介:基于立创·梁山派的智能LED灯带遥控器,跟我的毕设一脉相承,但搭载更顶级的触摸屏

开源协议

GPL 3.0

创建时间:2023-01-13 21:05:33更新时间:2023-04-18 13:44:26

描述

 

一、前言

前些阵子我完成了毕设的代码部分以及部分的硬件部分,偶然间看到了可以免费申请立创梁山派,于是就想到把我的毕设移植到立创梁山派中。

 

二、项目功能

本项目是根据毕设的遥控器部分移植而来的,遥控器的具体功能就是运行用户GUI界面,用户通过操作GUI界面可以无线控制LED灯带的各种属性,如改变颜色、切换显示模式等等。

无线控制的功能通过ESP8266模块实现,使用WiFi协议栈与LED灯带控制器进行通信。

 

三、项目方案

通过上面分析本项目的功能需求,我们只需要准备触控屏和WiFi模块。

为了方便硬件设计,使最终的硬件更加美观,触控屏最好选择与梁山派差不多大小的型号,最终我选择了一块3.5寸的IPS电容触摸屏作为本项目的屏幕。

相比于TFT显示屏,IPS显示屏能拥有更好的可视角度,色域表现也要好与常规的LCD显示屏。触摸方案选择电容屏,是因为这种触摸方式优雅;大多数用于学习板的屏幕都喜欢使用较便宜的电阻触摸屏,电阻触摸屏的缺点就是要很大力地按(有时候要戳)才能读取到触摸点;而使用电容触摸方案的话只需轻点即可读取到触摸点。

显示屏的控制芯片为ST7796U,触摸芯片为GT911

WiFi模块方面,因为本项目只需要实现基本的WiFi功能,即使用TCP与LED灯带控制器通信,通信包的协议也是我设计的,所以这里选择最便宜的ESP8266模块即可。

YXBkv0JfHOG4vtOoxsUjVJ84JxqITpkaxTGOKtjQ.png

 

四、硬件设计

 

1. 显示屏

在梁山派上提供了一个TFT屏幕的排线连接座,该排线座可以使用EXMC外设对显示屏进行通信。

1NFnzAhX1PxZLo3gE4sidUUOOxkm2vmzGe8Abgho.png

因此只需要设计一个与之对应的排线座连接即可。梁山派上的这个排线座不仅支持8080并口协议,还支持SPII2C协议,所以有一些通信管脚是不需要的。但因为我的屏幕带触摸功能,触摸芯片使用I2C协议进行通信,因此我巧妙地将排线座上I2C通信的管脚留给了触摸芯片;后面发现还差了一根复位线,这里就用SPI3的片选线代替了。

s4ihZd1kpCnc7adU1HsZ2Q797iBm5AsNbSAK4HmA.png

因为屏幕是通过排针连接的,所以也要设计一个与之对应的排母座进行连接。使用万用表进行测试,我发现厂家的屏幕板上面是没有I2C的上拉电阻的,因此在这边加上。

2eyDJopsy4HJ8he8zECm5HYDGln6AGSyQkhVNhtv.png

 

2. ESP8266模块

WiFi模块的硬件设计也不难,只要跟着乐鑫官方的硬件设计指南,设计一个ESP8266模块的最小系统即可。

dME0GYDZz9UwIuQMhazU4iEvmG1PzID2hpaEJB3L.pngDNtk61sa9dAVERP7nhS7bHvjQnVYSvRZRZrsQ6UW.pngnVTIZvx6s7lYy1JaFe85A1msgDbdijcj987NS39P.png

ESP8266的串口会比较鸡肋,只有两个,而且两个串口的其中一根线是复用的。在硬件设计中我把ESP8266的串口0与梁山派的串口2进行连接,但因为ESP8266的串口0是下载接口,因此我设计了一个排针座;当需要往ESP8266下载程序时,断开与梁山派的连接;当正常使用时,用跳帽连接排针,实现与梁山派的通信。

rsWQ0dZZ4KixHRvb0Ge8x49W1LW12yaEATOfz0OB.png

 

五、软件设计

本项目最难的地方在于软件的设计,当中涉及到GD32单片机中EXMC外设的使用,及如何使用EXMC外设驱动LCD屏幕;为了充分发挥梁山派的性能,我往里面移植了FreeRTOS系统;GUI界面使用当下很火的LVGL库实现,该库的移植和应用也是不小的挑战。

 

1. 显示屏

显示屏的EXMC外设部分核心驱动代码。

/**
  * @brief  Initialized EXMC
  * @param  None
  * @retval None
  */
static void ST7796_EXMCInit(void)
{
    exmc_norsram_parameter_struct exmc_init_struct;
    exmc_norsram_timing_parameter_struct exmc_timing_struct;
    
    /* config FMC clock */
    rcu_periph_clock_enable(EXMC_CLK);
    
    exmc_timing_struct.asyn_access_mode = EXMC_ACCESS_MODE_B;
    exmc_timing_struct.asyn_address_setuptime = 5;  // 5 / 240MHz ≈ 20ns
    exmc_timing_struct.asyn_data_setuptime = 4;  // (4 + 1) / 240MHz ≈ 20ns
    exmc_timing_struct.asyn_address_holdtime = 0;  // unused
    exmc_timing_struct.bus_latency = 0;  // unused
    exmc_timing_struct.syn_data_latency = 0;  // unused
    exmc_timing_struct.syn_clk_division = 0;  // unused

    exmc_init_struct.address_data_mux = DISABLE;
    exmc_init_struct.asyn_wait = DISABLE;
    exmc_init_struct.burst_mode = DISABLE;
    exmc_init_struct.databus_width = EXMC_NOR_DATABUS_WIDTH_16B;
    exmc_init_struct.extended_mode = DISABLE;
    exmc_init_struct.memory_type = EXMC_MEMORY_TYPE_NOR;
    exmc_init_struct.memory_write = ENABLE;
    exmc_init_struct.norsram_region = EXMC_BANK0_REGIONx;
    exmc_init_struct.nwait_config = EXMC_NWAIT_CONFIG_BEFORE;
    exmc_init_struct.nwait_polarity = EXMC_NWAIT_POLARITY_LOW;
    exmc_init_struct.nwait_signal = DISABLE;
    exmc_init_struct.wrap_burst_mode = DISABLE;
    exmc_init_struct.write_mode = EXMC_ASYN_WRITE;
    exmc_init_struct.read_write_timing = &exmc_timing_struct;
    exmc_init_struct.write_timing = &exmc_timing_struct;
    
    exmc_norsram_init(&exmc_init_struct);
    exmc_norsram_enable(EXMC_BANK0_REGIONx);
}

在设置时序的时候,地址建立时间和数据建立时间在数据手册中是10ns左右,为了保险设置为20ns左右。还要注意,梁山派上的8080并口DC信号对应A10地址线,片选信号对应NE3,也就是Region3,这对于确定数据和命令的读写地址尤为重要。

 

下面是显示屏的数据写和命令写代码,因为我们已经配置好EXMC外设,所以向显示屏写数据就好像给单片机内存赋值一样简单。

/**
  * @brief    Write command
  * @param  cmd: command
  * @retval None
  */
__inline void ST7796_WriteCmd(uint16_t cmd)
{
    *( __IO uint16_t*)(EXMC_Addr_ST7796_CMD) = cmd;
}

/**
  * @brief  Write data
  * @param  data: data
  * @retval None
  */
__inline void ST7796_WriteData(uint16_t data)
{
    *( __IO uint16_t*)(EXMC_Addr_ST7796_DATA) = data;
}

 

2. WiFi模块

ESP8266使用Arduino框架进行编写,代码很简单就是负责把梁山派通过串口发送过来的数据,通过WiFi转发到LED灯带控制器端即可。

static void dump_buf_to_serial(uint8_t* buf, uint16_t size) {
  Serial.print("Data: ");
  for (uint16_t i = 0; i < size; i++) {
    Serial.printf("%02X ", buf[i]);
  }
  Serial.println();
}

static void receive_package(void) {
  memset(cmd_buf, 0x00, sizeof(cmd_buf));
  Serial.read(cmd_buf, sizeof(cmd_buf));
  for (cmd_size = sizeof(cmd_buf); !cmd_buf[cmd_size-1]; cmd_size--) {}
  Serial.println("Receive from host");
  dump_buf_to_serial(cmd_buf, cmd_size);
}

void setup() {
  Serial.begin(115200);

  WiFi.begin(WIFI_SSID, WIFI_PSW);
  Serial.print("WiFi connecting");
  while (WiFi.status() != WL_CONNECTED)
  {
    Serial.print(".");
    delay(500);
  }
  Serial.printf("\nIP: %s\n", WiFi.localIP().toString().c_str());
}

void loop() {
  if (Serial.available()) {
    delay(10);
    receive_package();
    if (client.connect(SERVER_IP, SERVER_PORT)) {
      Serial.println("Connected to server");
      while (client.connected()) {
        client.write(cmd_buf, cmd_size);
        
        uint16_t timeout = TIMEOUT_MS;
        while (timeout--) {
          if (resp_size = client.available()) {
            memset(resp_buf, 0x00, sizeof(resp_buf));
            client.read(resp_buf, resp_size);
            Serial.println("Receive from server");
            dump_buf_to_serial(resp_buf, resp_size);
            break;
          }
          delay(1);
        }
        break;
      }
    }
    else {
      Serial.println("Connected to server failed");
    }
    
    while(Serial.read() > 0);
  }
}

 

在主机端,为了提高数据发送给ESP8266的效率,我还使用DMA进行串口发送,这样主机在串口数据发送的时候就可以完成其他任务。

 

dma_single_data_parameter_struct dma_init_struct;

dma_deinit(ESP8266_DMAx, ESP8266_DMA_CHy);

dma_init_struct.memory0_addr = (uint32_t)buf;
dma_init_struct.memory_inc = DMA_MEMORY_INCREASE_ENABLE;
dma_init_struct.periph_addr = (uint32_t)ESP8266_USART_DR;
dma_init_struct.periph_inc = DMA_PERIPH_INCREASE_DISABLE;
dma_init_struct.periph_memory_width = DMA_PERIPH_WIDTH_8BIT;
dma_init_struct.number = size;
dma_init_struct.direction = DMA_MEMORY_TO_PERIPH;
dma_init_struct.circular_mode = DMA_CIRCULAR_MODE_DISABLE;
dma_init_struct.priority = DMA_PRIORITY_MEDIUM;

dma_single_data_mode_init(ESP8266_DMAx, ESP8266_DMA_CHy, &dma_init_struct);
dma_channel_subperipheral_select(ESP8266_DMAx, ESP8266_DMA_CHy, DMA_SUBPERI4);
dma_flag_clear(ESP8266_DMAx, ESP8266_DMA_CHy, DMA_FLAG_FTF);
dma_channel_enable(ESP8266_DMAx, ESP8266_DMA_CHy);

3. 屏幕UI

GUI使用了当下较火的LVGL库进行设计,该库最低需要64KB的Flash空间和8KB的RAM空间,但对于性能强大的梁山派简直不在话下啦。

在使用LVGL进行GUI设计时,建议搭建一个模拟器,在模拟器中把GUI代码写好,再移植到单片机中写交互代码,这样就省去了频繁烧录的麻烦。

vex9nQ4UNQIUYHIks3Wh221pDlRQeRJaVeKSgvJp.png

 

六、附件资料

梁山派主控和ESP8266的源码在下面的Remote_Controller_Branch1.zip压缩包中,梁山派的主控使用Keil5开发,ESP8266使用VSCode+Platformio+Arduino开发

ESP8266的相关开发资料在下面的0a-esp8266ex_datasheet_cn.pdf、esp8266-technical_reference_cn.pdf、esp-wroom-02d_esp-wroom-02u_datasheet_cn.pdf文档中

设计图

未生成预览图,请在编辑器重新保存一次

BOM

暂无BOM

附件

序号文件名称下载次数
1
Remote_Controller_Branch1.zip
129
2
0a-esp8266ex_datasheet_cn.pdf
7
3
esp8266-technical_reference_cn.pdf
8
4
esp-wroom-02d_esp-wroom-02u_datasheet_cn.pdf
7
5
设计外观及功能展示.mp4
47
克隆工程
添加到专辑
0
0
分享
侵权投诉

工程成员

评论

全部评论(1
按时间排序|按热度排序
粉丝0|获赞0
相关工程
暂无相关工程

底部导航