Sei sulla pagina 1di 3

10/15/2017 Microcontrollers - A Beginner's Guide - Our First LCD Program

[ Your Cart ] [ Log In ]

NewbieHack.com
LEARN THE FUNDAMENTALS OF MECHATRONICS!

Products Microcontroller tutorials Show and Tell Contact Us Add a Video Clip C# Notes and Examples

Product/Video Search GO

ARM DEVELOPMENT Microcontroller - A Beginners Guide - Writing Our first LCD Program
ARDUINO AVR
DEVELOPMENT
20. Arduino for Production! AVR Atmega32 - How to write our First LCD Program
CABLES AND WIRES
$8.50
CAPACITORS

COMMUNICATION

CONNECTORS

CRYSTAL OSCILLATORS
$10.95
DEVELOPMENT TOOLS

DVDS

INPUT DEVICES

INTEGRATED CIRCUITS

INTERFACES
$0.94
LCD DISPLAYS AND LEDS

MERCHANDISE
Now that we know almost all that we need to know about interfacing the LCD to the microcontroller, we can jump right into
MICROCONTROLLER programming. We know the sequence that we need to control the pins of the LCD from the previous tutorial. Lets list the
sequence so we can understand how to create the program.
MICROCONTROLLER KITS
If we want to send a command or a character to the LCD, we must first check to see if the LCD is busy or not. If not, then it is
MOTOR DRIVERS ok to send the command or character. Let take a look at the sequence of instructions we need to use to check the busy
status. Also, consider peeking at the LCD processor's datasheet. This has all of the georgous information and specifications $0.43
MOTORS that you could ever want to know about LCD's. Lost? Count on me to help decipher this information these tutorials.

POTENTIOMETERS (1) Set the microcontroller port data direction to input. Let's call this DDR port as DataDir
(2) Set the pin connected to the LCD RW to ON (read mode)
PROGRAMMERS (3) Set the pin connected to the LCD RS to OFF (command mode)
(4) Turn the enable on, then off after a tiny delay.
POWER (5) Read the D7 pin to determine if it is a 1 or a 0.
(6) Do numbers 4 and 5 until the D7 is 0 (meaning that it is not busy).
PROTOTYPING
$0.75
The above instructions would be contained in its own sub routine. We could call it something like
RESISTORS Check_If_The_LCD_Is_Busy. It might look like this:

SENSORS
void CheckIfBusy()
TESTERS {
DDRB = 0b00000000; //Put PortB in Input (read) Mode
VOLTAGE REGULATORS PORTD &= ~(1<<2); //Turn on Mr. LCD's Command Mode (RS off)
PORTD |= (1<<7); //Set Mr. LCD to Read (RW on)
while (PORTB >= 0x80); //D7 pin will be a "1" with any number above 0x80 (that's hex) $3.80
Microcontroller - Intro {
BlinkLight(); // this is just another routine to turn the enable on and off
MCU Programmer 1 }
DDRB = 0xFF; //Set portB as output
MCU Programmer 2 }

MCU WinAVR Install

MCU Add LED and Test That BlinkLight() command is just a routine to turn on the enable and then turn it back off. The LCD needs this to be able to
perform the action that it needs to. It's like giving Mr. LCD a kick to do his job! the code might look like this:
MCU First Program

MCU LED Blink $149.00


void BlinkLight()
{
Installing Atmel Studio 6
PORTD |= (1<<5); //Turn Enable on so Mr. LCD can function
asm volatile ("nop");
MCU Add a Button asm volatile ("nop");
//
https://www.newbiehack.com/MicrocontrollersABeginnersGuideOurFirstLCDProgram.aspx 1/3
10/15/2017 Microcontrollers - A Beginner's Guide - Our First LCD Program
PORTD &= ~(1<<5); //turn off Enable so Mr. LCD can Concentrate
Button Debouncing }
Software Debounce

The Button Game Ok, here is a quick quiz... Can you tell me what pin the Enable is connected to on the microcontroller? Don't worry about the
Creating a Button Library port for now, just the pin. $0.69

Timers Counters Basic Here are some new commands: asm, volatile and "nop". The "nop" is actually a command within the language of assembly
(aka assembler). This just allows the microcontroller to wait some nanoseconds. According to the datasheet, the Enable must
Intro to Interrupts be kept on for about 500 ns (nanoseconds).
Interfacing an LCD
So, now we have enough ammunition in our arsenal to start creating the code for sending a command, or sending a character
First LCD Program to the LCD display. The two are actually very similar. First we check to make sure the LCD is not busy. We are setting the RS to
off to send a command, and on to send a character. The port must have the output direction and the port must be equal to
LCD and Strings the approprate character, or command. Then the RW read/write would be off for write mode. The LCD can be flashed with the
enable (the BlinkLight command). The LCD then magically performs the action (displays the character, or follows your $9.95
Numbers on the LCD
direction -"command"). Here is what this code may look like:
Separating the LCD Code

Function to Display Integers void SendCommand(unsigned char command)


{
Power Sources CheckIfBusy();
PORTB = command;
Making Connectors PORTD &= ~((1<<2)|(1<<2)); //turn off RS (command mode) and RW (write mode)
BlinkLight();
Potentiometers DDRB = 0; $1.49
}
Intro to ADC
void SendCharacter(unsigned char character)
ADC - First Program {
CheckIfBusy();
ADC and 10-Bits PORTB = character;
PORTD &= ~(1<<7); //turn off RW (write mode)
PORTD |= (1<<2); //turn on RS (character display mode)
Accelerometers/ADC
BlinkLight();
DDRB = 0;
Measure ADC Noise }
ADC Multiple Channels

Intro to Hobby Servos You are now saying, why aren't you setting the data direction for the port. Well, the data direction for port B will always be in
Intro to PWM output mode unless it is check to see if the LCD is busy. So, within the CheckIfBusy() routine, I first make the port input, then
at the end of the CheckIfBusy() routine, I put it back to output.
Control a Servo with PWM
Wouldn't it be a pain in the #%^ if you needed to change the locations of the wires from the LCD to the microcontroller if you
UART and USART Details decided to, say, change the port. This is totally possible becuase the ports have other functions as well. You would need to go
UART One Way Comm. through almost each line of code and change the pin and port specifications. An easier way would be to asign these pins,
ports and even port direction at the beginning of the program. We do this with the "#define" statement. It's pretty self
Controlling Digital Servos explanitory just by looking at the program. Essentially, you are creating a proxy (proxy... an evil clone, but with a different
name... think about it, in the year 2245, you wouldn't name your clone with the same name? Would you?) for these numbers
I2C Programming (Exclusive)
and port designations and populating the program with these proxies instead. Here is the program at this stage having the
ability to send commands and characters to the LCD.

#include <avr/io.h>
#include <util/delay.h>

#define MrLCDsCrib PORTB


#define DataDir_MrLCDsCrib DDRB
#define MrLCDsControl PORTD
#define DataDir_MrLCDsControl DDRD
#define LightSwitch 5
#define ReadWrite 7
#define BiPolarMood 2

void Check_IF_MrLCD_isBusy(void);
void Peek_A_Boo(void);
void Send_A_Command(unsigned char command);
void Send_A_Character(unsigned char character);
void Send_A_String(char *string);

int main(void)
{
DataDir_MrLCDsControl |= 1<<LightSwitch | 1<<ReadWrite | 1<<BiPolarMood;
_delay_ms(15);

Send_A_Command(0x01); //Clear Screen 0x01 = 00000001


_delay_ms(2);
Send_A_Command(0x38);
_delay_us(50);
Send_A_Command(0b00001110);
_delay_us(50);

Send_A_Character(0x4E); //N
Send_A_Character(0x65); //e
Send_A_Character(0x77); //w
Send_A_Character(0x62); //b
Send_A_Character(0x69); //i
Send_A_Character(0x65); //e
Send_A_Character(0x48); //H
Send_A_Character(0x61); //a
Send_A_Character(0x63); //c
Send_A_Character(0x6B); //k

https://www.newbiehack.com/MicrocontrollersABeginnersGuideOurFirstLCDProgram.aspx 2/3
10/15/2017 Microcontrollers - A Beginner's Guide - Our First LCD Program
_ _
Send_A_Character(0x2E); //.
Send_A_Character(0x63); //c
Send_A_Character(0x6F); //o
Send_A_Character(0x6D); //m

Send_A_String("Patrick");

while(1)
{
}
}

void Check_IF_MrLCD_isBusy()
{
DataDir_MrLCDsCrib = 0;
MrLCDsControl |= 1<<ReadWrite;
MrLCDsControl &= ~1<<BiPolarMood;

while (MrLCDsCrib >= 0x80)


{
Peek_A_Boo();
}
DataDir_MrLCDsCrib = 0xFF; //0xFF means 0b11111111
}

void Peek_A_Boo()
{
MrLCDsControl |= 1<<LightSwitch;
asm volatile ("nop");
asm volatile ("nop");
MrLCDsControl &= ~1<<LightSwitch;
}

void Send_A_Command(unsigned char command)


{
Check_IF_MrLCD_isBusy();
MrLCDsCrib = command;
MrLCDsControl &= ~ ((1<<ReadWrite)|(1<<BiPolarMood));
Peek_A_Boo();
MrLCDsCrib = 0;
}

void Send_A_Character(unsigned char character)


{
Check_IF_MrLCD_isBusy();
MrLCDsCrib = character;
MrLCDsControl &= ~ (1<<ReadWrite);
MrLCDsControl |= 1<<BiPolarMood;
Peek_A_Boo();
MrLCDsCrib = 0;
}

Here is the result of the above program:

So you actually scrolled all the way down to the bottom of this page
and actually WANT MORE! I'm so excited and would refer you to my
next tutorial on adding string functionality to this LCD tutorial. If, on
the other hand, you are completely lost, you can go to the previous
tutorial to know more about the inner guts of the LCD, or you could
just start from the beginning.


About Us - Site Map - Donate
Save
© Copyright 2014, PHD Robotics, LLC.

https://www.newbiehack.com/MicrocontrollersABeginnersGuideOurFirstLCDProgram.aspx 3/3

Potrebbero piacerti anche