基於STM32 加入LCM 16*2 display (HD44780)

最近弄一個產品, 處理器是ARM STM32f10,
其中計畫加入一個簡單的顯示螢幕, 可以讓使用者知道目前系統的資訊
於是找了一個16行*2列的螢幕,
裡面使用到的是HD44780的chip吧, 大概長這樣

這個網站有基本的介紹與sample code (C語言)
** http://www.eeherald.com/section/design-guide/sample_lcd_c_programs.html

這個網站也有程式可看, 但不幸的是他寫的似乎是給8051那類的IC使用
但好處是可以將這些sample code互相比較, 找出同異
** http://www.microcontroller-project.com/alphanumeric-keypad-with-16×2-lcd.html

推薦!! 這個網址的說明是最清楚的
程式碼也是寫最棒的(for 4-bits), 還有影片分享
但有個小小錯誤需要改, 自己改吧~
** http://myactivities-mazen.blogspot.tw/2013/09/controlling-216-lcd-with-stm32f4.html

這篇寫得很詳細, 每個步驟都說明
可以study一下~
** http://web.alfredstate.edu/weimandn/lcd/lcd_initialization/lcd_initialization_index.html

以下分享從Mazen得到,
修改成 for 8-bits的版本
Thanks Mazen!

lcd_hd44780.c

#include "stm32f10x.h"
#include "usb_box.h"

#include "lcd_hd44780.h"
#include "stm32f10x_gpio.h"
#include 
#include 
#include 
//#include "stm32f4_discovery.h"
 
GPIO_InitTypeDef GPIO_InitStructure;


//-----------------------------------------------------------------------------
void lcd_writenibble(unsigned char nibbleToWrite)
{
  GPIO_WriteBit(LCD_GPIO, LCD_EN, Bit_SET);
  GPIO_WriteBit(LCD_GPIO, LCD_D0,(BitAction)(nibbleToWrite & 0x001));
  GPIO_WriteBit(LCD_GPIO, LCD_D1,(BitAction)(nibbleToWrite & 0x002));
  GPIO_WriteBit(LCD_GPIO, LCD_D2,(BitAction)(nibbleToWrite & 0x004));
  GPIO_WriteBit(LCD_GPIO, LCD_D3,(BitAction)(nibbleToWrite & 0x008));  
  GPIO_WriteBit(LCD_GPIO, LCD_D4,(BitAction)(nibbleToWrite & 0x010));
  GPIO_WriteBit(LCD_GPIO, LCD_D5,(BitAction)(nibbleToWrite & 0x020));
  GPIO_WriteBit(LCD_GPIO, LCD_D6,(BitAction)(nibbleToWrite & 0x040));
  GPIO_WriteBit(LCD_GPIO, LCD_D7,(BitAction)(nibbleToWrite & 0x080));
  udelay(200);
  GPIO_WriteBit(LCD_GPIO, LCD_EN, Bit_RESET);
}
 
 
//-----------------------------------------------------------------------------
unsigned char LCD_ReadNibble(void)
{
  unsigned char tmp = 0;
  GPIO_WriteBit(LCD_GPIO, LCD_EN, Bit_SET);
  tmp |= (GPIO_ReadInputDataBit(LCD_GPIO, LCD_D0) << 0);
  tmp |= (GPIO_ReadInputDataBit(LCD_GPIO, LCD_D1) << 1);
  tmp |= (GPIO_ReadInputDataBit(LCD_GPIO, LCD_D2) << 2);
  tmp |= (GPIO_ReadInputDataBit(LCD_GPIO, LCD_D3) << 3);
  tmp |= (GPIO_ReadInputDataBit(LCD_GPIO, LCD_D4) << 4);
  tmp |= (GPIO_ReadInputDataBit(LCD_GPIO, LCD_D5) << 5);
  tmp |= (GPIO_ReadInputDataBit(LCD_GPIO, LCD_D6) << 6);
  tmp |= (GPIO_ReadInputDataBit(LCD_GPIO, LCD_D7) << 7);  
  GPIO_WriteBit(LCD_GPIO, LCD_EN, Bit_RESET);

  return tmp;
}
 
 
//-----------------------------------------------------------------------------
unsigned char LCD_ReadStatus(void)
{
 unsigned char status = 0;

 GPIO_InitStructure.GPIO_Pin   =  LCD_D0 | LCD_D1 | LCD_D2 | LCD_D3 |LCD_D4 | LCD_D5 | LCD_D6 | LCD_D7;
 GPIO_InitStructure.GPIO_Mode  =  GPIO_Mode_AIN;
 GPIO_Init(LCD_GPIO, &GPIO_InitStructure);

 GPIO_WriteBit(LCD_GPIO, LCD_RW, Bit_SET);
 GPIO_WriteBit(LCD_GPIO, LCD_RS, Bit_RESET);

 status = LCD_ReadNibble();

 GPIO_InitStructure.GPIO_Pin   =  LCD_D0 | LCD_D1 | LCD_D2 | LCD_D3 |LCD_D4 | LCD_D5 | LCD_D6 | LCD_D7;
 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
 GPIO_Init(LCD_GPIO, &GPIO_InitStructure);

 return status;
}
 
//-----------------------------------------------------------------------------
unsigned char LCD_ReadOutNibble(void)
{
  unsigned char tmp = 0;
  GPIO_WriteBit(LCD_GPIO, LCD_EN, Bit_SET);
  tmp |= (GPIO_ReadOutputDataBit(LCD_GPIO, LCD_D0) << 0);
  tmp |= (GPIO_ReadOutputDataBit(LCD_GPIO, LCD_D1) << 1);
  tmp |= (GPIO_ReadOutputDataBit(LCD_GPIO, LCD_D2) << 2);
  tmp |= (GPIO_ReadOutputDataBit(LCD_GPIO, LCD_D3) << 3);
  tmp |= (GPIO_ReadOutputDataBit(LCD_GPIO, LCD_D4) << 4);
  tmp |= (GPIO_ReadOutputDataBit(LCD_GPIO, LCD_D5) << 5);
  tmp |= (GPIO_ReadOutputDataBit(LCD_GPIO, LCD_D6) << 6);
  tmp |= (GPIO_ReadOutputDataBit(LCD_GPIO, LCD_D7) << 7);  
  GPIO_WriteBit(LCD_GPIO, LCD_EN, Bit_RESET);
  return tmp;
}

//-----------------------------------------------------------------------------
unsigned char LCD_ReadOutStatus(void)
{
  unsigned char status = 0;

    GPIO_WriteBit(LCD_GPIO, LCD_RW, Bit_SET);
    GPIO_WriteBit(LCD_GPIO, LCD_RS, Bit_RESET);

 status = LCD_ReadOutNibble();

  return status;
}
 
//------------------------------------------------------------------------------
// Function Name : lcd_writedata
// Description : Send Data Select routine(RS=1 & RW=0)
//------------------------------------------------------------------------------
void lcd_writedata(unsigned char dataToWrite)
{
  GPIO_WriteBit(LCD_GPIO, LCD_RW, Bit_RESET);
  GPIO_WriteBit(LCD_GPIO, LCD_RS, Bit_SET);
  lcd_writenibble(dataToWrite);

  //LCD_ReadOutStatus();
  while(LCD_ReadStatus() & 0x80);
}
 
 
//-----------------------------------------------------------------------------
void lcd_writecommand(unsigned char commandToWrite)
{
  GPIO_WriteBit(LCD_GPIO, LCD_RW | LCD_RS, Bit_RESET);
  lcd_writenibble(commandToWrite);

  //LCD_ReadOutStatus();
  while(LCD_ReadStatus() & 0x80);
}
 
 
//-----------------------------------------------------------------------------
void lcd_str(unsigned char * text)
{
  while(*text)
    lcd_writedata(*text++);
}
 
 
//-----------------------------------------------------------------------------
void lcd_locate(unsigned char x, unsigned char y)
{
  lcd_writecommand(HD44780_DDRAM_SET | (x + (0x40 * y)));
}
 
 
//-----------------------------------------------------------------------------
void lcd_strxy(unsigned char * text, unsigned char x, unsigned char y)
{
  lcd_locate(x,y);
  while(*text)
    lcd_writedata(*text++);
}
 
 
//-----------------------------------------------------------------------------
void lcd_writebinary(unsigned int var, unsigned char bitCount)
{
  signed char i;
 
  for(i = (bitCount - 1); i >= 0; i--)
     {
     lcd_writedata((var & (1 << i))?'1':'0');
     }
}
 
 
//-----------------------------------------------------------------------------
void LCD_ShiftLeft(void)
{
  lcd_writecommand(HD44780_DISPLAY_CURSOR_SHIFT | HD44780_SHIFT_LEFT | HD44780_SHIFT_DISPLAY);
}
 
 
//-----------------------------------------------------------------------------
void LCD_ShiftRight(void)
{
  lcd_writecommand(HD44780_DISPLAY_CURSOR_SHIFT | HD44780_SHIFT_RIGHT | HD44780_SHIFT_DISPLAY);
}
 
 
//-----------------------------------------------------------------------------
void lcd_init(void)
{
 volatile unsigned char i = 0;
 volatile unsigned int delayCnt = 0;
 RCC_APB2PeriphClockCmd(LCD_CLK_LINE, ENABLE);

 GPIO_InitStructure.GPIO_Pin = LCD_D0|LCD_D1|LCD_D2|LCD_D3|LCD_D4|LCD_D5|LCD_D6|LCD_D7|LCD_RS|LCD_RW|LCD_EN;
 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
 GPIO_Init(LCD_GPIO, &GPIO_InitStructure);

 GPIO_WriteBit(LCD_GPIO, LCD_RW | LCD_RS | LCD_EN, Bit_SET);
 udelay(200);
 GPIO_WriteBit(LCD_GPIO, LCD_RW | LCD_RS | LCD_EN, Bit_RESET);
 udelay(200);

 /* Initial by instruction */
 lcd_writecommand(0x030);
 udelay(500);
 lcd_writecommand(0x030);
 udelay(200);
 lcd_writecommand(0x030);
 udelay(200);

 lcd_writecommand(HD44780_FUNCTION_SET |
                HD44780_FONT5x7 |
                HD44780_TWO_LINE |
                HD44780_8_BIT); //0x38
 udelay(200);

 lcd_writecommand(HD44780_DISPLAY_ONOFF |
                HD44780_DISPLAY_OFF); //0x08
 udelay(200);

 lcd_writecommand(HD44780_CLEAR); //0x01
 udelay(200);

 lcd_writecommand(HD44780_ENTRY_MODE |
                HD44780_EM_SHIFT_CURSOR |
                HD44780_EM_INCREMENT);//0x06
 udelay(200);

 lcd_writecommand(HD44780_DISPLAY_ONOFF |
                HD44780_DISPLAY_ON |
                HD44780_CURSOR_ON |
                HD44780_CURSOR_NOBLINK);//0x0E
 udelay(200);

}
 
 
//-----------------------------------------------------------------------------
void lcd_addchar (unsigned char chrNum, unsigned char n, const unsigned char *p)
{
        lcd_writecommand(HD44780_CGRAM_SET | chrNum * 8);
        n *= 8;
        do
         lcd_writedata(*p++);
        while (--n);
}
 
 
//-----------------------------------------------------------------------------
void lcd_cls(void){
        lcd_writecommand(HD44780_CLEAR);
}
 
 
 
unsigned char* intToStr(int n){
 int i = 0;
 int j = 0;
 char *tmp = (char*)malloc(sizeof(char));
    unsigned char *ret = (unsigned char*)malloc(12);

 if(n<0 || n>9){
  *tmp = n%10+48;
  n-=n%10;
  n/=10;
  tmp++;
  i++;
 }
 
 *tmp = n+48;
 i++;
 while(i--){
   ret[j++] = *tmp--;
 }
 return ret;
}

void lcd_int(int a){
  unsigned short ch,first; //you need this to display 0 if there was any char
 
    //Get first char
    ch = a/10000;
    if(ch){
     lcd_writedata(48+ch);
     first = 1;
    }
 
    //Get second char
    ch = (a/1000)%10;
    if(ch || first){
     lcd_writedata(48+ch);
     first = 1;
    }
 
    //Get third char
    ch = (a/100)%10;
    if(ch || first){
     lcd_writedata(48+ch);
     first = 1;
    }
 
    //Get fourth char
    ch = (a/10)%10;
    if(ch || first){
     lcd_writedata(48+ch);
     //first = 1;                   //q
    }
 
    //Get fifth char
    ch = a%10;
    //if(ch || first)   //you dont need to check las one if ch is 0 then just display it, unless you dont want to then uncomment this line ("//q" line too)
     lcd_writedata(48+ch);
       // lcd_str(intToStr(n));
}
 
void lcd_intxy(int n, unsigned char x, unsigned char y){
        lcd_locate(x,y);
        lcd_int(n);
}


lcd_hd44780.h

//******************************************************************************
//    THE SOFTWARE INCLUDED IN THIS FILE IS FOR GUIDANCE ONLY.
//    AUTHOR SHALL NOT BE HELD LIABLE FOR ANY DIRECT, INDIRECT
//    OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
//    FROM USE OF THIS SOFTWARE.
//******************************************************************************
 
//##############################################################################
// lcd_hd44780.h
//##############################################################################
 
//****************************************************************************//
//#include "main.h"
 
 
#define LCD_GPIO GPIOB
#define LCD_CLK_LINE RCC_APB2Periph_GPIOB
 
#define LCD_D0 GPIO_Pin_0
#define LCD_D1 GPIO_Pin_1
#define LCD_D2 GPIO_Pin_5
#define LCD_D3 GPIO_Pin_8
#define LCD_D4 GPIO_Pin_9
#define LCD_D5 GPIO_Pin_10
#define LCD_D6 GPIO_Pin_11
#define LCD_D7 GPIO_Pin_12
 
#define LCD_RS GPIO_Pin_13
#define LCD_RW GPIO_Pin_14
#define LCD_EN GPIO_Pin_15
//******************************************************************************//
 
 
#define HD44780_CLEAR                                          0x01
 
#define HD44780_HOME                                           0x02
 
#define HD44780_ENTRY_MODE     0x04
        #define HD44780_EM_SHIFT_CURSOR    0x00
        #define HD44780_EM_SHIFT_DISPLAY   0x01
        #define HD44780_EM_DECREMENT    0x00
        #define HD44780_EM_INCREMENT    0x02
 
#define HD44780_DISPLAY_ONOFF    0x08
        #define HD44780_DISPLAY_OFF     0x00
        #define HD44780_DISPLAY_ON                  0x04
        #define HD44780_CURSOR_OFF                  0x00
        #define HD44780_CURSOR_ON                   0x02
        #define HD44780_CURSOR_NOBLINK    0x00
        #define HD44780_CURSOR_BLINK    0x01
 
#define HD44780_DISPLAY_CURSOR_SHIFT 0x10
        #define HD44780_SHIFT_CURSOR               0
        #define HD44780_SHIFT_DISPLAY              8
        #define HD44780_SHIFT_LEFT                         0
        #define HD44780_SHIFT_RIGHT                  4
 
#define HD44780_FUNCTION_SET    0x20
        #define HD44780_FONT5x7      0x00
        #define HD44780_FONT5x10     0x04
        #define HD44780_ONE_LINE     0x00
        #define HD44780_TWO_LINE     0x08
        #define HD44780_4_BIT      0x00
        #define HD44780_8_BIT      0x10
 
#define HD44780_CGRAM_SET                                    0x40
 
#define HD44780_DDRAM_SET                                    0x80
 
//##############################################################
void lcd_init(void);
void lcd_cls(void);
void lcd_str(unsigned char * text);
void lcd_strxy(unsigned char * text, unsigned char x, unsigned char y);
void lcd_locate(unsigned char x, unsigned char y);
void lcd_int(int n);
void lcd_intxy(int n, unsigned char x, unsigned char y);
 
//###############################################################
 
void lcd_writedata(unsigned char dataToWrite);
void lcd_writecommand(unsigned char commandToWrite);
void lcd_writebinary(unsigned int var, unsigned char bitCount);
void lcd_addchar (unsigned char chrNum, unsigned char n, const unsigned char *p);

main.c

lcd_init();
 
        while (1)
          {
 
                  lcd_locate(1,0);
                  lcd_str("Mazen");
                  lcd_locate(7,0);
                  lcd_str("A.");
                  lcd_locate(0,1);
                  lcd_str("-3125");
 
          }

發表迴響