stm32cubemx第七篇之mcu屏(代码片段)

海洋想想 海洋想想     2022-12-13     125

关键词:

文章目录

前言

本文主要讲解自己实现MCU控制程序。

本程序具有以下功能:

  1. 能够输出汉字
  2. 能够输出ASCII字符串
  3. 能够输出整数

本文使用的HAL库的版本为:STM32Cube_FW_F4_V1.25.0
本文使用的STM32CubeMX版本为:6.1.1

该工程的下载地址为:

关于MCU屏的相关知识,可以参考博客<硬件介绍之NT35510(80系列并口使用)>。

关于SRAM及其HAL库的介绍,可以参考博客<STM32F429第二十四篇之SRAM原理>和<STM32F429第二十五篇之MCU屏实验详解>。

主程序

/**
  ******************************************************************************
  * @file    main.c
  * @author  zhy
  * @version 1.0
  * @date    2021-05-13
  * @brief   通过SRAM控制LCD
  *             1.输出汉字
  *             2.输出英文字符串
  *             3.输出数字
  ******************************************************************************
  */

#include "stm32f4xx_hal.h"
#include "lcd.h"
#include "gpio.h"
#include "led.h"
#include "fmc.h"
#include "sys.h"
#include "delay.h"

int main()

    HAL_Init();
    SystemClock_Config();
    LedInit();
    GpioInit();
    SramInit();
    LcdInit();

    const uint8_t encode[] = 0, 1, 2, 255, 253;
    LcdShowChinese(encode);
    LcdShowNumber(123);
    LcdShowString("\\nHello, zhy!");
    
    while (1)
    
        delay_ms(500);
        LED0 = !LED0;
        LED1 = !LED0;
    


在主程序中,已经以下几个步骤:

  1. 外设配置
  2. 输出OLED屏内容
  3. 点亮LED灯,表现程序运行。

在外设初始化中,要注意到,LCD使用了SRAM和GPIO两个底层应用。GPIO用于点亮LCD的背光灯,而SRAM用于与LCD之间通信。所以,若要使用LCD,这两个模块的初始化必不可少!

在输出OLED屏内容的时候,可以知道:本文提供了方便的程序用于显示汉字,数字,以及字符串。

配置

模式A配置

首先,可以找到LCD的时序图如下所示:

通过观察上面的波形图,可以从SRAM所有的模式中选择模式A为比较符合,如下图所示:

所以,首先,应该确定读写使用模式A完成。模式A的寄存器配置如下:



对应程序如下:

    SRAM_HandleTypeDef hsram1 = 0;
    hsram1.Instance = FMC_NORSRAM_DEVICE;                           //设置SRAM的寄存器地址
    hsram1.Extended = FMC_NORSRAM_EXTENDED_DEVICE;                  //设置SRAM拓展寄存器地址
    hsram1.Init.NSBank = FMC_NORSRAM_BANK1;                         //设置存储区域的地址
    hsram1.Init.DataAddressMux = FMC_DATA_ADDRESS_MUX_DISABLE;      //设置数据与地址
    hsram1.Init.MemoryType = FMC_MEMORY_TYPE_SRAM;                  //存储类型
    hsram1.Init.MemoryDataWidth = FMC_NORSRAM_MEM_BUS_WIDTH_16;     //总线长度
    hsram1.Init.BurstAccessMode = FMC_BURST_ACCESS_MODE_DISABLE;    //不支持突发模式
    hsram1.Init.WaitSignalPolarity = FMC_WAIT_SIGNAL_POLARITY_HIGH; //等待信号极性:高
    hsram1.Init.WrapMode = FMC_WRAP_MODE_DISABLE;                   //禁止回卷模式
    hsram1.Init.WaitSignalActive = FMC_WAIT_TIMING_BEFORE_WS;       //等待状态一个数据周期NWAIT有效
    hsram1.Init.WriteOperation = FMC_WRITE_OPERATION_ENABLE;        //写操作使能
    hsram1.Init.WaitSignal = FMC_WAIT_SIGNAL_DISABLE;               //禁用等待信号
    hsram1.Init.ExtendedMode = FMC_EXTENDED_MODE_ENABLE;            //打开拓展模式
    hsram1.Init.AsynchronousWait = FMC_ASYNCHRONOUS_WAIT_DISABLE;   //同步等待
    hsram1.Init.WriteBurst = FMC_WRITE_BURST_DISABLE;               //写突发禁止
    hsram1.Init.ContinuousClock = FMC_CONTINUOUS_CLOCK_SYNC_ONLY;   //连续时钟同步
    hsram1.Init.PageSize = FMC_PAGE_SIZE_NONE;                      //页大小无

时序

在模式A中,读/写时序能够改变的时间选项共有三项:

  • BUSTURN:总线反转时间,范围为[0-15]
  • DATASET:数据建立时间,范围为[0-255]
  • ADDSET:地址建立时间,范围为[0-15]

通过观察,可以知道以上三个时间分别对应LCD时序中的前六项:

  1. 读/写 周期时间
  2. 读/写 低电平时间
  3. 读/写 高电平时间

所以,对应初始化程序如下:

    FMC_NORSRAM_TimingTypeDef readTiming = 0;
    readTiming.AccessMode = FMC_ACCESS_MODE_A; //读取模式为:A
    readTiming.AddressSetupTime = 15;          //地址建立时间(15/180M=83ns)
    readTiming.DataSetupTime = 9;              //数据建立时间(9/180M=50ns)
    readTiming.BusTurnAroundDuration = 8;      //总线反转时间((15+9+8)/180M=177ns)

    FMC_NORSRAM_TimingTypeDef writeTiming = 0;
    writeTiming.AccessMode = FMC_ACCESS_MODE_A; //写入模式为:A
    writeTiming.AddressSetupTime = 3;           //地址建立时间:(3/180M=16.6ns)
    writeTiming.DataSetupTime = 3;              //数据建立时间:(3/180M=16.6ns)
    writeTiming.BusTurnAroundDuration = 1;      //总线反转时间:(7/180M=38.8ns)

应用

下面介绍,如何通过指令来写入一个字符:

完整程序如下:

/** 
 * @brief 在给定位置显示给定颜色的汉字
 * @note 无
 * @param uint8_t pc 汉字编码数组
 * @param CharacterType type 字符类型:英文或者中文
 * @retval 无
 */
void ShowWord(const uint8_t *pc, CharacterType type)

    int length = 0;
    uint16_t *col = &character.st.y;
    uint16_t *row = &character.st.x;
    uint8_t sizeX = character.size;
    uint8_t sizeY = type == EN ? character.size >> 1 : character.size;

    /* 1.判断字符是否越界 */
    if (character.st.y + sizeY > LCD_WIDTH)
    
        character.st.x += sizeX;
        character.st.y = 0;
    
    if (character.st.x + sizeX > LCD_HEIGHT)
    
        return;
    

    /* 2.设置字符区域 */
    SetRegion(*col, *col + sizeY - 1, *row, *row + sizeX - 1);
    length = sizeX * sizeY >> 3;

    /* 3.写入字符 */
    LCD->command = 0x2c00;
    for (int i = 0; i < length; i++)
    
        uint8_t temp = pc[i];
        for (int j = 0; j < 8; j++)
        
            LCD->data = temp & 0x01 ? character.foreColor : character.backColor;
            temp >>= 1;
        
    

    /* 4.光标右移一个位置 */
    if (type == EN)
    
        LcdAddSpace(1);
    
    else
    
        LcdAddSpace(2);
    


这是在LCD中写入一个字符的程序,大致分成四个步骤:

  1. 判断是否越界
  2. 设置字符所在区域
  3. 写入字符
  4. 光标右移

其实除去多余的处理程序,写入一个字符只需要两个步骤即可:

  1. 设置字符所在的区域
  2. 写入字符

如下图所示:

设置字符所在区域的函数如下所示:

/** 
 * @brief 设置写入区域范围
 * @note 从0开始计数
 * @param uint16_t colS 开始的列数(包含)
 * @param uint16_t colE 结束的列数(包含)
 * @param uint16_t rowS 开始的行数(包含)
 * @param uint16_t rowE 结束的行数(包含)
 * @retval 无
 */
void SetRegion(uint16_t colS, uint16_t colE, uint16_t rowS, uint16_t rowE)

    /* 1.设置列范围 */
    __LcdWriteReg(0x2a00, colS >> 8);
    __LcdWriteReg(0x2a01, colS & 0xFF);
    __LcdWriteReg(0x2a02, colE >> 8);
    __LcdWriteReg(0x2a03, colE & 0xFF);

    /* 2.设置行范围 */
    __LcdWriteReg(0x2b00, rowS >> 8);
    __LcdWriteReg(0x2b01, rowS & 0xFF);
    __LcdWriteReg(0x2b02, rowE >> 8);
    __LcdWriteReg(0x2b03, rowE & 0xFF);

即使用指令0x2A和0X2B实现。

写入一个字符的具体实现部分如下:

    LCD->command = 0x2c00;
    for (int i = 0; i < length; i++)
    
        uint8_t temp = pc[i];
        for (int j = 0; j < 8; j++)
        
            LCD->data = temp & 0x01 ? character.foreColor : character.backColor;
            temp >>= 1;
        
    

首先,写入指令0x2c00。然后,通过判断字符编码,判断写入前景色还是背景色。

字符编码可以使用软件PCtoLCD2002 实现,本文不详细介绍其用法。其软件界面截图如下:

stm32f429第二十七篇之dma实验详解(代码片段)

文章目录前言结构体Instance(实例)Init(初始化结构体)Lock(锁)State(状态)XferCpltCallback(传输完成回调函数)XferHalfCpltCallback(传输完成一半回调函数)XferM1CpltCallback(内存1传输完成回调函数)XferM1HalfCpltCallback(内存1传输一半回调函数)XferErrorCa... 查看详情

stm32cubemx第八篇之dma(代码片段)

...的HAL库的版本为:STM32Cube_FW_F4_V1.25.0本实验使用的STM32CubeMX版本为:6.1.1该 查看详情

混合编程jni第七篇之jni的命令行们(代码片段)

 系列目录:【混合编程Jni】系列目录_香菜聊游戏的博客-CSDN博客        今天将继续JNI的学习,jni编程中常使用的一些命令行工具如何使用事半功倍,今天就快速的过一下,希望在接下来的使用中... 查看详情

stm32cubemx学习:05-串口(代码片段)

...stm32-cube-05-using-serial.mddate:2020-03-0910:37:34categories:tags:-stm32-cubeMx-serial---知识串口是一种通讯协议,存在于设备-设备之间。在介绍串口协议之前,我们先来看看通信网络中的分层。如果参考OSI模型,网络OSI七层模型及各层作用那么... 查看详情

stm32cubemx学习:06-配置dma(代码片段)

...e:mcu-stm32-cube-06-配置DMAdate:2020-05-3116:39:05categories:tags:-stm32-cubeMx-dma-serial---知识DMA(DirectMemoryAccess,直接存储器访问)用于在外设与存储器之间以及存储器与存储器之间提供高速数据传输。可以在无需任何CPU操作的情况下通过DMA快速... 查看详情

混合编程jni第七篇之jni的命令行们(代码片段)

        今天将继续JNI的学习,jni编程中常使用的一些命令行工具如何使用事半功倍,今天就快速的过一下,希望在接下来的使用中可以发挥效果    javahjavah是Java提供的生成jni头文件的... 查看详情

stm32cubedmx下载与安装(代码片段)

 §01STM32CubeMX一、安装版本STM32CubeMX是ST公司对于其MCU进行模组配置以及生成C语言工程文件的工具。在2015年安装使用的STM32CubeMX版本。▲图1.0早期安装的版本现在在官网可以看到现在的版本已经升级到6.30。所以需要对于软件进行... 查看详情

stm32f429第二十七篇之dma

文章目录前言基本流程通道选择优先级传输模式外设到内存内存到外设内存到内存双缓冲区模式直接模式循环模式DMA中断前言DMA(Directmemoryaccess)用于内存与内存之间或者内存与外设之间的高度数据传输。而且使用DMA进行数据传输... 查看详情

java基础第七篇之接口

1.什么是接口: *接口是方法的集合,而且接口中的方法全是抽象的 *你可以把接口看成一个特殊的"抽象类",接口中的方法全是抽象的 * * *2.java中怎么定义接口: *定义类的关键字:class *定义接口的关键字:inter... 查看详情

stm32cubemx安装和配置cube.ai教程(代码片段)

目录前言下载STCubeMxIDE安装过程配置Cube.AICube.AI背景知识CubeMX配置Cube.AI在项目中使用Cube.AI扩展库验证AI结尾小谈前言Stm32CubeMX是Stm32公司推出的一款专门为Stm32平台开发的IDE,通过它能够快速构建集成开发环境,与早期的STM... 查看详情

使用stm32cubemx生成stm32工程(代码片段)

使用STM32CubeMX生成STM32工程引言介绍使用流程引言随着技术发展的越来越成熟,单片机开发已经出现越来越多好用的开发软件了。STM32CubeMX是一种图形工具,通过分步过程可以非常轻松地配置STM32微控制器和微处理生成相应... 查看详情

stm32+lwip:使用stm32cubemx生成项目(代码片段)

系列文章:stm32+lwip(一):使用STM32CubeMX生成项目stm32+lwip(二):UDP测试stm32+lwip(三):TCP测试stm32+lwip(四):网页服务器测试stm32+lwip(五):以太网帧发送测试 STM32CubeMX是一个图形化的配置工具,根据用户配置可以生成相应的代码,可以帮助... 查看详情

区块链100篇之第七篇--比特币的分叉

遵循相同机制的分叉我在第六篇讲到了一种情况就是在比特币网络中,在某一时刻有两个矿工同时算出随机数(即获得记账权),那么这个时候便会出现一种情况,即一条主链叉开变成两条叉链,每条链沿着各自的方向延伸下去... 查看详情

stm32cubemx|42-使用dma2d加速显存数据传输(代码片段)

...在上一篇文章中讲述了如何配置LTDC驱动RGB屏幕:STM32CubeMX|41-使用LTDC驱动TFT-LCD屏幕(RGB屏)。本节中我们接着上一节的实验,讲述如何使用DMA2D实现打点、画线、填充等函数,只需要单层全屏即可,修改LTDC... 查看详情

安装stm32cubemx,stm32串口通信(代码片段)

...通信波特率数据位停止位奇偶校验2.RS-232标准二.安装STM32CubeMX,搭建STM32的开发环境1.安装jdk2.安装STM32CubeMX3.安装固件库 三.LED流水灯1.新建工程2.main.c3.实验效果四.USART串口通讯程序1.新建工程2.汇编代码3.烧录五.用keil观察时... 查看详情

stm32cubemx(04)串口中断实验(代码片段)

文章目录前言一、STM32CubeMX配置1.1.芯片选择1.2.配置SYS,RCC1.3.配置时钟树1.4.工程文件配置二、串口配置2.1.STM32CubeMX配置2.2.USART中断2.3.USART1引脚2.4.生成代码三、添加代码3.1.添加回调函数3.2main函数中初始化3.3while中编写代码4.... 查看详情

使用stm32cubemx创建freertos项目(代码片段)

使用STM32CubeMX创建FreeRTOS项目介绍STM32CubeMXFreeRTOS使用流程后续介绍STM32CubeMXSTM32CubeMX是被广泛使用的。它集成了芯片选型、引脚分配和功能配置,中间件配置,时钟配置,初始代码和项目的功能。FreeRTOSFreeRTOS是与世界... 查看详情

使用stm32cubemx创建freertos项目(代码片段)

使用STM32CubeMX创建FreeRTOS项目介绍STM32CubeMXFreeRTOS使用流程后续介绍STM32CubeMXSTM32CubeMX是被广泛使用的。它集成了芯片选型、引脚分配和功能配置,中间件配置,时钟配置,初始代码和项目的功能。FreeRTOSFreeRTOS是与世界... 查看详情