Universal Asynchronous Receiver/Transmitter (UART) is the most common point to point (peer) serial communication interface used in microcontrollers. It is a simple two-wire interface that requires no clock signal or any master device for serial transmission of data between two embedded devices. It can transmit data packets of variable length (5 to 9 bits) with the provision of a parity bit for error detection. That is why almost all microcontrollers have USART or at least UART peripheral built-in.
In UART communication, two devices communicate data directly with each other. This communication of data can be simplex (where one device is the receiver, and other is transmitter), full duplex (where both devices receive and transmit data to each other simultaneously) or half duplex (both devices transmit and receive data to each other but one at a time). One device having UART peripheral can communicate with another device having UART peripheral, either directly (if both devices are operating at TTL logic levels) or through a serial driver chip (if one or both devices are operating at other signal levels than TTL). The serial driver protocols have been developed to facilitate a long-range of data communication. There are three most commonly used UART serial driver protocols –
1) RS-232 – In RS-232 serial driver protocol, a voltage signal in the range from -25 V to +25V are used for data communication where -25 V to -3V signal is equivalent to HIGH logic (bit status 1) and +3 V to +25V signal is equivalent to LOW logic (bit status 0). RS-232 driver chip (like MAX232) converts these voltage levels (like from a PC) to TTL voltage levels (0 to 5V) for transmission of data to a TTL device having UART peripheral (like a microcontroller). The driver chip (like MAX-232) similarly receives bits in TTL logic levels from TTL device having UART peripheral (like a microcontroller) and convert them to RS-232 standard signal levels for transmission to the device having RS-232 interface (like PC). RS-232 allows the full-duplex point to point UART communication between two devices. RS-232 driver chip uses at least three wires (Tx, RX, and Common Ground) for interfacing with RS-232 port or interface of a device. In RS-232 protocol, one UART transmitter can communicate data only to one UART receiver.
2) RS-422 – In RS-422 serial driver protocol, voltage signal in range from -6 V to +6V are used for data communication, where -6 V to -2V signal is equivalent to HIGH logic (bit status 1) and +2 V to +6V signal is equivalent to LOW logic (bit status 0). RS-422 driver chip converts these voltage levels to TTL voltage levels (0 to 5V) for transmission to TTL device having UART peripheral. The driver chip similarly converts bits in TTL logic levels from TTL device having UART peripheral to RS-422 standard signal levels for transmission to the device having RS-422 interface. RS-422 allows full-duplex as well as half-duplex UART communication between two devices. RS-422 protocol uses differential signals (two inverted signals on two lines for transmission as well as reception of data at end device) to deliver data at long range with better signal-to-noise characteristics. So, RS-422 driver chip use at least 5 wires to connect with RS-422 port of a device (two Tx, two Rx, and common ground). In RS-422 protocol, one UART transmitter can communicate data to two UART receivers.
3) RS-485 – RS-485 is a half-duplex version of RS-422 protocol. Generally, RS-422 driver chips can also operate in RS-485 mode. In RS-485 protocol, one UART transmitter can communicate data to many UART receivers.
The devices with UART peripheral communicate data asynchronously. Instead of using any clock signal, devices with UART peripheral frame data (5bits to 9bits long) in a data packet that begins with a start bit and ends with a stop bit. When the UART receiver detects start bit, it begins fetching data packets at a pre-determined frequency called baud rate. Baud rate is expressed as bauds per second which mean data packets or words communicated per second. Ideally, two devices communicating data through UART peripherals must have the same baud rate. UART peripherals can manage a maximum 10 percent of tolerance in baud rates. An optional parity bit can be sent in the UART data packet to detect any errors in data communication. The data packets are framed as shown in the following figure by the UART devices –
Fig. 1: Format of Data Packet in UART Serial Protocol
In this project, a portable device has been designed which can read data (up to 500 bytes) from a UART transmitter and let the user inspect the transmitted data on a character LCD. The user can set baud rate, a number of data bits, parity and stop bit on the device to match with the UART transmitter. The user can tweak these parameters on the device until the correct data packets are observed on the display screen. This way, a user can identify baud rate, the number of data bits, parity and stop bit of the UART transmitter and set the same parameters at an unconfigured UART receiver.
Usually, to check the USART transmission from a microcontroller based embedded device, the Rx and Tx pins from the controller are connected to COM PORT of a PC through a serial driver chip (like MAX232 for RS-232 protocol). Then, programs like HyperTerminal are used to check the data transmission. In this method, still it is difficult to check/identify the non-printable characters on the computer screen. The device designed in this project display the read data packets on character LCD in a text, hexadecimal, decimal and octal formats for easy identification of non-printable characters. This device is also capable of communicating a fixed stream of data packets (a test string containing characters A-to-Z and digits 0-to-9) to a UART receiver to determine if the receiver device is working properly or not.
This device is designed using AVR ATMega8 microcontroller. ATMega8 has programmable Serial USART so it can easily communicate with UART or USART peripheral of any other microcontroller. ATMega8 has 512 bytes internal EEPROM which is used to fetch up to 500 bytes of serial data from a UART transmitter for inspection. A 20X4 character LCD has been interfaced with the ATMega8 to display and inspect the fetched UART data packets.
This device is intended to be used in an industrial environment, so ATMega8 has been interfaced with MAX485 serial driver chip. MAX485 is a UART serial driver chip that can be used for UART communication with devices having RS-422 or RS-485 interface. The device can also directly communicate with the USART/UART interface of a TTL device (like other microcontrollers). For reading data from devices having RS-232 interface, MAX-232 must be externally interfaced with this device.
Components Required –Â
Component Name | Quantity |
ATMega8 or ATMega8A Microcontroller IC | 1 |
MAX485 IC | 1 |
20 x 4 Character LCD | 1 |
11.0592 MHz Crystal | 1 |
5K trimpot | 1 |
3mm LEDS | 3 |
Push Button Switches | 6 |
22pF Disc Capacitors | 2 |
0.1uF Disc Capacitor | 1 |
10K ohm 0.25 W Resistors | 7 |
4.7K ohm 0.25 W Resistor | 1 |
3.3K ohm 0.25 W Resistor | 1 |
2.2K ohm 0.25 W Resistors | 2 |
470 ohm 0.25 W Resistor | 1 |
100 ohm 0.5 W Resistor | 1 |
28-pin IC Base | 1 |
8-pin IC Base | 1 |
6-pin Connector | 1 |
Berg Strip – Male | 1 |
Berg Strip – Female | 1 |
Suitable PCB | 1 |
AVR Programmer | 1 |
Circuit Diagram –Â
Fig. 2: Circuit Diagram of AVR ATmega8 based Universal UART Data Receiver and UART Tester
Circuit Connections –Â
This device is based on AVR ATMega8. ATMega8 is an 8-bit microcontroller that can operate up to 16 MIPS Throughput at 16 MHz clock. ATMega8 is interfaced with a 20X4 character LCD and MAX485 Serial Driver Chip to make the device. There is a Trimpot (Shown as VR1 in the circuit diagram) which is used to adjust the contrast of LCD. There is a Yellow LED that is interfaced parallel to the whole circuit which is used to indicate that the device is working. There is a red LED interfaced at bit 2 of Port D of Atmega8 which is used to indicate that the device is sending test data to a UART receiver. There is a white LED interfaced at bit 7 of Port D of the ATMega8 which indicates that the microcontroller is active and waiting for a menu button press by blinking.
There are 6 push button switches interfaced at Port B of ATMega8 for user input. The device can operate in two modes – 1) Menu Mode which displays baud rate, data bits, parity and stops bit and 2) View Mode which displays the fetched data packets in its buffer from a UART transmitter. The push button switches are used to change mode and operate the device in the two modes. The push buttons are interfaced at the microcontroller pins through six pull-up resistors.
The Serial Data settings and control can be operated using these six push buttons (Shown as SW1 to SW6 in the circuit diagram). The push button interfaced at bit 5 of port B (Shown as SW6 in the circuit diagram) is a toggle switch used to change between View mode and Menu mode. The Push buttons SW2, SW3, SW4 and SW5 have different functions in both the modes. The SW1 works in VIEW MODE only for sending test data to a UART receiver.
The Rx and Tx pins of ATmega8 can be used to receive data packets from any microcontroller’s USART/UART data transmission. The Rx and Tx pin of ATmega8 is also interfaced with MAX485 Serial Driver IC. MAX485 can receive UART data from any device having RS-485 or RS422 interface. The RS-485 and RS-422 are most commonly used serial communication protocols used in industries. For receiving UART data from RS-232 interface, this device needs to be externally interfaced with MAX232 IC.
The entire circuit operates on 5V DC which may obtain from 5V power bank or 9V battery with 5V regulated power supply using 7805 IC. A crystal of 11.0592 MHz frequency is used with ATmega8 to have accurate baud rate while testing.
How the circuit works –Â
After assembling the circuit, the ISP port of ATmega8 must be connected to any AVR programmer and SerialDataTester.HEX file should be flashed in the microcontroller. Then, disconnect the circuit from the AVR programmer. Now the device is ready for operation.
When the device is powered ON, the Blinker LED and RX-MODE LEDs glow for a while and LCD starts displaying the Title of the project and current USART settings. After a few seconds, the LCD displays NO DATA or BUFFER EMPTY message if there is no data received from a UART transmitter.
Now, the device can be used to test serial data from a UART transmitter or to test a UART receiver by sending sample data packets. The push buttons SW1 to SW6 can be used to navigate through View mode and Menu mode. The View mode displays the serial data received from a UART transmitter while Menu mode lets tweak the UART settings.
1) Menu mode – For testing serial data from a UART transmitter, the user first of all, needs to make UART settings in the device. The baud rate, number of data bits, parity and stop bit settings of the device should be same as of the UART transmitter to receive the data packets correctly. The expected baud rate, number of data bits, parity and stop bit must be set by navigating to the menu mode. The user can enter the menu mode by pressing SW6 button. On pressing the switch, the LCD displays the USART menu having parameters (Baud Rate, Data bits, Parity and Stop Bits) with current values. To select a parameter, the button SW4 must be pressed. The selected parameter is indicated by the blinking cursor. To change the parameter value, the button SW5 must be pressed against the selected parameter. The parameters can be set with the required values using buttons SW4 and SW5. Once the parameters are set, their values can be saved by pressing the button SW3. These values are saved permanently to internal EEPROM of the micro-controller. To change the values, if required, the user needs to once again navigate to menu mode by pressing the button SW6. The default parameter settings for baud rate, data bits, parity and stop bit are 9600, 8, 0 and 1 respectively. The user can reset to default USART settings (9600, 8, 0, 1) by pressing button SW2.
2) View Mode – It is the default mode for viewing the received serial data. To change from Menu mode to View mode, user needs to press button SW6 once again or wait for 10 seconds without operating any button. In View mode, four data packets of the received data are shown in four rows of the character LCD. Each row consists of position, character, hexadecimal code, decimal code and octal code of the serial data packet received in the buffer. If the received data packet is not a printable character, a dot is displayed in character place. The maximum size of the buffer is set to 500 bytes as ATmega8 has 512 bytes of in-built EEPROM. The total number of bytes received (in the buffer) is displayed in bottom left corner of the LCD.
In View mode, the received data packets can be scrolled up and down by pressing buttons SW5 and SW4. On pressing the button SW3, the display shows the data from the first data packet received in the buffer. If the button SW2 is pressed, the received buffer is cleared and the LCD displays “NO DATA or BUFFER EMPTY” message.
3) Testing a UART receiver – For testing a UART receiver, the user needs to press button SW1. On pressing this button, a test string containing characters A-to-Z and 0-to-9, is transmitted through Tx pin as well as A and B pins of MAX485. On pressing this switch the received buffer is also cleared for fresh data reception. The red LED glows for a short period, which is an indication for data is transmitting from micro-controller to UART receiver.
    Â
Fig. 3: Image showing Menu Mode of ATmega8 based UART Serial Data Tester
Fig. 4: Image showing View Mode of ATmega8 based UART Serial Data TesterÂ
Programming Guide-
This device is based on AVR ATmega8 and it is programmed with embedded C using AVR Studio 4. Other programming tools like Atmel Studio or Notepad++ can also be used to write and compile the code. The ATmega8 is programmed to receive UART settings from the user via push buttons and receive serial data from a UART transmitter accordingly. The received data buffer is displayed on 20X4 characters LCD where the received data packets can be scrolled up and down. ATmega8 is also programmed to test any UART receiver by sending a test string to it.
Constants used in the code-
#define F_CPU 11059200L: – Constant used to define clock frequency of the MCU
#define F_CPU_BY_100Â F_CPU/100Â :-Â Frequency divided by 100 for baud rate calculation.
#define UMS 500Â :-Â USART Message Size initialization for Array
#define LCD_P PORTCÂ Â :-Â Port C for interfacing LCD
#define LCD_EN 0b00010000Â Â :- En pin Of LCD connected to 4th pin of Port C
#define LCD_RS 0b00100000Â Â :- Rs pin of LCD connected to 5th pin of Port C
#define BTN_SW6 0b00100000Â Â :- Switch 6 connected to 5th pin of Port B
#define BTN_SW1 0b00000001Â Â :- Switch 1 connected to 0th pin of Port B
#define BTN_SWS 0b00011110Â Â :- Switch for 4 pins 2,3,4,5
#define BTN_SW5 0b00010000Â Â :- Switch 5 connected to 4th pin of Port B
#define BTN_SW4 0b00001000Â Â :- Switch 4 connected to 3rd pin of Port B
#define BTN_SW3 0b00000100Â Â :- Switch 3 connected to 2nd pin of Port B
#define BTN_SW2 0b00000010Â Â :- Switch 2 connected to 1st pin of Port B
#define TX_LÂ Â Â Â Â Â Â Â Â Â Â Â Â Â Â 0b00000100Â Â :- Tx LED connected to 2nd pin of Port D
#define TX_CÂ Â Â Â Â Â Â Â Â Â Â Â Â Â Â 0b00001000Â Â :- RX or TX mode enable at MAX485
#define BLK Â Â Â Â Â Â 0b10000000Â Â :- Blinker LED connected to 7th pin of Port D that indicate the MCU is working.
Variable used in code-
unsigned char URD[UMS+1];Â :- This Array is used to read data from USART
char USD[] = “ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789”; :-This array is used to send data on USART
char HEX[16] = {‘0′,’1′,’2′,’3′,’4′,’5′,’6′,’7′,’8′,’9’, ‘A’,’B’,’C’,’D’,’E’,’F’}; :- This array is used to convert receive data to hex
int UBRL[12]={ 3, 6, 12, 24, 48, 96, 144, 192, 288, 384, 576, 768}; // X 100 :- baud rates to change
uint8_t U_B=5;Â Â Â Â :- typedef unsigned char 8bit for baud rate
uint8_t U_D=8;Â Â Â :- typedef unsigned char 8bit for data bits
uint8_t U_P=1;Â Â Â :- typedef unsigned char 8bit for parity
uint8_t U_S=1;Â Â Â :- typedef unsigned char 8bit for Stop bit
unsigned char USART_RXD=0;Â :- variable purpose of receive data
int URDP = 0;Â Â Â Â Â Â :- For purpose of reading data from pin
int USDP = 0;Â Â Â Â Â Â :- For purpose of sending data from pin
uint8_t USCH = 1;Â Â :- for updating USART data
uint8_t VCCH = 1;Â Â :- for updating view mode
Header file and libraries used in the code –
#include <avr/io.h>Â Â Â Â Â Â Â :- Standard AVR header for input /output
#include <util/delay.h>Â Â Â Â :- Standard AVR header to provide time delays
#include <avr/interrupt.h>Â Â :- Standard AVR header for interrupts
#include <avr/eeprom.h>Â Â :- Standard AVR header for handling the data EEPROM
Function used in the code-
getString :- handle string for print on LCD
rdEÂ Â Â Â Â Â :- Read data from EEPROM
wrEÂ Â Â Â Â Â :- Write data from EEPROM
P_init    :- initializing ports for use
LCD_E   :- enable LCD’s E pin
LCD_WN :- to enable and disable RS mode
LCD_WCM :- To Wire commands
LCD_init :- To initialize LCD
LCD_WC :- Write character
LCD_WS :- Write String
LCD_CS :- To clear screen
LCD_POS :- Pause cursor
USART_init :- initialize USART
USART_SC :- To send characters
USART_SM :-To set Menu mode
ISR :- To receive data
VUSCR :- View screen setup
USART_UPD :- USART data update
USART_SD :-USART data send
USART_MN :- USART menu can be change by switch
VWL :-Â control the buffer data by switches
Algorithm:
The code for this portable UART data receiver/tester works as follow –
1) When the Serial data tester circuit is powered on , first of all , the ports are initialized that set the port B as input , Port C as output and port D’s 7 pin as output. It also pass zero bit to” TX_C, TX_L, LCD_RS, LCD_EN “ to make them LOW.
void P_init ( ) { DDRB = 0x00; DDRC = 0xFF; DDRD = 0xFE; PORTD &= (~TX_C); PORTD &= (~TX_L); LCD_P &= (~LCD_RS); LCD_P &= (~LCD_EN ); }
2)Â After initialization of Ports, the TX_L LED and BLK LED turn on for 2000 milliseconds and turn off, which indicates the program has started.
PORTD |= BLK; PORTD |= TX_L; _delay_ms ( 2000 ); PORTD &= ~BLK; PORTD &= (~TX_L);
3)Â The LCD is initialized and it prints a welcome message which is displayed to check that the LCD is working properly.
LCD_init( ); LCD_CS ( ); LCD_POS (1,1); LCD_WS ( " SERIAL DATA TESTER "); LCD_POS (2,1); LCD_WS ( "===================="); LCD_POS (3,1); LCD_WS ( "for USART & MAX485 "); LCD_POS (4,1); LCD_WS ( " communications");
4) Now it reads current EEPROM values to update the menu mode then it set up the buffer value received at USART.
_delay_ms ( 3000 ); rdE ( ); _delay_ms ( 100 ); USART_SM ( ); sei(); _delay_ms ( 2000 );
5) In a while loop, blink led is on to indicate that it is ready to work. Here, the USART data is updated and view mode is also updated on LCD. Now, the user can see the buffer data and saved serial communication data in EEPROM.
if ( USCH ) USART_UPD ( ); if ( VCCH ) { VUSCR ( ); _delay_ms ( 200 ); }
6) When switch 1 is pressed in view mode, it sends the data to USART. The user can see the data on LCD as well as on UART receiver like serial terminal of a connected PC.
if ( ( PINB & BTN_SW1 ) == 0 ) USART_SD ( );
7) When switch 6 is pressed, it displays menu mode so user can change the baud rate, data bits, parity and stop bit settings. If switch 6 is pressed again, it switches device from menu mode to view mode where the buffer data is shown.
if ( ( PINB & BTN_SW6 ) == 0 ) isMenuPressed = 1; if ( isMenuPressed ) { USART_MN ( ); LCD_WCM ( 0x0C ); } else VWL ( );
Check out the complete code and quickly start building this exciting project.
You may also like:
Project Source Code
//Program to /* filename : SerialDataTester.C author : fhn Dtd : 22-mar-2018 MCU : ATmega8 (A) @ 11.0592 MHz display ; LCD 4 rows X 20 columns others: menu driven buttons : 6 */ #define F_CPU 11059200L #define F_CPU_BY_100 F_CPU/100 #include#include #include #include #define UMS 500 #define LCD_P PORTC #define LCD_EN 0b00010000 #define LCD_RS 0b00100000 #define BTN_SW6 0b00100000 #define BTN_SW1 0b00000001 #define BTN_SWS 0b00011110 #define BTN_SW5 0b00010000 #define BTN_SW4 0b00001000 #define BTN_SW3 0b00000100 #define BTN_SW2 0b00000010 #define TX_L 0b00000100 #define TX_C 0b00001000 #define BLK 0b10000000 //============================================================================= unsigned char URD[UMS+1]; char USD[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; char HEX[16] = {'0','1','2','3','4','5','6','7','8','9', 'A','B','C','D','E','F'}; int UBRL[12]={ 3, 6, 12, 24, 48, 96, 144, 192, 288, 384, 576, 768}; // X 100 uint8_t U_B=5; uint8_t U_D=8; uint8_t U_P=1; uint8_t U_S=1; unsigned char USART_RXD=0; int URDP = 0; int USDP = 0; uint8_t USCH = 1; uint8_t VCCH = 1; //============================================================================= void getString ( long val, char *str, char fc, int width ) { long v=val,i=0; int nst=0, p=0; long hvl=1; for ( int w=0; w =1 ; i=i/10 ) { if( (v/i)>=1 && nst==0 ) nst = 1; if ( nst==1 ) { str[p++] = (v/i) + '0'; } else { str[p++] = fc; } v = v%i; } str[p]=0; if (str[p-1]==' ') { str[p-1]='0'; } } //============================================================================= void rdE ( ) { int rval = 0; rval = eeprom_read_byte ( (void *)1); if ( rval<1 || rval>2 ) return; U_S = rval; rval = eeprom_read_byte ( (void *)2); if ( rval<0 || rval>2 ) return; U_P = rval; rval = eeprom_read_byte ( (void *)3); if ( rval<5 || rval>8 ) return; U_D = rval; rval = eeprom_read_byte ( (void *)4); if ( rval<0 || rval>13 ) return; U_B = rval; } //============================================================================= void wrE ( ) { eeprom_write_byte ( (void *)1, U_S); _delay_ms(10); eeprom_write_byte ( (void *)2, U_P ); _delay_ms(10); eeprom_write_byte ( (void *)3, U_D); _delay_ms(10); eeprom_write_byte ( (void *)4, U_B);; _delay_ms(10); } //============================================================================= void P_init ( ) { DDRB = 0x00; DDRC = 0xFF; DDRD = 0xFE; PORTD &= (~TX_C); PORTD &= (~TX_L); LCD_P &= (~LCD_RS); LCD_P &= (~LCD_EN ); } //============================================================================= void LCD_E ( ) { LCD_P |= LCD_EN; _delay_us(10); LCD_P &= (~LCD_EN ); _delay_us(15); } //============================================================================= void LCD_WN ( unsigned char nibl , unsigned char RS) { LCD_P &= 0xF0; _delay_us(5); if ( nibl > 0b00001111) LCD_P |= ( (nibl>>4) & 0x0F); else LCD_P |= (nibl & 0x0F); if (RS) LCD_P |= LCD_RS; else LCD_P &= (~LCD_RS); LCD_E ( ); } //============================================================================= void LCD_WCM ( unsigned char cmd ) { LCD_WN ( cmd & 0xF0 , 0); LCD_WN ( cmd & 0x0F , 0); _delay_us(2); } //============================================================================= void LCD_init( ) { unsigned char initval = 0x20; _delay_ms ( 50 ); LCD_WN ( 0x30 , 0); _delay_ms ( 20 ); LCD_WN ( 0x30 , 0); _delay_us ( 200 ); LCD_WN ( 0x30 , 0); _delay_ms ( 100 ); LCD_WN ( 0x20 , 0 ); _delay_ms ( 25 ); initval |= 0b00001000; initval |= 0b00000100; LCD_WCM ( initval ); _delay_ms ( 25 ); LCD_WCM ( 0x0C ); _delay_ms ( 25 ); LCD_WCM ( 0x06 ); _delay_ms ( 250 ); } //============================================================================= void LCD_WC ( unsigned char c ) { LCD_WN ( c & 0xF0 , 1); LCD_WN ( c & 0x0F , 1); _delay_us(1); } //================================================= void LCD_WS ( char s[] ) { for (int i=0; s[i]!=0; i++) { LCD_WC ( s[i] ); _delay_us ( 5 ); } } //============================================================================= void LCD_CS ( ) { LCD_WCM ( 0x01 ); _delay_ms(3); } //================================================= void LCD_POS ( unsigned char R, unsigned char C ) { switch (R) { case 3: LCD_WCM ( 0x94 + C-1 ); break; case 4: LCD_WCM ( 0xD4 + C-1 ); break; case 2: LCD_WCM ( 0xC0 + C-1 ); break; case 1: default: LCD_WCM ( 0x80 + C-1 ); break; } _delay_ms ( 3 ); } //============================================================================= int USART_init ( int bd, int db, int prt, int stb) { int ubrr = 0; int bd_rate=bd; unsigned int ucsrc = (1< =0) { UBRRL = ubrr; UBRRH = (ubrr>>8); } else return (-1); UCSRB = (1< break; case 6: ucsrc |= (1< break; case 7: ucsrc |= (2< break; case 8: ucsrc |= (3< break; default: return (-1); } if (stb==2) ucsrc |= (1< getString(UBRL[U_B], str,' ', 3); LCD_WS ( str ); LCD_WS ( "00" ); LCD_POS ( 2,1 ); LCD_WS ( "DataBits : "); LCD_POS ( 2,12 ); LCD_WC ( U_D+'0'); LCD_POS ( 3,1 ); LCD_WS ( "Parity : " ); LCD_POS ( 3,12 ); switch( U_P ) { case 1: LCD_WS ( "ODD " ); break; case 2: LCD_WS ( "EVEN" ); break; default:LCD_WS ( "NONE" ); break; } LCD_POS ( 4,1 ); LCD_WS ( "StopBits : " ); LCD_POS ( 4,12 ); LCD_WC ( U_S+'0'); LCD_POS ( 1,12 ); } //============================================================================= ISR ( USART_RXC_vect ) { USART_RXD = UDR; if ( URDP < UMS ) { URD[URDP++] = USART_RXD; } } //============================================================================= void VUSCR ( ) { char str[10]; LCD_CS ( ); if ( URDP<=0) { LCD_POS (2,1); LCD_WS ( "NO DATA or" ); LCD_POS (3,1); LCD_WS ( "BUFFER EMPTY" ); return; } for ( int i=0; i<4 && URDP>(USDP+i); i++ ) { LCD_POS ( i+1 , 1 ); LCD_WC ( '@' ); getString(USDP+i, str,'0',3); LCD_WS ( str ); LCD_WS ( "= " ); if ( URD[USDP+i]<32 || URD[USDP+i]>126 ) LCD_WC ( '.' ); else LCD_WC ( URD[USDP+i] ); LCD_WC ( ' ' ); LCD_WC ( HEX[URD[USDP+i]/16] ); LCD_WC ( HEX[URD[USDP+i]%16] ); LCD_WS ( "h " ); getString(URD[USDP+i], str,'0',3); LCD_WS ( str ); LCD_WS ( "d " ); int n = URD[USDP+i]; LCD_WC ( n/64 + '0' ); n = n%64; LCD_WC ( n/8 + '0' ); LCD_WC ( n%8 + '0' ); } LCD_POS(4,1); LCD_WC ( '[' ); getString(URDP, str,'0', 3); LCD_WS ( str ); LCD_WC ( ']' ); } //============================================================================= void USART_UPD ( ) { USART_init ( UBRL[U_B], U_D, U_P, U_S ); URDP=0; USDP = 0; VCCH = 1; wrE ( ); rdE ( ); } //============================================================================= void USART_SD ( ) { LCD_CS ( ); PORTD |= BLK; LCD_POS (1,1); LCD_WS ( "SENDING.... " ); PORTD |= TX_C; PORTD |= TX_L; _delay_ms(10); LCD_POS ( 2,1 ); for ( int i=0; USD[i]!=0 ;i++) { if ( i==18 ) LCD_POS ( 3,1 ); LCD_WC ( USD[i] ); USART_SC ( USD[i] ); _delay_ms(1); } _delay_ms(50); PORTD &= (~TX_C); LCD_POS (4,1); LCD_WS ( "SENT (Check LSB)" ); _delay_ms(50); PORTD &= (~TX_L); _delay_ms(1500); VCCH = 1; } //============================================================================= void USART_MN ( ) { uint8_t wtl = 100; uint8_t btn_sws = 0; uint8_t editpos = 0; char str[10]; uint8_t sU_B = U_B; uint8_t sU_D = U_D; uint8_t sU_P = U_P; uint8_t sU_S = U_S; USART_SM ( ); _delay_ms ( 300 ); LCD_WCM ( 0x0F ); while ( wtl > 0) { PORTD ^= BLK; LCD_POS (editpos+1,12); btn_sws = PINB & BTN_SWS; if ( btn_sws != BTN_SWS) { wtl = 100; _delay_ms ( 300 ); if ( ( btn_sws & BTN_SW4 ) ==0 ) { editpos++; if (editpos>3) editpos = 0; _delay_ms ( 300 ); } else if ( ( btn_sws & BTN_SW5 ) ==0 ) { switch (editpos) { case 0: sU_B++; if (sU_B>11) sU_B=0; LCD_POS ( 1,12 ); getString(UBRL[sU_B], str, ' ', 3); LCD_WS ( str ); LCD_WS ( "00" ); break; case 1: sU_D ++; if ( sU_D>8) sU_D=5; LCD_POS ( 2,12 ); LCD_WC ( sU_D +'0' ); break; case 2: sU_P++; if ( sU_P>2) sU_P=0; LCD_POS ( 3,12 ); switch( sU_P ) { case 1: LCD_WS ( "ODD " ); break; case 2: LCD_WS ( "EVEN" ); break; default:LCD_WS ( "NONE" ); break; } break; case 3: sU_S ++; if ( sU_S>2) sU_S=1; LCD_POS ( 4,12 ); LCD_WC ( sU_S +'0' ); break; default: break; } } else if ( ( btn_sws & BTN_SW3 ) ==0 ) { U_B = sU_B; U_D = sU_D; U_P = sU_P; U_S = sU_S; USCH = 1; USART_SM ( ); LCD_POS ( 4,15 ); LCD_WS ( "SAVED" ); _delay_ms ( 2000 ); return; } else if ( ( btn_sws & BTN_SW2 ) ==0 ) { U_B = 5; U_D = 8; U_P = 1; U_S = 1; USCH = 1; USART_SM ( ); LCD_POS ( 4,15 ); LCD_WS ( "RESET" ); _delay_ms ( 2000 ); return; } } else { wtl--; } if ( ( PINB & BTN_SW6 ) == 0 ) { wtl = 0; _delay_ms ( 300 ); } _delay_ms ( 100 ); } VCCH = 1; } //============================================================================= void VWL ( ) { int btn_sws = 0; PORTD ^= BLK; btn_sws = PINB & BTN_SWS; if (( btn_sws & BTN_SW2 ) == 0 ) { URDP=0; USDP = 0; VCCH = 1; _delay_ms ( 100 ); } else if ( ( btn_sws & BTN_SW4 ) == 0 ) { USDP += 3; if ( USDP>=URDP) USDP = URDP-1; VCCH = 1; _delay_ms ( 100 ); } else if ( ( btn_sws & BTN_SW5 ) == 0 ) { USDP -= 3; if ( USDP<0) USDP = 0; VCCH = 1; _delay_ms ( 100 ); } else if ( ( btn_sws & BTN_SW3 ) == 0 ) { USDP = 0; VCCH = 1; _delay_ms ( 100 ); } } //============================================================================= int main ( ) { int isMenuPressed = 0; int usart_recd_data_pos = -1; P_init ( ); PORTD |= BLK; PORTD |= TX_L; _delay_ms ( 2000 ); PORTD &= ~BLK; PORTD &= (~TX_L); LCD_init( ); LCD_CS ( ); LCD_POS (1,1); LCD_WS ( " SERIAL DATA TESTER "); LCD_POS (2,1); LCD_WS ( "===================="); LCD_POS (3,1); LCD_WS ( "for USART & MAX485 "); LCD_POS (4,1); LCD_WS ( " communications"); _delay_ms ( 3000 ); rdE ( ); _delay_ms ( 100 ); USART_SM ( ); USCH = 1; VCCH = 1; sei(); _delay_ms ( 2000 ); while ( 1 ) { PORTD ^= BLK; if (usart_recd_data_pos != URDP) VCCH = 1; usart_recd_data_pos = URDP; if ( USCH ) USART_UPD ( ); if ( VCCH ) { VUSCR ( ); _delay_ms ( 200 ); } isMenuPressed = 0; USCH = 0; VCCH = 0; _delay_ms ( 50 ); if ( ( PINB & BTN_SW1 ) == 0 ) USART_SD ( ); if ( ( PINB & BTN_SW6 ) == 0 ) isMenuPressed = 1; if ( isMenuPressed ) { USART_MN ( ); LCD_WCM ( 0x0C ); } else VWL ( ); } return 0; } //============================================================================= ### Â
Circuit Diagrams
Project Video
Filed Under: Electronic Projects
Filed Under: Electronic Projects
Questions related to this article?
👉Ask and discuss on Electro-Tech-Online.com and EDAboard.com forums.
Tell Us What You Think!!
You must be logged in to post a comment.