Conmajia

Stop stealing sheep!

导航

< 20253 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

统计

字符型液晶屏模拟控件En

A replica CLCD module control.
Initiated on May 5, 2012
Updated on Feb 21, 2017

Copyright 2012-2017 Conmajia

Nobi's LCM Display

Simple Demo

Here is a demo screenplay of the LCM control. Just in case you understand what I'm talking 'bout.

Basic Background

Character liquid crystal display module (CLCD, or simply LCD/LCM) module is one of the display devices well used for electronic equipments.

Panel Organization

An LCM panel that displays alpha-numeric characters is controlled by its core controller chip like Hitachi's HD44780 or HD44100. Panels are organized in general as shown below.

Inside The Controller

Two things among all the hardware details that you should pay attention are the DDRAM and the CGRAM/CGROM.

DDRAM

DDRAM (display data RAM) is an 80-byte buffer which can hold up to 40 columns by 2 rows of display data. You change a DDRAM byte, you change that character on the screen.

CGRAM/CGROM

Character generator is formed by 2 parts: the CGRAM and the CGROM. With the character generator you can draw custom characters such as symbols, icons and simple Chinese characters.

Implementation

The LCD control is a standard WinForm control derived from the UserControl class.

[ToolboxBitmap("Lcd\\lcd_logo.bmp")]
public partial class DotMatrixLcd : UserControl

With a 2-D array stores all characters to display.

DotMatrixCharacter[][] characters;

A DotMatrixCharacter represents the data of a character to display. I made this class a Control so that it can do much more than storing data.

public class DotMatrixCharacter : Control
public byte Ddram
public byte[] Cgram
public char Character

Generate Character

A generator class is designed to return raw character data for the control.

public sealed class CharacterGenerator {
  /// Get character data from DDRAM by address.
  public static byte[] GetDdram(byte address) {
    return charset[address];
  }
  /// Get character data from DDRAM to match the given character.
  public static byte[] GetDdram(char character) {
    return charset[(byte) character];
  }
  // 8 cgram chars
  static byte[][] cgram = new byte[8][];
  // for dummy
  static byte[] emptyChar = {
    0x00,
    0x00,
    0x00,
    0x00,
    0x00,
    0x00,
    0x00,
    0x00
  };
  /// Store character data in CGRAM registers by index.
  public static void SetCgram(byte[] data, int index) {
    if (data == null || data.Length != 8) return;
    if (index < 0 || index > 7) return;
    cgram[index] = data;
  }
  /// Get CGRAM character data by index.
  public static byte[] GetCgram(int index) {
    if (index < 0 || index > 7) return emptyChar;
    return cgram[index];
  }
  // 256x8 bytes (1024 bytes) characters
  static readonly byte[][] charset = {
      // 0000 0000
      new byte[] {
        0x00,
        0x00,
        0x00,
        0x00,
        0x00,
        0x00,
        0x00,
        0x00
      },
      // 0000 0001
      new byte[] {
        0x00,
        0x00,
        0x00,
        0x00,
        0x00,
        0x00,
        0x00,
        0x00
      },
      // ...

Now all the data is prepared.

Paint A Character

The characters renderer is inside the DotMatrixCharacter control.

void drawBlocks(Graphics g) {
  byte[] charData;
  // check source of char to display for CGRAM support
  switch (charSource) {
    case DisplaySource.CGRAM:
      if (cgramData == null || cgramData.Length != DOT_ROWS)
        // invalid data, draw empty
        // all 0x00
        charData = new byte[DOT_ROWS];
      else charData = cgramData;
      break;
    case DisplaySource.DDRAM:
    default:
      charData = CharacterGenerator.GetDdram(ddramAddress);
      break;
  }
  // ready to draw
  byte mask;
  for (int i = 0; i < DOT_ROWS; i++) {
    // if use mask = 0x01 (right to left)
    // the output will be vertical mirrored
    mask = 0x01 << (DOT_COLS - 1);
    for (int j = 0; j < DOT_COLS; j++) {
      if ((mask & charData[i]) == 0) {
        // 0 - empty
        if (circleBlock) g.FillEllipse(inactiveBrush, j * (blockSize.Width + spacing), i * (blockSize.Height + spacing), blockSize.Width, blockSize.Height);
        else g.FillRectangle(inactiveBrush, j * (blockSize.Width + spacing), i * (blockSize.Height + spacing), blockSize.Width, blockSize.Height);
      } else {
        // 1 - fill
        if (circleBlock) g.FillEllipse(activeBrush, j * (blockSize.Width + spacing), i * (blockSize.Height + spacing), blockSize.Width, blockSize.Height);
        else g.FillRectangle(activeBrush, j * (blockSize.Width + spacing), i * (blockSize.Height + spacing), blockSize.Width, blockSize.Height);
      }
      // next bit
      //mask <<= 1;
      // msb to lsb
      mask >>= 1;
    }
  }
}

With the built-in renderer, the final LCD module control can obtain the extensibility to switch between different display contents like character displays, graphic dot matrix display, etc.

Full Project Source & Demo Executive

You can download them here:
Project source code: → Click to download
Demo executive file: → Click to download

References

  1. How to Use Character LCD Module, elm-chan.org

posted on2017-02-21   Conmajia  阅读(688)  评论(0编辑  收藏  举报

编辑推荐:
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
阅读排行:
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?
点击右上角即可分享
微信分享提示