MSP430 HD44780 seriell ansteuern

Im folgenden Beispiel-Programm wird ein LCD mit HD44780-Controller seriell angesteuert (Quick’n’Dirty). Realisiert wird die Ansteuerung per Schieberegister und der USI-Schnitstelle des MSPs (siehe “Daten per USI (SPI) an Schieberegister senden”). Ziel war es, mit so wenigen Ports wie möglich, ein HD44780-LCD (4bit-Interface) anzusteuern. Insgesamt benötigte Ports: 3.

Auf eine detaillierte Erklärung zum HD44780-Controller wird in diesem Beispiel nicht eingegangen. Das Display wird im 4bit-Modus betrieben. Es wird also immer High- und Low-Teil hintereinander übertragen. Es müssen also ingesamt pro Befehl 4*7bits an das Schieberegister übertragen werden:

1) High-Teil + Enable(High)
2) High-Teil + Enable(Low)
3) Low-Teil + Enable(High)
4) Low-Teil + Enable(Low)

Schaltplan

lcd_serial

Video

C-Programm

FILE: main.c

  1. /*************************************************
  2.  *     ___       _             _    
  3.  *    |   |_ _ _| |___ ___   _| |___
  4.  *    | | |_'_| . | -_|  _|_| . | -_|
  5.  *    |___|_,_|___|___|___|_|___|___|
  6.  *
  7.  * FILE:     main.c
  8.  * Author:   declis (xdec.de)
  9.  ************************************************/
  10.  
  11. #include <msp430g2231.h>
  12. #include "def_lcd.h"
  13.  
  14. void main(void)
  15. {
  16.     const char string_site[]={"www.xdec.de"};
  17.     volatile signed char rechts=0,links=39;
  18.     WDTCTL=WDTPW+WDTHOLD;
  19.     BCSCTL1=CALBC1_1MHZ;
  20.     DCOCTL=CALDCO_1MHZ;
  21.  
  22.     init_USI();                         // Init. USI
  23.     init_lcd();                         // Init. LCD
  24.  
  25.     //small display-animation
  26.     while(rechts<=14)
  27.     {
  28.         write_char(rechts,0,'>');
  29.         write_char(rechts++,1,'>');
  30.         write_char(links,0,'<');
  31.         write_char(links--,1,'<');
  32.         wait_ms(100);
  33.  
  34.         if(rechts==14)
  35.         {
  36.             write_string(14,0,string_site);
  37.             while(rechts!=20)
  38.             {
  39.                 write_char(rechts++,1,'>');
  40.                 write_char(links--,1,'<');
  41.                 wait_ms(100);
  42.             }
  43.         }
  44.     }
  45.  
  46.     while(rechts>=0)
  47.     {
  48.         write_char(rechts--,1,' ');
  49.         write_char(links++,1,' ');
  50.         wait_ms(100);
  51.     }
  52.  
  53.     rechts=13;
  54.     links=26;
  55.  
  56.     while(rechts>=0)
  57.     {
  58.         write_char(rechts--,0,' ');
  59.         write_char(links++,0,' ');
  60.         wait_ms(100);
  61.     }
  62.  
  63.     while(1);
  64. }
/*************************************************
 *     ___       _             _     
 *    |   |_ _ _| |___ ___   _| |___
 *    | | |_'_| . | -_|  _|_| . | -_|
 *    |___|_,_|___|___|___|_|___|___|
 *
 * FILE:     main.c
 * Author:   declis (xdec.de)
 ************************************************/

#include <msp430g2231.h>
#include "def_lcd.h"

void main(void)
{
    const char string_site[]={"www.xdec.de"};
    volatile signed char rechts=0,links=39;
    WDTCTL=WDTPW+WDTHOLD;
    BCSCTL1=CALBC1_1MHZ;
    DCOCTL=CALDCO_1MHZ;

    init_USI();                         // Init. USI
    init_lcd();                         // Init. LCD

    //small display-animation
    while(rechts<=14)
    {
        write_char(rechts,0,'>');
        write_char(rechts++,1,'>');
        write_char(links,0,'<');
        write_char(links--,1,'<');
        wait_ms(100);

        if(rechts==14)
        {
            write_string(14,0,string_site);
            while(rechts!=20)
            {
                write_char(rechts++,1,'>');
                write_char(links--,1,'<');
                wait_ms(100);
            }
        }
    }

    while(rechts>=0)
    {
        write_char(rechts--,1,' ');
        write_char(links++,1,' ');
        wait_ms(100);
    }

    rechts=13;
    links=26;

    while(rechts>=0)
    {
        write_char(rechts--,0,' ');
        write_char(links++,0,' ');
        wait_ms(100);
    }

    while(1);
}

FILE: lib_lcd.c

  1. ´/*************************************************
  2.  *     ___       _             _    
  3.  *    |   |_ _ _| |___ ___   _| |___
  4.  *    | | |_'_| . | -_|  _|_| . | -_|
  5.  *    |___|_,_|___|___|___|_|___|___|
  6.  *
  7.  * FILE:     lib_lcd.c
  8.  * Author:   declis (xdec.de)
  9.  ************************************************/
  10.  
  11. #include <msp430g2231.h>
  12. #include "def_lcd.h"
  13.  
  14. // send one character to display ; x=0...39 ; y=0,1
  15. void write_char(unsigned char x_pos,unsigned char y_pos,unsigned char character)
  16. {
  17.     set_cursor(x_pos,y_pos);            // set cursor to xy-position
  18.     set_instruction(1,character);
  19. }
  20.  
  21. // send a string to display ; x=0..39 ; y=0,1
  22. void write_string(unsigned char x_pos,unsigned char y_pos,const char *string)
  23. {
  24.     set_cursor(x_pos,y_pos);            // set cursor to xy-position
  25.     while(*string!=0)
  26.         set_instruction(1,*string++);
  27. }
  28.  
  29. // set cursor to xy-position ; x=0...39 ; y=0,1
  30. void set_cursor(unsigned char x_pos,unsigned char y_pos)
  31. {
  32.     if(y_pos)                           // second row + x_pos
  33.         set_instruction(0,second_row+x_pos);
  34.     else                                // first row + x_pos
  35.         set_instruction(0,first_row+x_pos);
  36. }
  37.  
  38. // 8bit-interface emulation for 4bit-interface (8bit into 2*4bit converter)
  39. // register_sel = 0,1 (0=instruction,1=data)
  40. // number = 8bit value
  41. void set_instruction(unsigned char register_sel,unsigned char number)
  42. {
  43.     volatile unsigned char high_part=0,low_part=0;
  44.  
  45.     high_part=(number>>4);            // transform 8bit into 2*4bit
  46.     low_part=(number&0x0F);
  47.  
  48.     if(register_sel)                // if register_sel=1 -> RS=high
  49.     {
  50.         high_part|=RS;
  51.         low_part|=RS;
  52.     }
  53.  
  54.     send_lcd(high_part);            // send high part
  55.     send_lcd(low_part);             // send low part
  56. }
  57.  
  58. void send_lcd(unsigned char value)
  59. {
  60.     volatile unsigned char run=0;
  61.  
  62.     value|=Enable;                  // enable=high
  63.  
  64.     while(run!=2)
  65.     {
  66.         if(run) value&=~Enable;     // 2nd run, enable=low
  67.         USISRL=value;               // USI 8bit shift register= = 7bit value
  68.         USICNT=7;                   // start transmission (7bit)
  69.         wait_us(100);
  70.         run++;
  71.     }
  72. }
  73.  
  74. void init_lcd(void)
  75. {
  76.     wait_ms(20);
  77.     send_lcd(_8bit_inter);
  78.     wait_ms(5);
  79.     send_lcd(_8bit_inter);
  80.     wait_ms(2);
  81.     send_lcd(_8bit_inter);
  82.     send_lcd(2);                // change interface to 4bit
  83.  
  84.     set_instruction(0,40);      // 5x8, 2-rows
  85.     set_instruction(0,8);       // display off
  86.     set_instruction(0,1);       // clear display
  87.     set_instruction(0,6);       // shift cursor to the right, no display shift
  88.     set_instruction(0,12);      // display on
  89. }
  90.  
  91. void init_USI(void)
  92. {
  93.     // P1.7 (strobe) -> output
  94.     P1DIR|=strobe;
  95.     P1OUT&=~strobe;
  96.     // SPI Master, SI enabled, CLK enabled, LSB first, output enabled, USI in reset state
  97.     USICTL0|=USIPE6+USIPE5+USIMST+USILSB+USIOE+USISWRST;
  98.     // USI counter interrupt enabled,
  99.     // data is captured on the first CLK edge and changed on the following edge
  100.     USICTL1|=USICKPH+USIIE;
  101.     // CLK-Source=SMCLK=1MHz
  102.     USICKCTL|=USISSEL_2;
  103.     // USI released for operation
  104.     USICTL0&=~USISWRST;
  105.     // clear USIIFG
  106.     USICTL1&=~USIIFG;
  107.     // global interrupt enabled
  108.     _EINT();
  109. }
  110.  
  111. #pragma INTERRUPT (USI)
  112. #pragma vector=USI_VECTOR
  113. void USI(void)
  114. {
  115.     P1OUT|=strobe;                  // strobe-pulse
  116.     P1OUT&=~strobe;
  117.     USICTL1&=~USIIFG;               // clear USIIFG
  118. }
  119.  
  120. void wait_ms(unsigned int m_sec)
  121. {
  122.     while(m_sec--)
  123.         __delay_cycles(1000);
  124. }
  125.  
  126. void wait_us(unsigned int u_sec)
  127. {
  128.     while(u_sec--)
  129.         __delay_cycles(1);
  130. }
´/*************************************************
 *     ___       _             _     
 *    |   |_ _ _| |___ ___   _| |___
 *    | | |_'_| . | -_|  _|_| . | -_|
 *    |___|_,_|___|___|___|_|___|___|
 *
 * FILE:     lib_lcd.c
 * Author:   declis (xdec.de)
 ************************************************/

#include <msp430g2231.h>
#include "def_lcd.h"

// send one character to display ; x=0...39 ; y=0,1
void write_char(unsigned char x_pos,unsigned char y_pos,unsigned char character)
{
    set_cursor(x_pos,y_pos);            // set cursor to xy-position
    set_instruction(1,character);
}

// send a string to display ; x=0..39 ; y=0,1
void write_string(unsigned char x_pos,unsigned char y_pos,const char *string)
{
    set_cursor(x_pos,y_pos);            // set cursor to xy-position
    while(*string!=0)
        set_instruction(1,*string++);
}

// set cursor to xy-position ; x=0...39 ; y=0,1
void set_cursor(unsigned char x_pos,unsigned char y_pos)
{
    if(y_pos)                           // second row + x_pos
        set_instruction(0,second_row+x_pos);
    else                                // first row + x_pos
        set_instruction(0,first_row+x_pos);
}

// 8bit-interface emulation for 4bit-interface (8bit into 2*4bit converter)
// register_sel = 0,1 (0=instruction,1=data)
// number = 8bit value
void set_instruction(unsigned char register_sel,unsigned char number)
{
    volatile unsigned char high_part=0,low_part=0;

    high_part=(number>>4);            // transform 8bit into 2*4bit
    low_part=(number&0x0F);

    if(register_sel)                // if register_sel=1 -> RS=high
    {
        high_part|=RS;
        low_part|=RS;
    }

    send_lcd(high_part);            // send high part
    send_lcd(low_part);             // send low part
}

void send_lcd(unsigned char value)
{
    volatile unsigned char run=0;

    value|=Enable;                  // enable=high

    while(run!=2)
    {
        if(run) value&=~Enable;     // 2nd run, enable=low
        USISRL=value;               // USI 8bit shift register= = 7bit value
        USICNT=7;                   // start transmission (7bit)
        wait_us(100);
        run++;
    }
}

void init_lcd(void)
{
    wait_ms(20);
    send_lcd(_8bit_inter);
    wait_ms(5);
    send_lcd(_8bit_inter);
    wait_ms(2);
    send_lcd(_8bit_inter);
    send_lcd(2);                // change interface to 4bit

    set_instruction(0,40);      // 5x8, 2-rows
    set_instruction(0,8);       // display off
    set_instruction(0,1);       // clear display
    set_instruction(0,6);       // shift cursor to the right, no display shift
    set_instruction(0,12);      // display on
}

void init_USI(void)
{
    // P1.7 (strobe) -> output
    P1DIR|=strobe;
    P1OUT&=~strobe;
    // SPI Master, SI enabled, CLK enabled, LSB first, output enabled, USI in reset state
    USICTL0|=USIPE6+USIPE5+USIMST+USILSB+USIOE+USISWRST;
    // USI counter interrupt enabled,
    // data is captured on the first CLK edge and changed on the following edge
    USICTL1|=USICKPH+USIIE;
    // CLK-Source=SMCLK=1MHz
    USICKCTL|=USISSEL_2;
    // USI released for operation
    USICTL0&=~USISWRST;
    // clear USIIFG
    USICTL1&=~USIIFG;
    // global interrupt enabled
    _EINT();
}

#pragma INTERRUPT (USI)
#pragma vector=USI_VECTOR
void USI(void)
{
    P1OUT|=strobe;                  // strobe-pulse
    P1OUT&=~strobe;
    USICTL1&=~USIIFG;               // clear USIIFG
}

void wait_ms(unsigned int m_sec)
{
    while(m_sec--)
        __delay_cycles(1000);
}

void wait_us(unsigned int u_sec)
{
    while(u_sec--)
        __delay_cycles(1);
}

FILE: def_lcd.h

  1. /*************************************************
  2.  *     ___       _             _    
  3.  *    |   |_ _ _| |___ ___   _| |___
  4.  *    | | |_'_| . | -_|  _|_| . | -_|
  5.  *    |___|_,_|___|___|___|_|___|___|
  6.  *
  7.  * FILE:     def_lcd.h
  8.  * Author:   declis (xdec.de)
  9.  ************************************************/
  10.  
  11. #ifndef DEF_LCD_H_
  12. #define DEF_LCD_H_
  13.  
  14. void write_char(unsigned char x_pos,unsigned char y_pos,unsigned char character);
  15. void write_string(unsigned char x_pos,unsigned char y_pos,const char *string);
  16. void set_cursor(unsigned char x_pos,unsigned char y_pos);
  17. void set_instruction(unsigned char register_sel,unsigned char number);
  18. void send_lcd(unsigned char value);
  19. void init_USI(void);
  20. void init_lcd(void);
  21. void wait_ms(unsigned int);
  22. void wait_us(unsigned int);
  23.  
  24. #define _8bit_inter     0x03
  25. #define Enable          0x40
  26. #define RS              0x20
  27.  
  28. #define first_row       0x80
  29. #define second_row      0xC0
  30.  
  31. //8bit-shift-register
  32. #define clock       0x0020          //"Strobe" at P1.5
  33. #define data        0x0040          //"Data" at P1.6
  34. #define strobe      0x0080          //"Clock" at P1.7
  35.  
  36. #endif /*DEF_LCD_H_*/
/*************************************************
 *     ___       _             _     
 *    |   |_ _ _| |___ ___   _| |___
 *    | | |_'_| . | -_|  _|_| . | -_|
 *    |___|_,_|___|___|___|_|___|___|
 *
 * FILE:     def_lcd.h
 * Author:   declis (xdec.de)
 ************************************************/

#ifndef DEF_LCD_H_
#define DEF_LCD_H_

void write_char(unsigned char x_pos,unsigned char y_pos,unsigned char character);
void write_string(unsigned char x_pos,unsigned char y_pos,const char *string);
void set_cursor(unsigned char x_pos,unsigned char y_pos);
void set_instruction(unsigned char register_sel,unsigned char number);
void send_lcd(unsigned char value);
void init_USI(void);
void init_lcd(void);
void wait_ms(unsigned int);
void wait_us(unsigned int);

#define _8bit_inter     0x03
#define Enable          0x40
#define RS              0x20

#define first_row       0x80
#define second_row      0xC0

//8bit-shift-register
#define clock       0x0020          //"Strobe" at P1.5
#define data        0x0040          //"Data" at P1.6
#define strobe      0x0080          //"Clock" at P1.7

#endif /*DEF_LCD_H_*/

Leave a Reply

Your email address will not be published. Required fields are marked *

Time limit is exhausted. Please reload CAPTCHA.