Serial Communication

Hello!! Before I start this post I want to say that if anyone of you wants to add me to their linkedin network here is my profile link : in.linkedin.com/in/msminhas93/

Often we need to communicate between two devices. This can be either parallel or serial. In parallel communication there is an individual data line for each bit, so normally there would be 8 data lines for 8 bit data. In asynchronous we require only two lines. One for transmission and the other for reception.

Theory

So the main thing in serial communication is ‘baud rate’. It is nothing but the bits sent per second. In serial asynchronous communication the baud rate of both transmitter and receiver have to be equal. If there is any mismatch there is bound to be error in sending and receiving data.

Now you might wonder what is sent serially? The answer is ASCII values of the character or symbol to be transmitted is sent serially. Now ASCII is a 7 bit hex code. There is the extended ASCII code as well. You can find all the ASCII values here.

Now let us take an example. Suppose I want to send character M serially. The ASCII value of M is 0x4D. The binary equivalent is 0b01001101. Now we send this data as pulses, changing the bits after the time 1/baud_rate.

070120141331

So this is how the serial data looks like. Some of you might have this doubt that how on earth will the processor or controller come to know that the other party is transmitting data and it has to take those bits. This is a very good doubt.

The beginning of serial data is marked by a start bit and on similar grounds there is a stop bit or two. Just like one normally says ‘hello’ at the start of a conversation and ‘bye’ at the end we send the start and stop bits for the same purpose.

The other question that may arise in the mind of the curious is that what if there is noise in the system? This is a valid question as well. So there are error checking bits like parity bits which are sent along with the data serially. (Parity can be even or odd. Now if the system uses even parity, then it will make the number of ‘1’ bits in the data even by adding 1 or 0. So if the data already has even number of ones the even parity bit is 0 and if the data has odd number of ones then the even parity bit is set or is 1 so that the total number of ones in the data is even.) Well this sums up asynchronous serial communication part.

Now this is known as UART module in the microcontrollers. UART stands for universal asynchronous transmitter and receiver. Most modern microcontrollers have a dedicated hardware for asynchronous serial communication called UART. msp430 also has this facility. Now what this means that you have to just configure the peripheral and the baud rate generation, parity bits and all other factors as well as the receiving part is done by this hardware. (If you wanted to send data serially without hardware dedicated for the same you would have to make the port high and low, use delay subroutines and the rotate instructions for doing the same task. The detection will also be tedious.)

This is how the data will look when  you send it via UART module.

w_example

Well let’s begin with the USCI module that provided in the msp430 micro controllers. This provides a UART mode for asynchronous serial communication. There are few basic initialization registers like all peripherals of msp430. Note that you can use grace for initializing the UART mode. But I’ll be covering the normal method by using the command registers and configuring it to meet our needs.

Let us begin.

UART mode features include:
• 7- or 8-bit data with odd, even, or non-parity
• Independent transmit and receive shift registers
• Separate transmit and receive buffer registers
• LSB-first or MSB-first data transmit and receive
• Built-in idle-line and address-bit communication protocols for multiprocessor systems
• Receiver start-edge detection for auto-wake up from LPMx modes
• Programmable baud rate with modulation for fractional baud rate support
• Status flags for error detection and suppression
• Status flags for address detection
• Independent interrupt capability for receive and transmit

The list of all registers related to the UART mode are listed below.

registers_list

Now the procedure how to initialize these registers is given in the msp430g2 user manual.

initializing

Just set those bits which you want as per the explanation given in the user guide.

Then there are the UCA0TXBUF and UCA0RXBUF via which the serial data is transmitted and received respectively. If you want to send any character just put it in the UCA0TXBUF register and it will be transmitted. Just check whether the byte has been sent or not by checking the UCA0TXIFG bit of IFG2 register. If it is set means the module is busy sending the previous byte or data and one has to wait till it is reset.

With this background you should be able to program the controller to send and receive data.

Before we shift to the program there is something that I need to tell you. For hardware UART via launchpad without having to use the rs232 cable and max232 IC. For newer launchpad versions i.e. 1.5 and above there is the position of the jumpers printed on the launchpad itself for hardware UART and software UART respectively.

Hardware UART on Launchpad 1.4

If you have a Launchpad of v1.4 (versions that have no ‘Rev x.x’ printed below the ‘MSP-EXP430G2’ label are pre 1.5) is is possible to use hardware UART by replacing the MSP430 with a newer model, such as the MSP430G2553 and then cross connecting the serial pins in header J3 i.e the TXD and RXD(use a cross jumper or female to female wires for the same.)

Program

#include "serial.h"
#include "lcd.h"
int main(void) {
    WDTCTL = WDTPW | WDTHOLD;	// Stop watchdog timer
    uart_init();
    lcd_init();
    IE2 |= UCA0RXIE;
    println("START");
    __bis_SR_register(LPM0_bits + GIE);
}
#pragma vector=USCIAB0RX_VECTOR
__interrupt void USCI0RX_ISR(void)
{
	if(UCA0RXBUF == '0')
        {
            send_command(0x01);
        }
	else
        send_data(UCA0RXBUF);
}

/*
 *  serial.h
 *  Created on   	: 01-Jan-2014 12:25:06 PM
 *  Author	  	: Manpreet Singh Minhas
 *  Website		: https://learningmsp430.wordpress.com/
 *  This is a standard header for 9600 baud rate serial communication.
 */

#ifndef SERIAL_H_
#define SERIAL_H_

#include<msp430g2553.h>// Change this as per your micro-controller chip.
void uart_init(void);
void send_byte(int data);
void print(char *data);
void println(char *data);
void send_int(int a);
void send_intln(int a);
void uart_init()
{
	P1SEL  |= BIT1|BIT2; // Port for UART transmission and reception purpose.
	P1SEL2 |= BIT1|BIT2;
    UCA0CTL1 |= UCSWRST; // Software reset
    UCA0CTL1 |= UCSSEL_1;// Select ACLK
    UCA0BR0 = 3;// This is the count for getting 9600 baud rate 32768/9600 = 3.4133
    UCA0BR1 = 0;
    UCA0MCTL = UCBRS1 + UCBRS0;// Modulation bits = 0b00000011
    UCA0CTL1 &= ~UCSWRST;	// Start the UART
}
void send_byte(int data)
{
	while (!(IFG2&UCA0TXIFG));
	UCA0TXBUF = data;
}
void print(char *data)
{
	while(*data)
	{
		send_byte(*data);
		data++;
	}
}
void println(char *data)
{
	while(*data)
	{
		send_byte(*data);
		data++;
	}
	send_byte('\n');
	send_byte('\r');
}
void send_int(int a)
{
	int temp;
	int rev=0;
	int dummy =a;
	 while (dummy)
	   {
	      rev = rev * 10;
	      rev = rev + dummy%10;
	      dummy = dummy/10;
	   }
	while(rev)
	{
		temp=rev%10;
		send_byte(0x30+temp);
		rev /=10;
	}
}
void send_intln(int a)
{
	int temp;
	int rev=0;
	int dummy =a;
	 while (dummy)
	   {
	      rev = rev * 10;
	      rev = rev + dummy%10;
	      dummy = dummy/10;
	   }
	while(rev)
	{
		temp=rev%10;
		send_byte(0x30+temp);
		rev /=10;
	}
	 send_byte('\n');
	 send_byte('\r');
}
#endif/* SERIAL_H_ */

Well this program will send the data received serially to lcd. For sending data you will require a software like hyper terminal, putty, energia serial monitor, arduino serial monitor etc. So just configure that to 9600 baud rate with no parity bits and only one stop bit and you are all set to send data serially. If you have any problem you can comment or send me mail.

Video

Advertisements

16×2 LCD interfacing in 4 bit mode

Hello there!! After trying many times I finally managed to interface LCD in 4 bit mode. I’m writing this post as soon as I got the output and understood what was going wrong. First things first, if you are reading this article directly without knowing about 8 bit mode interfacing then you should read my blog post on 8 bit LCD interfacing. Assuming that you know what 8 bit mode is, let’s begin with the 4 bit mode interfacing.

Need for 4 bit mode

Well for interfacing anything with any processor we need system-bus (data-bus, address-bus and control-bus). In our case for 8 bit mode the 8 data pins (D0-D7) are the data and address bus while the 3 control pins(RS, R/W and E) are the control bus. Thus using these we can control the peripheral that we are interfacing. We are greedy so we want to interface as many peripherals as possible with the same microcontroller. This requires either large number of ports or we need to be smart and utilize what we have to the fullest. Thus first thing is we try to do is reduce the number of pins required for controlling the peripheral. Here comes the need for 4 bit mode. Thus we reduce the port pins required from 11 to 7. It might not seem much, but for a small microcontroller like msp430g2553 with limited port pins this is really a big amount. Now coming to the other method. Maybe we can use demultiplexing , in this way we can use ‘n’ lines to share the system bus with ‘2^n’ devices. I got one tip that we can use SIPO shift register for sending data. Now this will require only 5 port pins. Three control pins and two for serial data and clock.

4 bit mode working

In 4 bit mode we send the data nibble by nibble, first upper nibble and then lower nibble. For those of you who don’t know what a nibble is: a nibble is a group of four bits, so the lower four bits (D0-D3) of a byte form the lower nibble while the upper four bits (D4-D7) of a byte form the higher nibble. This enables us to send 8 bit data be it the ASCII code or the command code by using 4 pins instead of 8. The connections remain identical. The only change is that the lower nibble pins of LCD are unused.

Initializing the LCD in 4 bit mode

This is perhaps the most tricky part of this interfacing. When LCD is powered ON it is by default in 8 bit mode.

reset

This is the command code format for function set operation. Using this we form the command code for 4 bit mode operation.

upper part

mode_set

The function set bits are explained in the following section.

functions_mode_set_bits

We need 4 bit mode so make DL ‘0’. Thus the upper nibble of the command code is 0010b which is 0x02. If we need 2 lines we set N and the normal font so F is 0 thus lower nibble comes out to be 1000b i.e 0x08. Thus total command code is 0x28.

Before sending this 0x28 we need to perform a specific initialization.

initialization

So we send 0x33 as the command code. This will do the initial 8 bit mode starting of LCD. Now after this we need to send 0x32.(Note : We’re using the nibble method so what will go for 0x33 is 3 followed by 3 and for 0x32 is 3 followed by 2.) I was not able to do the initialization. But then I suddenly remembered about a workshop that I had attended on msp430. The professor had taught LCD interfacing in 4 bit mode but due to shortage of time could not go into the details. He had just told about the nibble sending part and that we need to send command codes to initialize. So I opened his file and saw this 0x33 and 0x32 and tried sending it. And to my surprise I got my name on the LCD. So this credit goes to him. His name is Gurjeet Singh Gill.

Now coming back to the topic at hand. So now we have initialized the LCD in 4 bit mode. All we need to learn is how to send the value nibble by nibble in c and without affecting other port pins except the ones that we use for sending data. (In assembly its just the rotate instruction.)

Nibble sending logic

P1OUT = (P1OUT & 0xF0)|((data>>4) & 0x0F); // send higher nibble

In this we make use of masking concept and logical shift operation in c. Now in my program I’m using P1.0 – P1.3 pins as the data pins. Thus I’ll explain the logic accordingly. Here data is the parameter that is passed in the function. I shift the data right by four bits, thus bringing the higher nibble in the lower nibble location. Mask the upper part. Then I make the P1OUT lower nibble 0 so that ‘or’ing with nibble data will give nibble data on P1OUT pin. (x and 0 is 0 ; x and 1 is x; x or 1 is 1 and x or 0 is x—-> (x&0)|(data_bit)= 0|data_bit= data_bit. Thus we get data bit on the port pin without affecting P1.4-P1.7) This takes care of upper nibble.

P1OUT = (P1OUT & 0xF0)|(data & 0x0F); // send lower nibble

Now lower nibble involves the same operations except the shifting operation.

Code

Header file :

// Author : Manpreet Singh Minhas
// This file is for 4 bit mode LCD interfacing with msp430g2553 chip
// 16x2 LCD is used
#include &lt;msp430g2553.h&gt;
#define DR P1OUT = P1OUT | BIT4 // define RS high
#define CWR P1OUT = P1OUT &amp; (~BIT4) // define RS low
#define READ P1OUT = P1OUT | BIT5 
// define Read signal R/W = 1 for reading
#define WRITE P1OUT = P1OUT &amp; (~BIT5) 
// define Write signal R/W = 0 for writing
#define ENABLE_HIGH P1OUT = P1OUT | BIT6 
// define Enable high signal
#define ENABLE_LOW P1OUT = P1OUT &amp; (~BIT6) 
// define Enable Low signal
unsigned int i;
unsigned int j;
void delay(unsigned int k)
{
for(j=0;j&lt;=k;j++)
{
for(i=0;i&lt;100;i++);

}

}
void data_write(void)
{
ENABLE_HIGH;
delay(2);
ENABLE_LOW;
}

void data_read(void)
{
ENABLE_LOW;
delay(2);
ENABLE_HIGH;
}

void check_busy(void)
{
P1DIR &amp;= ~(BIT3); // make P1.3 as input
while((P1IN&amp;BIT3)==1)
{
data_read();
}
P1DIR |= BIT3; // make P1.3 as output
}

void send_command(unsigned char cmd)
{

check_busy();
WRITE;
CWR;
P1OUT = (P1OUT &amp; 0xF0)|((cmd&gt;&gt;4) &amp; 0x0F); // send higher nibble
data_write(); // give enable trigger
P1OUT = (P1OUT &amp; 0xF0)|(cmd &amp; 0x0F); // send lower nibble
data_write(); // give enable trigger

}

void send_data(unsigned char data)
{
check_busy();
WRITE;
DR;
P1OUT = (P1OUT &amp; 0xF0)|((data&gt;&gt;4) &amp; 0x0F); // send higher nibble
data_write(); // give enable trigger
P1OUT = (P1OUT &amp; 0xF0)|(data &amp; 0x0F); // send lower nibble
data_write(); // give enable trigger
}

void send_string(char *s)
{
while(*s)
{
send_data(*s);
s++;
}
}

void lcd_init(void)
{
P1DIR |= 0xFF;
P1OUT &amp;= 0x00;
send_command(0x33);
send_command(0x32);
send_command(0x28); // 4 bit mode
send_command(0x0E); // clear the screen
send_command(0x01); // display on cursor on
send_command(0x06); // increment cursor
send_command(0x80); // row 1 column 1
}

Main Code:

/* LCD_own.c
* Created on: 12-Nov-2013
* Author: Manpreet
* In this program we interface the lcd in 4 bit mode. We send strings and display it on the screen.
*/
#include "lcd.h"

void main(void)
{
WDTCTL = WDTPW + WDTHOLD; // stop watchdog timer
lcd_init();
send_string("Manpreet Singh");
send_command(0xC0);
send_string("Minhas");
while(1){}
}

P1.0 – D4            Pin11

P1.1 – D5             Pin12

P1.2 – D6             Pin13

P1.3 – D7             Pin14

P1.4 – RS             Pin4

P1.5 – R/W         Pin5

P1.6 – E                 Pin6

16×2 LCD Interfacing in 8bit mode

lcd_real

Hello there!! In this post I’ll tell you about 16×2 LCD’s and their interfacing in 8 bit mode. As you all know LCD stands for liquid crystal display. Now earlier we used to use 7 segment displays for display purposes, but now LCD’s are preferred. The main reason is we need less number of databus lines for interfacing LCD’s as compared to 7 segment displays. Other reason is we can print various characters on the screen. Now the basic characters are already saved inside CGROM(Character Generator ROM). So you need to send only the ASCII values in order to display the character on screen. So let us see what a 16×2 LCD reakky means. It has 2 rows and 16 columns. So basically a 16×2 LCD has 32 blocks where one can display data. Each block has certain number of pixels. You can draw your own character by saving the pattern of pixels.

Ok then let’s begin. First things first lets get the datasheet. The link is : Datasheet Link

Please download the datasheet because a datasheet tells you everything there is to know the electrical parameters, command registers, pin-outs and so on. Assuming you have the datasheet with you, let’s go further.

Pin-out:

Lcd16x2Now there is a protruding rectangular portion on this LCD. This will help you identify which pin is which. Now let us see what each pin does exactly. But then they have also printed 16 and 1 on the back of LCD, so no need to worry about connecting the pins inverted.

lcd_pinoutThe pin features are explained in the table. The contrast adjust input is nothing but output taken from a pot.contrast-input

So basically when you vary the pot , you get different values of voltage from the voltage divider network. And thus you can change the contrast to suit your visual needs. (Caution: Do not give the LCD voltage greater than 5 Volts. Your LCD may get damaged. By more I’m not talking about 5.1 Volts but 6 V and beyond.)

RS, R/W,E are the control signals of LCD. DB0 to DB7 are the databus lines. You send the command word as well as the data to be written on this bus.

Let’s see a little about the control signals first.

RS : This stands for register select. The two registers in LCD are the data register and the command word/code register. In order to tell LCD that the bits on databus are for which register we make use of RS control signal via the RS pin. When you make this pin high you select data register, where you’ll send the ASCII values to be displayed on screen. When you make RS low you select the command word register where you’ll be sending all the commands for configuring and initializing the LCD.

RS = 1 —–> Data Register

RS = 0 —–> Command Code Register

R/W : This stands for read or write. The read is active high signal and write is active low. Thus when you want to read from the LCD you make the signal on this pin high and when you want to write you make the signal on this pin low.

R/W = 1 —-> Read Operation

R/W = 0 —-> Write Operation.

(For those who are wondering why W has no bar on its top indicating an active low signal, there should be one. Its just that I don’t know how to type W bar!!)

E : This stands for enable. This is a edge triggering signal which is used while writing or reading data to/from LCD respectively. E line is negative edge triggered for write while it is positive edge triggered for the read. The timing diagram given in datasheet tells about the minimum delay between the level transitions.

E = high to low / negative edge triggered —-> Write

E = low to high / positive edge triggered  —-> Read

Busy Flag :  The concept of busy flag is beautiful. Now the LCD internal processor takes time to latch and make the necessary adjustments as per the command word. While the LCD’s internal processor is busy this flag is set. So one should check the status of this flag before sending the next command word or data. D7 is the busy flag pin. You’ll have to configure the port pin connected to D7 pin as input while checking the flag condition. Along with this we need to make RS = 0 and R/W = 1 , since this is read operation and busy flag is given by command code register mode.

Busy Flag = 1 —-> LCD Busy

Busy Flag = 0 —-> LCD can take next data/command

Well you can give delays also for LCD to finish work, but this is better way if you have enough port pins. Because for reading busy flag status you need R/W signal and thus a port pin.

List of LCD Instructions

commands

Using the above table you can make any command byte. For example we’ll be using this LCD in 8 bit mode so make DL = 1, N = 1 and F =0 respectively. The hexadecimal value that we get is 0x38/038h. This is the command word that we must send to the LCD to initialize it in 8 bit mode and use 2 lines with 5×7 dots.

Command Codes

So these are few of the instruction codes that you come across frequently. Of course you can make these on your own by using the command code syntax table.

DDRAM address:

Display data random access memory. This is where the data you send to data register is stored. And it so happens that you can send the address of block to the command code register to position the cursor at that particular block. For example you want to position the cursor at row 2 column 10 , just send 0CAh to the command code register. So that is about the DDRAM and positioning the cursor.

ddram

Connection Diagram:

interfacing121120131277

The connections are shown in the above pictures.

Code:

/*  8bit_lcd.h
 *  Created on: 12-Nov-2013
 *  Author: Manpreet
 */


#include <msp430g2553.h>;
#define DR		  	P2OUT = P2OUT | BIT0 		// define RS high
#define CWR		   	P2OUT = P2OUT &amp; (~BIT0)	// define RS low
#define READ     	P2OUT = P2OUT | BIT1  	// define Read signal R/W = 1 for reading
#define WRITE    	P2OUT = P2OUT &amp; (~BIT1) 	// define Write signal R/W = 0 for writing
#define ENABLE_HIGH P2OUT = P2OUT | BIT2		// define Enable high signal
#define ENABLE_LOW  P2OUT = P2OUT &amp; (~BIT2)		// define Enable Low signal
unsigned int i;
unsigned int j;
void delay(unsigned int k)
{
	for(j=0;j&lt;=k;j++)
	{
		for(i=0;i&lt;100;i++);

	}

}
void data_write(void)
{
	ENABLE_HIGH;
	delay(2);
	ENABLE_LOW;
}

void data_read(void)
{
	ENABLE_LOW;
	delay(2);
	ENABLE_HIGH;
}

void check_busy(void)
{
	P1DIR &amp;= ~(BIT7); // make P1.7 as input
	while((P1IN&amp;BIT7)==1)
	{
		data_read();
	}
	P1DIR |= BIT7;  // make P1.7 as output
}

void send_command(unsigned char cmd)
{
		check_busy();
		WRITE;
		CWR;
		P1OUT = (P1OUT &amp; 0x00)|(cmd);
		data_write();								// give enable trigger

}

void send_data(unsigned char data)
{
		check_busy();
		WRITE;
		DR;
		P1OUT = (P1OUT &amp; 0x00)|(data);
		data_write();								// give enable trigger
}

void send_string(char *s)
{
	while(*s)
	{
		send_data(*s);
		s++;
	}
}

void lcd_init(void)
{
		P2DIR |= 0xFF;
		P1DIR |= 0xFF;
		P2OUT &amp;= 0x00;
		P1OUT &amp;= 0x00;
		send_command(0x38); // 8 bit mode
		send_command(0x0E); // clear the screen
		send_command(0x01); // display on cursor on
		send_command(0x06);// increment cursor
		send_command(0x80);// cursor position
}

Sample Code

/* LCD_own.c
* Created on: 12-Nov-2013
* Author: Manpreet
* In this program we interface the lcd in 8 bit mode. We send strings and display it on the screen.
*/
#include "8bit_lcd.h"

void main(void)
{
WDTCTL = WDTPW + WDTHOLD; // stop watchdog timer
lcd_init();
send_string("Manpreet Singh");
send_command(0xC0);
send_string("Minhas");
while(1){}
}

For code explanation watch:

Output:

output

This is all regarding the 8 bit mode interfacing. I’ll be writing  about 4 bit mode and creating custom character if I successfully learn and perform the same. Thank you for reading this post. Hope it was useful and informative.

References :

The 8051 Microcontroller and Embedded Systems using Assembly and C by Mazidi (ISBN-978-81-317-1026-5)

HD44780U Datasheet (Download Link)