Displays "Hello World!" and "Pac-Man!" on LCD C Program

How to write a C Program to Displays "Hello World!" and "Pac-Man!" on LCD in C Programming Language ?


  1. #include <msp430.h>
  2. //#include "LCD.h"
  3. //#include "CLK.h"
  4. // Port 1 defines
  5. #define BTN BIT3
  6. #define DB4 BIT4
  7. #define DB5 BIT5
  8. #define DB6 BIT6
  9. #define DB7 BIT7
  10. // Port 2 defines
  11. #define RS BIT0
  12. #define RW BIT1
  13. #define E  BIT2
  14. // CGRAM character defines
  15. #define PacMan 0x00
  16. #define Ghost 0x01
  17. #define Dot 0x02
  18. /*
  19.  * main.c
  20.  *
  21.  * Title: Project 1 Hello World
  22.  *
  23.  * Authors: Daniel Hodges & Omar Arriaga
  24.  *
  25.  * Description: Displays "Hello World!" on LCD. Press BTN -> displays "Pac-Man!",
  26.  * after 5 seconds displays a Pac-Man animation.
  27.  *
  28.  * I/O Ports: (x = no connect)
  29.  *
  30.  *  MSP: P1.[0 1 2 3 4 5 6 7]
  31.  *      LCD:  DB[x x x x 4 5 6 7]
  32.  *
  33.  *  MSP: P2.[ 0  1  2 3 4 5 6 7]
  34.  *      LCD:     RS R/W E x x x x x
  35.  *
  36.  */
  37. // function and variable declarations
  38. void lcd_wrt_cmd_nibble(unsigned short cmd);
  39. void lcd_wrt_data_nibble(unsigned short data);
  40. void lcd_init_seq_nibble();
  41. void lcd_clear_display();
  42. void lcd_set_DDRAM(unsigned short address);
  43. void lcd_create_characters();
  44. void lcd_display_HelloWorld();
  45. void lcd_display_PacMan();
  46. void lcd_animation_PacMan();
  47. void clk_set_16MHZ();
  48. void delay_clk_s(int sec);
  49. void delay_clk_ms(int ms);
  50. void delay_clk_us(int us);
  51. char toggle_message = 0x00;
  52. int main(void) {
  53.     WDTCTL = WDTPW | WDTHOLD;   // Stop watchdog timer
  54.     clk_set_16MHZ(); // set clock to 16MHz
  55.     P1DIR |= (DB4 + DB5 + DB6 + DB7); // sets ports P1.4-7 to outputs
  56.     P2DIR |= (RS + RW + E); // sets ports P2.0-2 to outputs (RS, R/W, E)
  57.     P1IE |= BTN; // P1.3 interrupt enabled
  58.     P1REN |= BTN; // add internal pullup to P1.3
  59.     P1OUT |= BTN; // selects pullup for P1.3
  60.     P1IES |= BTN; // P1.3 interrupt low to high enable
  61.     P1IFG &= ~BTN; // P1.3 IFG cleared
  62.     _enable_interrupts();
  63.     lcd_init_seq_nibble(); // initialize sequence for LCD nibble mode (2-line mode, 5x8 dots, cursor off, increment, no shifting)
  64.     lcd_create_characters(); // creates characters and stores into CGRAM
  65.     // infinite loop waiting for button press to toggle between messages
  66.     for(;;){
  67.         if (toggle_message == 0x00){
  68.                 lcd_display_HelloWorld();
  69.                 toggle_message |= 0x02;
  70.         }
  71.         else if (toggle_message == 0x01){
  72.                 lcd_display_PacMan();
  73.                 delay_clk_s(5); // wait for 5s
  74.                 lcd_animation_PacMan();
  75.         }
  76.         else{
  77.         }
  78.     }
  79. }
  80. //write instruction to LCD in nibble mode (writes one nibble at a time)
  81. void lcd_wrt_cmd_nibble(unsigned short cmd){
  82.         _disable_interrupts();
  83.         P2OUT = 0x00;                   // clear RS, R/W, E
  84.         P2OUT = 0x04;               // set E
  85.         P1OUT &= 0x0F;
  86.         P1OUT |= (cmd << 4) & 0xF0; // write command data
  87.         delay_clk_us(1);            // wait for more than 220ns
  88.         P2OUT = 0x00;               // clear E
  89.         delay_clk_us(80);                   // wait for more than 39us
  90.         _enable_interrupts();
  91. }
  92. // write data to LCD in nibble mode (writes both nibbles at same time)
  93. void lcd_wrt_data_nibble(unsigned short data){
  94.         _disable_interrupts();
  95.         // write upper 4-bits
  96.         P2OUT = 0x01;                            // Set RS; clear R/W, E
  97.         P2OUT = 0x05;                        // set E and RS
  98.         P1OUT &= 0x0F;
  99.         P1OUT |= data & 0xF0;            // write command data
  100.         delay_clk_us(1);             // wait for more than 220ns
  101.         P2OUT = 0x01;                // clear E; Set RS
  102.         delay_clk_us(80);            // wait for more than 39us
  103.         // write lower 4-bits
  104.         P2OUT = 0x01;                            // Set RS; clear R/W, E
  105.         P2OUT = 0x05;                        // set E and RS
  106.         P1OUT &= 0x0F;
  107.         P1OUT |= (data << 4) & 0xF0; // write command data
  108.         delay_clk_us(1);                 // wait for more than tw = 220ns
  109.         P2OUT = 0x01;                    // clear E; Set RS
  110.         delay_clk_us(80);                // wait for more than 39us
  111.         _enable_interrupts();
  112. }
  113. // initialize sequence for LCD nibble mode (2-line mode, 5x8 dots, cursor off, increment, no shifting)
  114. void lcd_init_seq_nibble(){
  115.         _disable_interrupts();
  116.         delay_clk_ms(60);               // wait for more than 30ms after power on
  117.         //function set w/ 2-line mode and 5x8 dots
  118.         lcd_wrt_cmd_nibble(0b0010);
  119.         lcd_wrt_cmd_nibble(0b0010);
  120.         lcd_wrt_cmd_nibble(0b1100);
  121.         // Display On/Off Control w/ cursor off
  122.         lcd_wrt_cmd_nibble(0b0000);
  123.         lcd_wrt_cmd_nibble(0b1100);
  124.     // Display Clear
  125.         lcd_wrt_cmd_nibble(0b0000);
  126.         lcd_wrt_cmd_nibble(0b0001);
  127.     delay_clk_ms(5);                // wait for more than 1.53ms after function set
  128.     // Entry Mode Set w/ increment and no shifting
  129.         lcd_wrt_cmd_nibble(0b0000);
  130.         lcd_wrt_cmd_nibble(0b0110);
  131.         _enable_interrupts();
  132. }
  133. // clears lcd display
  134. void lcd_clear_display(){
  135.         _disable_interrupts();
  136.     // Display Clear
  137.         lcd_wrt_cmd_nibble(0b0000);
  138.         lcd_wrt_cmd_nibble(0b0001);
  139.     delay_clk_ms(5);
  140.         _enable_interrupts();
  141. }
  142. // sets DDRAM address for line 1
  143. void lcd_set_DDRAM_address(unsigned short address){
  144.         lcd_wrt_cmd_nibble((BIT7 + (address & 0x70)) >> 4);
  145.         lcd_wrt_cmd_nibble(address & 0x0F);
  146. }
  147. // creates characters and stores them in CGRAM
  148. void lcd_create_characters(){
  149.         _disable_interrupts();
  150.         // put PacMan into CGRAM address 0
  151.     lcd_wrt_cmd_nibble(0b0100);
  152.     lcd_wrt_cmd_nibble(0b0000);
  153.     lcd_wrt_data_nibble(0b00000000);
  154.     lcd_wrt_data_nibble(0b00001110);
  155.     lcd_wrt_data_nibble(0b00011011);
  156.     lcd_wrt_data_nibble(0b00011110);
  157.     lcd_wrt_data_nibble(0b00011100);
  158.     lcd_wrt_data_nibble(0b00011110);
  159.     lcd_wrt_data_nibble(0b00011111);
  160.     lcd_wrt_data_nibble(0b00001110);
  161.     // put Ghost into CGRAM address 1
  162.     lcd_wrt_cmd_nibble(0b0100);
  163.     lcd_wrt_cmd_nibble(0b1000);
  164.     lcd_wrt_data_nibble(0b00000000);
  165.     lcd_wrt_data_nibble(0b00001110);
  166.     lcd_wrt_data_nibble(0b00011111);
  167.     lcd_wrt_data_nibble(0b00010101);
  168.     lcd_wrt_data_nibble(0b00011111);
  169.     lcd_wrt_data_nibble(0b00011111);
  170.     lcd_wrt_data_nibble(0b00010101);
  171.     lcd_wrt_data_nibble(0b00000000);
  172.     // put Dot into CGRAM address 2
  173.     lcd_wrt_cmd_nibble(0b0101);
  174.     lcd_wrt_cmd_nibble(0b0000);
  175.     lcd_wrt_data_nibble(0b00000000);
  176.     lcd_wrt_data_nibble(0b00000000);
  177.     lcd_wrt_data_nibble(0b00000000);
  178.     lcd_wrt_data_nibble(0b00001110);
  179.     lcd_wrt_data_nibble(0b00001110);
  180.     lcd_wrt_data_nibble(0b00001110);
  181.     lcd_wrt_data_nibble(0b00000000);
  182.     lcd_wrt_data_nibble(0b00000000);
  183.     _enable_interrupts();
  184. }
  185. // displays "Hello World!" on display
  186. void lcd_display_HelloWorld(){
  187.         _disable_interrupts();
  188.         lcd_clear_display();
  189.         lcd_set_DDRAM_address(0x04); // Set DDRAM address to 4 (line 1)
  190.     lcd_wrt_data_nibble('H'); // Set DDRAM to H
  191.     lcd_wrt_data_nibble('e'); // Set DDRAM to e
  192.     lcd_wrt_data_nibble('l'); // Set DDRAM to l
  193.     lcd_wrt_data_nibble('l'); // Set DDRAM to l
  194.     lcd_wrt_data_nibble('o'); // Set DDRAM to o
  195.     lcd_wrt_data_nibble(' '); // Set DDRAM to ' '
  196.     lcd_wrt_data_nibble('W'); // Set DDRAM to W
  197.     lcd_wrt_data_nibble('o'); // Set DDRAM to o
  198.     lcd_wrt_data_nibble('r'); // Set DDRAM to r
  199.     lcd_wrt_data_nibble('l'); // Set DDRAM to l
  200.     lcd_wrt_data_nibble('d'); // Set DDRAM to d
  201.     lcd_wrt_data_nibble('!'); // Set DDRAM to !
  202.         _enable_interrupts();
  203. }
  204. // displays "Pac-Man!" on display
  205. void lcd_display_PacMan(){
  206.         _disable_interrupts();
  207.         lcd_clear_display();
  208.         lcd_set_DDRAM_address(0x04); // Set DDRAM address to 4 (line 1)
  209.     lcd_wrt_data_nibble('P'); // Set DDRAM to P
  210.     lcd_wrt_data_nibble('a'); // Set DDRAM to a
  211.     lcd_wrt_data_nibble('c'); // Set DDRAM to c
  212.     lcd_wrt_data_nibble('-'); // Set DDRAM to -
  213.     lcd_wrt_data_nibble('M'); // Set DDRAM to M
  214.     lcd_wrt_data_nibble('a'); // Set DDRAM to a
  215.     lcd_wrt_data_nibble('n'); // Set DDRAM to n
  216.     lcd_wrt_data_nibble('!'); // Set DDRAM to !
  217.         _enable_interrupts();
  218. }
  219. // displays a Pac-Man animation
  220. void lcd_animation_PacMan(){
  221.         _disable_interrupts();
  222.         lcd_clear_display();
  223.         // Display On/Off Control w/ cursor on and blinking
  224.         lcd_wrt_cmd_nibble(0b0000);
  225.         lcd_wrt_cmd_nibble(0b1111);
  226.         lcd_set_DDRAM_address(0x03); // Set DDRAM address to 4 (line 1)
  227.         lcd_wrt_data_nibble(' '); // Set DDRAM to ' '
  228.     delay_clk_s(1);
  229.     lcd_wrt_data_nibble(PacMan); // Set DDRAM to PacMan
  230.     delay_clk_ms(750);
  231.     // for loop puts 10 dots in a row
  232.     unsigned short i;
  233.     for (i=0; i<9; i++){
  234.         lcd_wrt_data_nibble(Dot); // Set DDRAM to Dot
  235.         delay_clk_ms(750);
  236.     }
  237.     lcd_wrt_data_nibble(Ghost); // Set DDRAM to Ghost
  238.         // Display On/Off Control w/ cursor off
  239.         lcd_wrt_cmd_nibble(0b0000);
  240.         lcd_wrt_cmd_nibble(0b1100);
  241.     delay_clk_ms(750);
  242.         // PacMan eats dots
  243.     for (i=4; i<14; i++){
  244.         lcd_set_DDRAM_address(i);
  245.         lcd_wrt_data_nibble(' '); // Set DDRAM to ' '
  246.         lcd_wrt_data_nibble(PacMan); // Set DDRAM to PacMan
  247.         delay_clk_ms(500);
  248.     }
  249.     // PacMan hits ghost and dies (blinks on and off)
  250.     for (;;){
  251.         lcd_set_DDRAM_address(14);
  252.         lcd_wrt_data_nibble(' '); // Set DDRAM to ' '
  253.         delay_clk_ms(500);
  254.         lcd_set_DDRAM_address(14);
  255.         lcd_wrt_data_nibble(PacMan); // Set DDRAM to PacMan
  256.         delay_clk_ms(500);
  257.     }
  258. }
  259. // sets clock to 16MHz
  260. void clk_set_16MHZ(){
  261.     //16Mhz
  262.     if (CALBC1_16MHZ==0xFF) // If calibration constant erased
  263.     {
  264.     while(1); // do not load, trap CPU!!
  265.     }
  266.     DCOCTL = 0; // Select lowest DCOx and MODx settings
  267.     BCSCTL1 = CALBC1_16MHZ; // Set range
  268.     DCOCTL = CALDCO_16MHZ; // Set DCO step + modulation
  269. }
  270. // delay clock by # of seconds
  271. void delay_clk_s(int sec){
  272.         int i;
  273.         for (i=0; i< sec; i++){
  274.                 _delay_cycles(16000000);
  275.         }
  276. }
  277. // delay clock by # of milliseconds
  278. void delay_clk_ms(int ms){
  279.         int i;
  280.         for (i=0; i< ms; i++){
  281.                 _delay_cycles(16000);
  282.         }
  283. }
  284. // delay clock by # of microseconds
  285. void delay_clk_us(int us){
  286.         int i;
  287.         for (i=0; i< us; i++){
  288.                 _delay_cycles(16);
  289.         }
  290. }
  291. // Port 1 interrupt service routine
  292. #pragma vector=PORT1_VECTOR
  293. __interrupt void Port_1(void)
  294. {
  295. delay_clk_ms(100);
  296. toggle_message &= BIT0;
  297. toggle_message ^= BIT0;
  298. P1IFG &= ~BTN; // P1.3 IFG cleared
  299. delay_clk_ms(100);
  300. }


Learn More :