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
Video
C-Programm
FILE: main.c
- /*************************************************
- * ___ _ _
- * | |_ _ _| |___ ___ _| |___
- * | | |_'_| . | -_| _|_| . | -_|
- * |___|_,_|___|___|___|_|___|___|
- *
- * 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: 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
- ´/*************************************************
- * ___ _ _
- * | |_ _ _| |___ ___ _| |___
- * | | |_'_| . | -_| _|_| . | -_|
- * |___|_,_|___|___|___|_|___|___|
- *
- * 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: 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
- /*************************************************
- * ___ _ _
- * | |_ _ _| |___ ___ _| |___
- * | | |_'_| . | -_| _|_| . | -_|
- * |___|_,_|___|___|___|_|___|___|
- *
- * 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_*/
/************************************************* * ___ _ _ * | |_ _ _| |___ ___ _| |___ * | | |_'_| . | -_| _|_| . | -_| * |___|_,_|___|___|___|_|___|___| * * 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_*/