2014/03/18

基於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");           }

沒有留言:

張貼留言