วันพฤหัสบดีที่ 7 พฤศจิกายน พ.ศ. 2556

การสร้างอักษรที่ LCD

การสร้างอักษรที่ LCD 
โดย สมชาย เบียนสูงเนิน
               เราสามารถสร้างตัวอักษรหรือรูปแบบเก็บไว้ในโมดูลของ LCD ได้ 8 รูปแบบ  โดยส่งเก็บไว้ที่หน่วยความจำ CGRAM          เรียกแสดงผลผ่าน Address ของ DDRAM ที่ 0x00 ถึง 0x07 การบันทึกรูปแบบลงใน CGRAM จะต้องเริ่มจากการสร้างรหัสของรูปแบบ  โดยที่ 1 รูปแบบ จะต้องใช้ตัวแปรในการเก็บรหัสในแต่ละแถวจำนวน 8 ตัวแปร ส่วนใหญ่ต้องกำหนดเป็นแบบอะเรย์  หากต้องการสร้างตัว ก็จะต้องกำหนดค่าของตัวแปรเป็น  char pattern1[8] ={0x01,0x01,0x1F,0x01,0x1F,0x11,0x19,0x00}  ข้อมูลตัวสุดท้าย 0x00 เป็นแถวของการแสดง Cursor ไม่สามารถสร้างรูปแบบที่แถวนี้ได้จึงกำหนดค่าเป็น 0x00 โดยการกำหนดค่ารูปแบบขึ้นอยู่กับจำนวน Dot ของ LCD ด้วย ในรูปที่ 1 เป็นขนาด 5x7 dot


รูปที่ 1 รหัสสำหรับสร้างรูปแบบเป็นตัว

เมื่อได้รหัสของรูปแบบที่สร้างแล้ว แล้วขั้นต่อไปก็จะทำการบันทึกรหัสไปยังหน่วยความจำของ CGRAM โดยต้องส่งคำสั่งเพื่อระบุตำแหน่งที่จะจัดเก็บรหัสของ CGRAM ว่าต้องการเก็บที่ตำแหน่งใด โดยมีให้เลือก 8 ตำแหน่ง โดยรหัสคำสั่งรวมกับรหัสตำแหน่งของ CGRAM ขนาด 8 bit แสดงได้ดังนี้

- รูปแบบที่ 1 ( แสดงผลเมื่อส่งรหัส 0x00 ไปที่ DDRAM) กำหนดตำแหน่งเริ่มของ CGRAM ที่ 0x40  
- รูปแบบที่ 2 ( แสดงผลเมื่อส่งรหัส 0x01 ไปที่ DDRAM) กำหนดตำแหน่งเริ่มของ CGRAM ที่ 0x48  
- รูปแบบที่ 3 ( แสดงผลเมื่อส่งรหัส 0x02 ไปที่ DDRAM) กำหนดตำแหน่งเริ่มของ CGRAM ที่ 0x50  
- รูปแบบที่ 4 ( แสดงผลเมื่อส่งรหัส 0x03 ไปที่ DDRAM) กำหนดตำแหน่งเริ่มของ CGRAM ที่ 0x58  
- รูปแบบที่ 5 ( แสดงผลเมื่อส่งรหัส 0x04 ไปที่ DDRAM) กำหนดตำแหน่งเริ่มของ CGRAM ที่ 0x60  
- รูปแบบที่ 6 ( แสดงผลเมื่อส่งรหัส 0x05 ไปที่ DDRAM) กำหนดตำแหน่งเริ่มของ CGRAM ที่ 0x68  
- รูปแบบที่ 7 ( แสดงผลเมื่อส่งรหัส 0x06 ไปที่ DDRAM) กำหนดตำแหน่งเริ่มของ CGRAM ที่ 0x70  
- รูปแบบที่ 8 ( แสดงผลเมื่อส่งรหัส 0x07 ไปที่ DDRAM) กำหนดตำแหน่งเริ่มของ CGRAM ที่ 0x78  

            ถ้าต้องการให้ แสดงเมื่อส่งรหัส 0x02 ก็ต้อง ส่งรหัสคำสั่ง 0x50 ไปให้หน่วยประมวลผลของ LCD ทราบ จากนั้นก็ส่งรหัสข้อมูลของตัว ทั้ง 8 แถวตามไป แสดงการเขียนคำสั่ง โดยอ้างอิงชื่อฟังก์ชันที่ใช้ในการส่งแสดงผลที่ LCD ในตัวอย่างโปรแกรมที่ 1
         char patternSO[8]={0x01,0x01,0x1F,0x01,0x1F,0x11,0x19,0x00};//
         LCD_RS=0;                                // ส่งสัญญาณว่าเป็นคำสั่ง
         lcd_sendbyte(0x50);                     // ส่งคำสั่งเพื่อระบุตำแหน่งที่จะจัดเก็บรหัสของ CGRAM รหัส 0x50  แสดงผลเมื่อส่งรหัส 0x02
         LCD_RS=1; ;                              // ส่งสัญญาณว่าเป็นข้อมูล
         lcd_sendbyte(patternSO[0]);                 // ส่งข้อมูลที่เป็นรหัสรูปแบบแถวที่ 1
         lcd_sendbyte(patternSO[1]);                 // ส่งข้อมูลที่เป็นรหัสรูปแบบแถวที่ 2
            lcd_sendbyte(patternSO[2]);                  // ส่งข้อมูลที่เป็นรหัสรูปแบบแถวที่ 3
            lcd_sendbyte(patternSO[3]);                  // ส่งข้อมูลที่เป็นรหัสรูปแบบแถวที่ 4
            lcd_sendbyte(patternSO[4]);                  // ส่งข้อมูลที่เป็นรหัสรูปแบบแถวที่ 5
            lcd_sendbyte(patternSO[5]);                  // ส่งข้อมูลที่เป็นรหัสรูปแบบแถวที่ 6
            lcd_sendbyte(patternSO[6]);                  // ส่งข้อมูลที่เป็นรหัสรูปแบบแถวที่ 7
            lcd_sendbyte(patternSO[7]);                  // ส่งข้อมูลที่เป็นรหัสรูปแบบแถวที่ 8
   
หรืออาจใช้ for() ช่วย ในการส่งข้อมูลทั้ง 8 แถว เพราะประกาศตัวแปรแบบอะเรย์อยู่แล้ว แสดงได้ดังนี้
                for(i=0;i<8;i++)
                {              lcd_sendbyte(patternSO [i]);   // ส่งข้อมูลที่เป็นรหัสรูปแบบตัวที่ i
                }
               
สุดท้ายการเรียกให้แสดงผลก็ส่งรหัสที่เป็นตัวแทนของรูปแบบไปที่ LCD เช่นเดียวกับอักษรอื่นๆที่ถูกบันทึกใน CGROM เช่น ต้องการให้แสดงอักษร Z ก็ต้องส่งรหัส 0x5C ดังนั้นรหัสที่เป็นตัวแทนรูปแบบตัวอักษร  ก็คือ 0x02 นั้นเอง เช่น lcd_sendbyte(0x02)

ตัวอย่างโปรแกรม ใช้ไมโครคอนโทรลเลอร์ PIC16F887
โจทย์  ต่อวงจรและเขียนโปรแกรมเพื่อให้ LCD ขนาด 16x2 แสดงข้อความ ไฟฟ้า 2555  ที่บรรทัดแรก เริ่มตำแหน่งที่ 2 และ ข้อความ Electrical 2012บรรทัดสอง เริ่มตำแหน่งที่ 1
            ตัวอักษรที่ไม่มีในหน่วยความจำของ LCD คือคำว่า ไฟฟ้า ดังนั้นจะต้องสร้างตัวอักษรเอง 4 รูปแบบ โดยจะเก็บที่ในตำแหน่ง  0x00 ถึง 0x03



รูปที่ 2 การแสดงผลของรูปแบบที่สร้างขึ้นในหน่วยความจำของ LCD


โปรแกรม  แสดงรูปแบบที่สร้างขึ้น 
#include <pic.h>                                          // Include header file for MCU
#include "LCD16F887.h"                            // Include Library for LCD display

#define _XTAL_FREQ       20000000 // Define Frequency 20.0 MHz for __delay_ms
__CONFIG(FOSC_HS & WDTE_OFF & LVP_OFF);   

//----------------------------------------------------------Main Program---------------------------------------------------//
void main(void)
{      char PattI[8]={0x16,0x0A,0x02,0x02,0x02,0x02,0x03,0x00};     //
        char PattPho[8]={0x01,0x01,0x19,0x09,0x11,0x15,0x1B,0x00};            //
        char PattPho2[8]={0x0A,0x05,0x11,0x09,0x11,0x15,0x1B,0x00};             // ฟ้
        char PattR[8] ={0x00,0x00,0x06,0x09,0x01,0x01,0x01,0x00};    //
        int i;

           

        lcd_init();                                                    //Call initial Function of  LCD library
       
        LCD_RS=0;  lcd_sendbyte(0x40);             // Send Conmand Set Pattern Start at 0x00
        LCD_RS=1;                                               // Send Data of Pattern
        for(i=0;i<8;i++)
        {      lcd_sendbyte(PattI[i]);                        //
        }
      // ในกรณีที่บันทึกข้อมูลในตำแหน่งที่ต่อเนื่องกันไม่จำเป็นต้องส่งคำสั่งระบุตำแหน่งใหม่
        // เพราะตำแหน่งในหน่วยความจำของ LCD จะเลื่อนให้ครั้งละ 1 ตำแหน่ง แบบอัตโนมัติ 
        // แต่จำเป็นต้องส่งข้อมูลให้ครบ 8 ครั้ง สำหรับ 1 รูปแบบ
        for(i=0;i<8;i++)
        {      lcd_sendbyte(PattPho[i]);                  //
        }

        for(i=0;i<8;i++)
        {      lcd_sendbyte(PattPho2[i]);                // ฟ้
        }

        for(i=0;i<8;i++)
        {      lcd_sendbyte(PattR [i]);                     //
        }
       
        LCD_RS=0;   lcd_sendbyte(0x81);            // Send Conmand Line 1 Location 2
        LCD_RS=1;                                              // Send Data
        lcd_sendbyte(0x00);                                   //
      // ในกรณีที่แสดงผลในตำแหน่งที่ต่อเนื่องกันไม่จำเป็นต้องส่งคำสั่งระบุตำแหน่งใหม่
        // เพราะตำแหน่งในหน่วยความจำของ LCD จะเลื่อนให้ครั้งละ 1 ตำแหน่ง แบบอัตโนมัติ
        lcd_sendbyte(0x01);                                  //
        lcd_sendbyte(0x02);                                  // ฟ้
        lcd_sendbyte(0x03);                                  //

        lcd_puts (0x85, " 2555");                      //Send text 2555 start address 0x85 (6nd address of Line 1)
        lcd_puts (0xC0, "Electrical 2012");       //Send text Electrical 2012 start address 0xC0 of Line 2
        while(1);