点亮AliOS Things IOT开发板上的的OLED全彩屏

简介: 点亮AliOS Things IOT开发板上的的OLED全彩屏

640.jpg

   如图所示,这个板子的OLED驱动在开源例程里给出,但是不是基于Keil MDK来开发的,只是用CubeMX生成了对应的驱动源码,现在我将它的驱动移植到Keil MDK上来,屏的代码可以参考:

https://github.com/alibaba/AliOSThings/tree/rel_3.0.0/app/example/dk/dk_gui

一、LCD的管脚定义以及在开发板上对应的IO

640.jpg

   屏在开发板上的连接,参考开发板在github上提供的文档关于CubeMX配置,可以找到LCD相关的管脚。

640.jpg

相关的管脚连接

640.jpg

640.png

640.png

640.png

640.png

640.png

640.png

即是下面这几个核心的管脚

640.png

二、开始stm32CubeMX的配置

2.1 时钟配置

640.png

640.jpg

2.2 SPI配置

640.png

640.png

2.3 GPIO配置

640.png

640.png

640.png

640.png

三、生成代码与LCD驱动移植

640.jpg

LCD的初始化代码以及寄存器手册详情可参考:
https://download.csdn.net/download/bhtlbhtl123/8963365

接下来看一下我移植过来的ST7789.h

#ifndef __ST7789_H
#define __ST7789_H
#include "main.h"
#include "spi.h"
#define WIDTH        240
#define HEIGHT        240
#define BPP        16
#define LCD_MAX_MEM16_BLOCK             (1 << 6)
#define LCD_PIXEL_PER_BLOCK             (LCD_MAX_MEM16_BLOCK >> 1)
/* Init script function */
struct st7789_function {
  uint8_t cmd;
  uint16_t data;
};
/* Init script commands */
enum st7789_cmd {
  ST7789_START,
  ST7789_END,
  ST7789_CMD,
  ST7789_DATA,
  ST7789_DELAY
};
/* ST7789 Commands */
#define ST7789_CASET    0x2A
#define ST7789_RASET    0x2B
#define ST7789_RAMWR    0x2C
#define ST7789_RAMRD    0x2E
//LCD初始化
int st7789_init(void);
//写寄存器
void LcdWriteReg(uint8_t Data);
//写数据
void LcdWriteData(uint8_t Data);
//将多个值写入显示寄存器
void LcdWriteDataMultiple(uint8_t * pData, int NumItems);
//写一个像素到指定位置
void ST7789H2_WritePixel(uint16_t Xpos, uint16_t Ypos, uint16_t RGBCode);
//写一行数据    
void ST7789H2_WriteLine(uint16_t Xpos, uint16_t Ypos, uint16_t *RGBCode, uint16_t pointNum);
//显示图片
void st7789_display_picture(void);
#endif //__ST7789_H

ST7789.c

#include "ST7789.h"
static SPI_HandleTypeDef *hspi_lcd = NULL;
uint8_t black_gui[480] = {0};
uint8_t endian_buffer[480];
//参考LCD的寄存器手册
static struct st7789_function st7789_cfg_script[] = {
  {ST7789_START, ST7789_START},
  {ST7789_CMD, 0x11},
  {ST7789_DELAY, 120},
  {ST7789_CMD, 0x36},
  {ST7789_DATA, 0x00},
  {ST7789_CMD, 0x3a},
  {ST7789_DATA, 0x05},
  {ST7789_CMD, 0xb2},
  {ST7789_DATA, 0x0c},
  {ST7789_DATA, 0x0c},
  {ST7789_DATA, 0x00},
  {ST7789_DATA, 0x33},
  {ST7789_DATA, 0x33},
  {ST7789_CMD, 0xb7},
  {ST7789_DATA, 0x72},
  {ST7789_CMD, 0xbb},
  {ST7789_DATA, 0x3d},
  {ST7789_CMD, 0xc2},
  {ST7789_DATA, 0x01},
  {ST7789_CMD, 0xc3},
  {ST7789_DATA, 0x19},
  {ST7789_CMD, 0xc4},
  {ST7789_DATA, 0x20},
  {ST7789_CMD, 0xc6},
  {ST7789_DATA, 0x0f},
  {ST7789_CMD, 0xd0},
  {ST7789_DATA, 0xa4},
  {ST7789_DATA, 0xa1},
  {ST7789_CMD, 0xe0},
  {ST7789_DATA, 0x70},
  {ST7789_DATA, 0x04},
  {ST7789_DATA, 0x08},
  {ST7789_DATA, 0x09},
  {ST7789_DATA, 0x09},
  {ST7789_DATA, 0x05},
  {ST7789_DATA, 0x2a},
  {ST7789_DATA, 0x33},
  {ST7789_DATA, 0x41},
  {ST7789_DATA, 0x07},
  {ST7789_DATA, 0x13},
  {ST7789_DATA, 0x13},
  {ST7789_DATA, 0x29},
  {ST7789_DATA, 0x2f},
  {ST7789_CMD, 0xe1},
  {ST7789_DATA, 0x70},
  {ST7789_DATA, 0x03},
  {ST7789_DATA, 0x09},
  {ST7789_DATA, 0x0a},
  {ST7789_DATA, 0x09},
  {ST7789_DATA, 0x06},
  {ST7789_DATA, 0x2b},
  {ST7789_DATA, 0x34},
  {ST7789_DATA, 0x41},
  {ST7789_DATA, 0x07},
  {ST7789_DATA, 0x12},
  {ST7789_DATA, 0x14},
  {ST7789_DATA, 0x28},
  {ST7789_DATA, 0x2e},
  {ST7789_CMD, 0x21},
  {ST7789_CMD, 0x29},
  {ST7789_CMD, 0x2a},
  {ST7789_DATA, 0x00},
  {ST7789_DATA, 0x00},
  {ST7789_DATA, 0x00},
  {ST7789_DATA, 0xef},
  {ST7789_CMD, 0x2b},
  {ST7789_DATA, 0x00},
  {ST7789_DATA, 0x00},
  {ST7789_DATA, 0x00},
  {ST7789_DATA, 0xef},
  {ST7789_CMD, 0x2c},
  {ST7789_END, ST7789_END},
};
//ST7789复位
static void st7789_reset(void)
{    
  HAL_GPIO_WritePin(LCD_RST_GPIO_Port, LCD_RST_Pin, GPIO_PIN_SET); 
  HAL_Delay(1);
  HAL_GPIO_WritePin(LCD_RST_GPIO_Port, LCD_RST_Pin, GPIO_PIN_RESET);
  HAL_Delay(10);
  HAL_GPIO_WritePin(LCD_RST_GPIO_Port, LCD_RST_Pin, GPIO_PIN_SET);  
  HAL_Delay(120);
}
//打开LCD电源
void st7789_power_on(void)
{
    HAL_GPIO_WritePin(LCD_PWR_GPIO_Port, LCD_PWR_Pin, GPIO_PIN_SET); 
}
//ST7789写函数
static HAL_StatusTypeDef st7789_write(int is_cmd, uint8_t data)
{
  uint8_t pData[2] = {0};
  assert_param(NULL != hspi_lcd);
  pData[0] = data;
    if (is_cmd)
        HAL_GPIO_WritePin(LCD_DCX_GPIO_Port, LCD_DCX_Pin, GPIO_PIN_RESET);  
    else
        HAL_GPIO_WritePin(LCD_DCX_GPIO_Port, LCD_DCX_Pin, GPIO_PIN_SET);  
  return HAL_SPI_Transmit(hspi_lcd, pData, 1, HAL_MAX_DELAY);
}
static HAL_StatusTypeDef st7789_write_fb(uint16_t *data, uint16_t size)
{
  assert_param(NULL != hspi_lcd);
  return HAL_SPI_Transmit(hspi_lcd, (uint8_t *)data, size, HAL_MAX_DELAY);
}
/********************************************************************
*
*       LcdWriteReg
*
* Function description:
*   Sets display register
*/
void LcdWriteReg(uint8_t Data) 
{
  HAL_GPIO_WritePin(LCD_DCX_GPIO_Port, LCD_DCX_Pin, GPIO_PIN_RESET);  
  HAL_SPI_Transmit(&hspi1, &Data, 1, 10);
}
/********************************************************************
*
*       LcdWriteData
*
* Function description:
*   Writes a value to a display register
*/
void LcdWriteData(uint8_t Data) 
{
  HAL_GPIO_WritePin(LCD_DCX_GPIO_Port, LCD_DCX_Pin, GPIO_PIN_SET);    
  HAL_SPI_Transmit(&hspi1, &Data, 1, 10);
}
/********************************************************************
*
*       LcdWriteDataMultiple
*
* Function description:
*   Writes multiple values to a display register.
*/
void LcdWriteDataMultiple(uint8_t * pData, int NumItems) 
{
  HAL_GPIO_WritePin(LCD_DCX_GPIO_Port, LCD_DCX_Pin, GPIO_PIN_SET);
  HAL_SPI_Transmit(&hspi1, pData, NumItems, 10);
}
//配置启动参数
static void st7789_run_cfg_script(void)
{
  uint8_t data[2] = {0};
  int i = 0;
  int end_script = 0;
  do {
    switch (st7789_cfg_script[i].cmd) {
    case ST7789_START:
      break;
    case ST7789_CMD:
      data[0] = st7789_cfg_script[i].data & 0xff;
      st7789_write(1, data[0]);
      break;
    case ST7789_DATA:
      data[0] = st7789_cfg_script[i].data & 0xff;
      st7789_write(0, data[0]);
      break;
    case ST7789_DELAY:
      HAL_Delay(120);
      break;
    case ST7789_END:
      end_script = 1;
    }
    i++;
  } while (!end_script);
}
//设置地址
static void st7789_set_addr_win(uint16_t xs, uint16_t ys, uint16_t xe, uint16_t ye)
{
  uint8_t col_data[4] = {0};
  uint8_t row_data[4] = {0};
  col_data[0] = xs >> 8 & 0xff;
  col_data[1] = xs & 0xff;
  col_data[2] = xe >> 8 & 0xff;
  col_data[3] = xe & 0xff;
  row_data[0] = ys >> 8 & 0xff;
  row_data[1] = ys & 0xff;
  row_data[2] = ye >> 8 & 0xff;
  row_data[3] = ye & 0xff;
  st7789_write(1, ST7789_CASET);
  st7789_write(0, col_data[0]);
  st7789_write(0, col_data[1]);
  st7789_write(0, col_data[2]);
  st7789_write(0, col_data[3]);
  st7789_write(1, ST7789_RASET);
  st7789_write(0, row_data[0]);
  st7789_write(0, row_data[1]);
  st7789_write(0, row_data[2]);
  st7789_write(0, row_data[3]);
}
//发送到显示区域
static void spec_send_fb(uint16_t color, uint16_t pixel_num)
{
  int i;
  int count, remain;
  uint16_t real_mem[LCD_MAX_MEM16_BLOCK] = {0};
  for (i = 0; i < LCD_MAX_MEM16_BLOCK; ++i) {
    real_mem[i] = color;
  }
  HAL_GPIO_WritePin(LCD_DCX_GPIO_Port, LCD_DCX_Pin, GPIO_PIN_SET);
  if (pixel_num <= LCD_MAX_MEM16_BLOCK) {
    st7789_write_fb(real_mem, pixel_num << 1);
  } else {
    count = pixel_num / LCD_MAX_MEM16_BLOCK;
    remain = pixel_num % LCD_MAX_MEM16_BLOCK;
    for (i = 0; i < count; ++i) {
      st7789_write_fb(real_mem, LCD_MAX_MEM16_BLOCK << 1);
    }
    st7789_write_fb(real_mem, remain << 1);
  }
}
//显示图片
void st7789_display_picture(void)
{
  st7789_write(1, ST7789_RAMWR);
  spec_send_fb(0x0, WIDTH * HEIGHT / 4);
  spec_send_fb(0x1111, WIDTH * HEIGHT / 4);
  spec_send_fb(0x7777, WIDTH * HEIGHT / 4);
  spec_send_fb(0xeeee, WIDTH * HEIGHT / 4);
}
//写寄存器
void ST7789H2_WriteReg(uint8_t Command, uint8_t *Parameters, uint8_t NbParameters)
{
  uint8_t   i;
  /* Send command */
  LcdWriteReg(Command);
  /* Send command's parameters if any */
  for (i=0; i<NbParameters; i++)
  {
    LcdWriteData(Parameters[i]);
  }
}
//在指定位置设置光标
void ST7789H2_SetCursor(uint16_t Xpos, uint16_t Ypos)
{
  uint8_t   parameter[4];
  /* CASET: Comumn Addrses Set */
  parameter[0] = 0x00;     
  parameter[1] = 0x00 + Xpos;
  parameter[2] = 0x00;
  parameter[3] = 0xEF + Xpos;
  ST7789H2_WriteReg(0x2A, parameter, 4);
  /* RASET: Row Addrses Set */  
  parameter[0] = 0x00;
  parameter[1] = 0x00 + Ypos;
  parameter[2] = 0x00;
  parameter[3] = 0xEF + Ypos;
  ST7789H2_WriteReg(0x2B, parameter, 4);
}
//清屏
void BSP_LCD_Clear(void)
{
  uint32_t counter = 0;
  uint32_t y_size = 0;
    memset(black_gui, 0x00, sizeof(black_gui));
  for (counter = 0; counter < 240; counter++)
  {
        /* Set Cursor */
        ST7789H2_SetCursor(0, counter); 
        /* Prepare to write to LCD RAM */
        ST7789H2_WriteReg(0x2C, (uint8_t*)NULL, 0);   /* RAM write data command */
        LcdWriteDataMultiple(black_gui, 480);    
  }
}
//往指定区域写一个像素
void ST7789H2_WritePixel(uint16_t Xpos, uint16_t Ypos, uint16_t data)
{
  uint8_t dataB = 0;
  /* Set Cursor */
  ST7789H2_SetCursor(Xpos, Ypos);
  /* Prepare to write to LCD RAM */
  ST7789H2_WriteReg(0x2C, (uint8_t*)NULL, 0);   /* RAM write data command */
  /* Write RAM data */
  dataB = (uint8_t)(data >> 8);
  LcdWriteData(dataB);
  dataB = (uint8_t)data;
  LcdWriteData(dataB);
}
//往指定区域写一行数据
void ST7789H2_WriteLine(uint16_t Xpos, uint16_t Ypos, uint16_t *RGBCode, uint16_t pointNum)
{
  int i = 0;
  /* Set Cursor */
  ST7789H2_SetCursor(Xpos, Ypos);
  /* Prepare to write to LCD RAM */
  ST7789H2_WriteReg(0x2C, (uint8_t*)NULL, 0);   /* RAM write data command */
  for (i = 0; i < pointNum; i++) {
    endian_buffer[2*i] = (uint8_t)(RGBCode[i] >> 8);
    endian_buffer[2*i + 1] = (uint8_t)RGBCode[i];
  }
  /* Write RAM data */
  LcdWriteDataMultiple(endian_buffer, pointNum*2);
}
//ST7789初始化
int st7789_init(void)
{
  hspi_lcd = &hspi1;
  st7789_power_on();
  st7789_reset();
  st7789_run_cfg_script();
  return HAL_OK;
}

在main.c中添加逻辑:

/**
  * @brief  The application entry point.
  * @retval int
  */
int main(void)
{
  /* USER CODE BEGIN 1 */
  /* USER CODE END 1 */
  /* MCU Configuration--------------------------------------------------------*/
  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();
  /* USER CODE BEGIN Init */
  /* USER CODE END Init */
  /* Configure the system clock */
  SystemClock_Config();
  /* USER CODE BEGIN SysInit */
  /* USER CODE END SysInit */
  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_SPI1_Init();
  /* USER CODE BEGIN 2 */
  st7789_init();
  st7789_display_picture();
  /* USER CODE END 2 */
  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */
    /* USER CODE BEGIN 3 */
      HAL_GPIO_TogglePin(LED_GPIO_Port, LED_Pin);
      HAL_Delay(200);
  }
  /* USER CODE END 3 */
}

四、运行结果

640.jpg

   由于这个板子遗留较多硬件问题且诺行不愿在开发板出厂时修复;开发板相关文档较乱,所以只能靠自己慢慢探索咯,总体来说,这个板子还是非常强大的,可以用做日常学习,详情可看:

https://github.com/alibaba/AliOS-Things/wiki/Developer-Kit-Tutorial

目录
相关文章
|
传感器 数据采集 安全
|
算法 物联网 AliOS-Things
AliOS Things IOT开发板初体验(基于STM32L496VGTx)
AliOS Things IOT开发板初体验(基于STM32L496VGTx)
517 0
|
物联网
|
监控 小程序 物联网
华为认证物联网开发利器:小熊派IoT开发板
华为认证物联网开发利器:小熊派IoT开发板
华为认证物联网开发利器:小熊派IoT开发板
|
物联网 芯片
U1 NB-IoT开发板上云例程操作解析
本文介绍 U1 NB-IoT开发板上云例程操作解析
1039 0
U1 NB-IoT开发板上云例程操作解析
|
3月前
|
物联网 数据管理 Apache
拥抱IoT浪潮,Apache IoTDB如何成为你的智能数据守护者?解锁物联网新纪元的数据管理秘籍!
【8月更文挑战第22天】随着物联网技术的发展,数据量激增对数据库提出新挑战。Apache IoTDB凭借其面向时间序列数据的设计,在IoT领域脱颖而出。相较于传统数据库,IoTDB采用树形数据模型高效管理实时数据,具备轻量级结构与高并发能力,并集成Hadoop/Spark支持复杂分析。在智能城市等场景下,IoTDB能处理如交通流量等数据,为决策提供支持。IoTDB还提供InfluxDB协议适配器简化迁移过程,并支持细致的权限管理确保数据安全。综上所述,IoTDB在IoT数据管理中展现出巨大潜力与竞争力。
106 1
|
14天前
|
安全 物联网 网络安全
智能设备的安全隐患:物联网(IoT)安全指南
智能设备的安全隐患:物联网(IoT)安全指南
42 12
|
12天前
|
传感器 监控 安全
物联网(IoT):定义、影响与未来
物联网(IoT):定义、影响与未来
33 3
下一篇
无影云桌面