Serial COM
Serial COM
Serial COM
Components Required
Hardware: ATMEGA8 (2 pieces), power supply (5v), AVR-ISP
PROGRAMMER, 100uF capacitor (connected across power
supply), 1KΩ resistor (two pieces), LED , Button.
Software: Atmel studio 6.1, progisp or flash magic.
PROGRAM ON TRANSMITTER SIDE:
#include <avr/io.h>
//header to enable data flow control over pins
#define F_CPU 1000000UL
//telling controller crystal frequency attached
#include <util/delay.h>
//header to enable delay function in program
int main(void)
{
DDRD |= 1 << PIND1;//pin1 of portD as OUTPUT
DDRD &= ~(1 << PIND0);//pin0 of portD as INPUT
PORTD |= 1 << PIND0;
//Put the upper part of the baud number here (bits 8 to 11)
UBRRH = (unsigned char) (UBBRValue >> 8);
while (1)
{
if (bit_is_clear(PINC,0))//once button is pressed
{
_delay_ms(220);
}
receiveData = UDR;
if (receiveData == 0b11110000)
{
PORTC ^= (1 << PINC0);
_delay_ms(220);
}
}
}
Yang LAEN :
Yeah, I just straight copy/pasted the code and hit compile. I'm sure it's
probably something not so subtle causing the problem, but my newbie
experience just can't point it out to me.
#include
char ReceivedByte;
UCSRB |= (1 << RXEN) | (1 << TXEN); // Turn on the transmission
and reception circuitry
UBRRH = (BAUD_PRESCALE >> 8); // Load upper 8-bits of the baud rate
value into the high byte of the UBRR register
Next, we need to tell the AVR what type of serial format we're using. The
USART can receive bytes of various sizes (from 5 to 9 bits) but for
simplicity's sake we'll use the standard 8-bits (normal byte size for the AVR).
Looking again at the MEGA16 datasheet, we can see that the bits responsible
for the serial format are named UCSZ0 to UCSZ2, and are located in the
USART control register C named UCSRC.
The datasheet very handily gives us a table showing which bits to set for
each format. The standard 8-bit format is chosen by setting the UCSZ0 and
UCSZ1 bits. Before we write to the UCSRC register however, note a curious
peculiarity in our chosen AVR, the MEGA16. To save on register addresses,
the UCSRC and UBRRH registers (the latter being explained later in this text)
share the same address. To select between the two, you must also write the
URSEL bit when writing to UCSRC:
#include
{
UCSRB = (1 << RXEN) | (1 << TXEN); // Turn on the transmission
and reception circuitry
The URSEL bit does not exist in all AVR models; check your chosen AVR's
datasheet.
There, we're almost done setting up the USART! The last thing to set for
basic serial communications is the baud rate register. This register sets the
clock divider for the USART which is used as a timebase to sample the
incoming data at the correct frequency. It also gives the timebase for
sending data, so it's vital for RS-232 serial communications.
The baud rate register is 16-bit, split into two 8-bit registers as is the case
with all 16-bit registers in the AVR device family. To set our baud rate
prescaler value, we first need to determine it. Note that the baud rate
register value is NOT the same as the baud rate you wish to use - this is a
common point of failure amongst those new to the serial subsystem. Instead,
the value must be derived from the following formula:
BaudValue = (((F_CPU / (USART_BAUDRATE * 16))) - 1)
Where F_CPU is your AVR's system clock frequency (in Hz), and
USART_BAUDRATE is the desired communication baud rate.
Given my example project using a system clock of 7372800Hz and a baud
rate of 9600, our formula gives:
BaudValue = (((F_CPU / (USART_BAUDRATE * 16UL))) - 1) BaudValue =
(7372800 / (9600 * 16) - 1)
BaudValue = (7372800 / 153600 - 1)
BaudValue = (48 - 1)
BaudValue = 47
To make our life easier, we can turn this formula into a set of handy macros.
F_CPU is automatically defined in AVR-GCC via your makefile, so all that is
needed is the baud rate:
#define USART_BAUDRATE 9600
UBRRL = BAUD_PRESCALE; // Load lower 8-bits of the baud rate value into
the low byte of the UBRR register
However this is non-optimal. We spend time waiting after each byte which
could be better spent performing other tasks - better to check before a
transmission to see if the UDR register is ready for data. We can do this by
checking the USART Data Register Empty flag instead (called UDRE), also
located in the UCSRA control register of the MEGA16:
while ((UCSRA & (1 << UDRE)) == 0) {}; // Do nothing until UDR is ready
for more data to be written to it
This is much better, as now time is only wasted before a transmission if the
UDR register is full. After a transmission we can immediately continue
program execution while the UDR byte is sent, saving time.
Now we can move on to receiving data. As mentioned before, the UDR
register behaves differently between read and write operations. If data is
written to it it is sent out via the AVR's Tx pin, however when data is
received by the RX pin of the AVR, it may be read out of the UDR register.
Before reading the UDR register however, we need to check to see if we have
received a byte.
To do this, we can check the USART Receive Complete (RXC) flag to see if it
is set. Again, this is located in the UCSRA control register of the MEGA16:
while ((UCSRA & (1 << RXC)) == 0) {}; // Do nothing until data have
been received and is ready to be read from UDR
ReceivedByte = UDR; // Fetch the received byte value into the variable
"ReceivedByte"
And some echo code to complete our example. We'll add in a local variable
"ReceivedByte", which will always hold the last received character from the
computer:
#include
char ReceivedByte;
UCSRB = (1 << RXEN) | (1 << TXEN); // Turn on the transmission
and reception circuitry
And voila, we have a working serial example! Connect to this project via a
serial terminal on your computer, using 8-bit, no parity 9600 baud
communication settings and it will echo back anything you send to it.
Potential Pitfalls
There are several "gotchas" when dealing with the USART. First, make sure
your AVR is running of a reliable, known clock source with a low error
percentage at your chosen baud rate. New AVRs default to their internal
oscillators until their fuses are changed. The internal RC oscillator is of
too low a tolerance for use with the USART without external
calibration.
Check your datasheet to check for the locations of the different flags.
Different AVRs have the control flags located in different control registers
(UCSRA, UCSRB and UCSRC).
Make sure your computer terminal is connected at the exact settings your
AVR application is designed for. Different settings will cause corrupt data.
Cross your Rx and Tx wires. Your PC's Rx line should be connected to your
AVR's Tx line and vice-versa. This is because the Rx/Tx lines are labeled
relative to the device they are marked on.
Some AVRs do not have the URSEL bit to differentiate between the UCSRC
and UBRRH registers - check your datasheet.
Advanced serial communication
A more advanced method of serial communication involves the use of the
USART interrupts and is not covered here. I may cover it in a later tutorial if
so desired.
For an updated version of this tutorial in PDF format, please see this
page of my website.
- Dean :twisted:
Ini lagi:
#include <avr/io.h>
void ConfigureDevice(void)
UBRRH = (BAUD_PRESCALE >> 8); // Load upper 8-bits of the baud rate
value into the high byte of the UBRR register
ConfigureDevice();
char ReceivedByte;
if (ReceivedByte == 83) {
// do something here
hi Dean
about your previous reply :"The demo application just echoes back the sent
bytes, so all you need is a terminal application on your computer which can
send and receive serial data."
to confirm with you, the sent bytes is it any data to be sent from micro
controller to the computer?
after building the code that you have written, where should i add or write in
your code to send or receive data? is it after this line?
while ((UCSRA & (1 << RXC)) == 0) {};
ReceivedByte = UDR;
//add function or data to send to computer?
i not really too sure what i have asked is it clear or not, but i guess i am
confused by what i should write to send data to computer...
so can you help me with this, from your code, what else must i write or add,
for an example to send and receive data, to your code?
#include
#define USART_BAUDRATE 9600
#define BAUD_PRESCALE (((F_CPU / (USART_BAUDRATE * 16UL))) - 1)
int main (void)
{
char ReceivedByte;
UCSRB |= (1 << RXEN) | (1 << TXEN); // Turn on the transmission and
reception circuitry
UCSRC |= (1 << URSEL) | (1 << UCSZ0) | (1 << UCSZ1); // Use 8-bit
character sizes
UBRRL = BAUD_PRESCALE; // Load lower 8-bits of the baud rate value into
the low byte of the UBRR register
UBRRH = (BAUD_PRESCALE >> 8); // Load upper 8-bits of the baud rate
value
for (;;) // Loop forever
{
while ((UCSRA & (1 << RXC)) == 0) {}; // Do nothing until data have been
recieved and is ready to be read from UDR
ReceivedByte = UDR; // Fetch the recieved byte value into the variable
"ByteReceived"
//???add or write code at this line to send data???
while ((UCSRA & (1 << UDRE)) == 0) {}; // Do nothing until UDR is ready
for more data to be written to it
UDR = ReceivedByte; // Echo back the received byte back to the computer
//???add or write code at theis line to receive data???
}
}
i hope to hear from you and learn more about it... so do correct me...
thanks...
lewaltz
hi Dean
sorry i was having my examinations during this few weeks and now i am
focusing on the programming for my project...
i wanted to canofirm with you about the code that i have tried out but it
turns out to be nothing... chould you help me to check if there is any error in
my code?
i want transmit a char "S" from computer so that when (ReceivedByte ==
"S") it will turn off my LED (PORTC)
here is the code...
int main (void)
char ReceivedByte;
// Configure Device
UCSRB |= (1 << RXEN) | (1 << TXEN); // Turn on the transmission and reception circuitry
UCSRC |= (1 << URSEL) | (1 << UCSZ0) | (1 << UCSZ1); // Use 8-bit character sizes
UBRRL = BAUD_PRESCALE; // Load lower 8-bits of the baud rate value into the low byte of the UBRR register
UBRRH = (BAUD_PRESCALE >> 8); // Load upper 8-bits of the baud rate value
while ((UCSRA & (1 << RXC)) == 0) {}; // Do nothing until data have been recieved and is ready to be read from
UDR
ReceivedByte = UDR; // Fetch the recieved byte value into the variable "ByteReceived"
UDR = "S";
PORTC = 0x00;
#include
#include
/* Prototypes */
void USART0_Init( unsigned int baudrate );
unsigned char USART0_Receive( void );
void USART0_Transmit ( unsigned char data );
/* Initialize UART */
void USART0_Init(void)
{
/* Set the baud rate */
UBRRL = 0x19;
//I use 4 MHz crystal, and I want the baudrate to be
//9600, and then the UBRR should be 25, am I right?
UBRRH = 0x00;
/* Enable UART receiver and transmitter */
UCSRB = ( ( 1 << RXEN ) | ( 1 << TXEN ) );
/* Set frame format: 8 data 2stop */
UCSRC = (1<<URSEL)|(1<<UCSZ1)|(1<<UCSZ0);
}
/* Read and write functions */
unsigned char USART0_Receive( void )
{
while ( !(UCSRA & (1<<RXC)) );
return UDR;
}
void USART0_Transmit ( unsigned char data )
{
while ( !(UCSRA & (1<<UDRE)) );
UDR = data;
}
void port_init(void)
{
PORTA = 0x00;
DDRA = 0x00;
PORTB = 0x00;
DDRB = 0x00;
PORTC = 0x00;
DDRC = 0x00;
PORTD = 0x00;
DDRD = 0x02;
}
//call this routine to initialize all peripherals
void init_devices(void)
{
//stop errant interrupts until set up
CLI(); //disable all interrupts
port_init();
USART0_Init();
MCUCR= 0x00;
TIMSK= 0x02; //timer interrupt sources
GICR= 0x00;
SEI(); //re-enable interrupts
//all peripherals are now initialized
}
//
void main(void)
{
init_devices();
for(;;)
{
USART0_Transmit ('a');
while(1);
}
}
from the code above, the problem is that the data received at the PC is
wrong. what could possibly the the cause of this problem? I thought the
MAX232 i used was damaged, so I've replaced it with a new one, and there
are no mistakes with hardware connection. Thanks a lot.
#include
#include
#ifndef F_CPU
#define F_CPU 8000000
#endif
#define BAUDRATE 9600
#define UBRRVAL ((F_CPU/(BAUDRATE*16UL))-1)
int main (void)
{
char ReceivedByte;
DDRD = 0b01111111; //7 0
PORTD = 0b00000000;
UCSR1B |= (1 << RXEN1) | (1 << TXEN1); // Turn on the transmission and
reception circuitry
UBRR1L=UBRRVAL; //low byte
UBRR1H=(UBRRVAL>>8); //high byte
// sei(); // Enable the Global Interrupt Enable flag so that interrupts can be
processed
for (;;) // Loop forever
{
// while ((UCSR1A & (1 << RXC1)) == 0) {}; // Do nothing until data have
been recieved and is ready to be read from UDR
// ReceivedByte = UDR1; // Fetch the recieved byte value into the variable
"ByteReceived"
ReceivedByte = 'U';
while ((UCSR1A & (1 << UDRE1)) == 0) {}; // Do nothing until UDR is
ready for more data to be written to it
UDR1 = ReceivedByte; // Echo back the received byte back to the computer
}
}
/*
ISR(USART_RXC_vect)
{
char ReceivedByte;
ReceivedByte = UDR1; // Fetch the recieved byte value into the variable
"ByteReceived"
UDR1 = ReceivedByte; // Echo back the received byte back to the computer
}
*/
thatsthe code used atm, the reason i loop a 'U' out is simpel, clawson
sugested use a 'U' becouse that will measure 2,5volt avg on the avrs TXD.
Useing no codeline to set bits parity stopbits, im told skipping this leavs the
default 8n1
i have connected the avrs TXD to a max232 pin 10, wich is TTL input, still
measure 2.5volt
onmax 232 pin 7 i measure 0,14 volt wich is correct, its the avg of rs232
signal low and high (-9 and +9)
so it all seems to work, still when i connect it to my PCs serialport pin ground
and RXD my hyperterminal set to 8n1 do not output 'U' endlesly, nutting att
all happends
HELP!
#include
#include
char ReceivedByte;
UBRR0H = (BAUD_PRESCALE >> 8); // Load upper 8-bits of the baud rate
value into the high byte of the UBRR register
#include
#include
char ReceivedByte;
UBRR0L = BAUD_PRESCALE; // Load lower 8-bits of the baud rate value
into the low byte of the UBRR register
UBRR0H = (BAUD_PRESCALE >> 8); // Load upper 8-bits of the baud rate
value into the high byte of the UBRR register
#define LED 0
#define LED2 6
//tranmission led
//power led
#include
#include
//UBRRH = 0;
UBRRL = baud;
UDR = data;
return UDR;
void portInit() {
// PORTC = 0xFF;
DDRC = 0xFF;
int main(void){
asm("cli");
portInit();
_delay_ms(100);
rsInit(BAUDRATE);
LED2_ON();
bytes[0]=0x30;
bytes[2]=0x40;
bytes[3]=0x42;
bytes[4]=0xFF;
bytes[5]=0x48;
bytes[6]=0x40;
bytes[7]=0x60;
bytes[8]=0x70;
bytes[9]=0x80;
bytes[10]=0xF0;
bytes[11]=0xF0;
bytes[12]=0xF0;
bytes[13]=0xFA;
bytes[14]=0xFA;
bytes[15]=0xFA;
while(1){
for(i=0;i<16;i++){
rsSend(bytes[i]);
LED_ON();
_delay_ms(250);
LED_OFF();
_delay_ms(250);
_delay_ms(250);
_delay_ms(250);
return 0;
}
I am setting in Putty at the PC side 8bits,no parity,1 stop, no flow control,
checked also with Xon/Xoff. Sometimes it throws on my screen series of '
and |
Hallo All.
It is great that you spent time to make this great tutorial........thanks alot.
I want to make the mega16 responde to a command I will send from a
program made i C# from the pc over a serial rs232 line and use the modbus
protocol.
but right now I trying to send a string to the pc. I only works in JTAG mode
and is printing some strange charters like(!,,\)
in runtime mode it prints (X on pc if I enter a (0xE1). I checked the hex
value and it is A8F8
I dont understand why it do not print at least 5 charters.
can anybody help me???. and a sample code with the modbus implemented
would be perfect. see code below
#include
#include "stdlib.h"
#include "string.h"
#include "stdio.h"
int main ()
int ReceivedByte;
UBRRH = (BAUD_PRESCALE >> 8); // Load upper 8-bits of the baud rate
value into the high byte of the UBRR register
if ( ReceivedByte==0xED)
{UDR = 0xEC;
if ( ReceivedByte==0xE1)
USART_Tx(*StringPtr);
StringPtr++;
#include
UCSRB = (1<<RXEN)|(1<<TXEN);
UDR = data;
}
while(*str)
USART_Transmit(*str++);
return UDR;
USART_Init(baud);
int x;
DDRA=0xff;
PORTA=0xff;//Encendido
USART_Putstring("ATD 636725862");
PORTA=0x00;//Apagado
#include
char ReceivedByte;
int i=0;
UBRRH = (BAUD_PRESCALE >> 8); // Load upper 8-bits of the baud rate
value into the high byte of the UBRR register
in hyperterminal , I get the output abcdefghi , but after that , any characters
that I type are ignored and are not echoed back.
I've tested loopback using a wire , and it works fine for all baud rates ,
databits,parity , etc.
I've been trying to solve this for the last 2 days , and i'm at my wits end now
.. :(
hope you could guide me in the right direction.
Hi there,
all is fine so far but how can one write texts of strings of characters and
display them on a screen.
is it?
Output the following please:
"Hello world"
or is it
printf "hello world"
etc.?
I tried this recipe:
#include
#include
#include
#include
#define F 4000000 /* oscillator-frequency
in Hz */
#define UART_BAUD_RATE 9600
#define UART_BAUD_CALC(UART_BAUD_RATE,FC)
(F/(UART_BAUD_RATE*16l)-1)
size_t strlen (const char*);
void usart_putc(unsigned char c) {
// wait until UDR ready
while(!(UCSRA & (1 << UDRE)));
UDR = c; // send character
}
void uart_puts (char *s) {
// loop until *s != NULL
while (*s) {
usart_putc(*s);
s++;
}
}
char *str1 = "Hallo World!";
char s [7];
int16_t i=0x40;
void init(void) {
// set baud rate
UBRRH = (uint8_t)(UART_BAUD_CALC(UART_BAUD_RATE,F)>>8);
UBRRL = (uint8_t)UART_BAUD_CALC(UART_BAUD_RATE,F);
// Enable receiver and transmitter; enable RX interrupt
UCSRB = (1 << RXEN) | (1 << TXEN) | (1 << RXCIE);
//UCSRB = (1<<
//asynchronous 8N1
UCSRC = (1 << URSEL) | (3 << UCSZ0);
}
int main(void) {
init(); // init USART
//sei(); // enable interrupts
// send initial character
while (!(UCSRA & (1 << UDRE)));
itoa(i,s,10);
uart_puts(s);
return 0;
}
But i get the number 64 on the screen.
How, what, where should I write to get "hello world"?
Thanks
Hi Cliff,
Thanks for your Hints. Now i am able to remove all the errors. But the
program is not working.
I want to transmit 'a' on UART0. I am using ATmega128 & AVR Studio4. I
don't get pulses at TXD0 pin on C.R.O.
Program control is remaining in -- " while (!(UCSR0A & (1 << UDRE0)) ) {};
" loop continuously.
What could be the problem?
#include
#include
#include
#include
#include
#define FOSC 18432000// Clock Speed
#define BAUD 115200
#define MYUBRR FOSC/16/BAUD-1
//unsigned char buf[];
void usart_init(void);
void usart_Tx(unsigned char data);
unsigned char usart_Rx(void);
int main( void )
{
unsigned char *data,ptr[]="string to send",c;
data=ptr;
usart_init();
while(*data){
c=*data;
usart_Tx(c);
data++;}
while(1){
c =usart_Rx();
usart_Tx(c);}
return 0;
}
void usart_init( void )
{
unsigned int ubrr=MYUBRR;
printf("%d",ubrr);
UBRR0H = (unsigned char)(ubrr>>8); /* Set baud rate */
UBRR0L = (unsigned char)ubrr;
/* Enable receiver and transmitter */
UCSR0B |= (1<<RXEN0)|(1<<TXEN0);
/* Set frame format: 8data, 2stop bit */
UCSR0C = 0x06;
/*Disabling the interrrupts*/
}
void usart_Tx( unsigned char data )
{
/* Wait for empty transmit buffer */
while ( !( UCSR0A & (1<<UDRE)) );
/* Put data into buffer, sends the data */
UDR0 = data;
printf("%c",data);
}
unsigned char usart_Rx( void )
{
/* Wait for data to be received */
while ( !(UCSR0A & (1<<RXC0)) );
/* Get and return received data from buffer */
return UDR0;
}
i have written a program for send info from atmega 64 to hyper terminal and from
hyperterminal to atmega64. but it is displying junk values even i have selected
115200,8,none,1,flow control also none.wt is the proble could u tell me please.
Hi. I'm using an ATMega8 with a 16 MHz external crystal. I set the
SUT_CKSEL to Ext. Crystal/Resonator High Freq. and I can get the tutorial
code to work. It echos back the keys I hit. Now, I'm trying to get the value of
OCR1A sent to the terminal. All I get though, is a repeating
ZZZZZZZZZZZZZZZ. Any ideas?
#include
#include
#include
int i;
UDR = c[i];
{
char buff[4];
ICR1 = 40000;
TCCR1B |= (1<<WGM13)|(1<<WGM12)|(1<<CS11);
UBRRL = 103;
while(1)
for(OCR1A=2000;OCR1A<=4000;OCR1A++){
_delay_ms(1);
itoa(OCR1A,buff,10);
sendStream(buff,4);
for(OCR1A=4000;OCR1A>=2000;OCR1A--){
_delay_ms(1);
itoa(OCR1A,buff,10);
sendStream(buff,4);
}
#include
#include
#include
#include
int main(void)
char recieveddata;
/* Enable Rx and Tx */
while (1);{
recieveddata = UDR;
/* Add 1 to the last recieved byte and transmit it back */
Hi Cliff, thanks for having the patience to reply to my basic newbie questions!
I have tried 9600 but I received nothing on HyperT as well(with everything
on HyperT setup correctly, flow control-NONE).
Well, I am using a prescalar to get 2Mhz but the OSCCAL option that you
suggested is a bit too complicated for me to understand so I think I would
like to opt that out.
I am not sure if it is the problem with my code. I tried using synchonise
mode before but I couldn’t see any waveforms coming out on the
oscilloscope. So I modified my code to make it async. I don’t know if
there’s something I missed out during this modification – I changed the
register, added in SREG |=(1<<7) to enable interrupt as told on the
datasheet so that I can use Rx, Tx, Empty enables/flag enables. I am not
sure if I need any XCK clock settings for this so I omitted that. Can you spot
any mistakes in doing this?
void Setup_USART_As_SPI(void)
UCSR0B =
USART_CSR_B_Receive_Interrupt_EN |
USART_CSR_B_Transmit_Interrupt_EN |
USART_CSR_B_Data_Register_Empty_EN |
0;
UCSR0B &= ~(
USART_CSR_B_Receiver_EN |
USART_CSR_B_Transmitter_EN
);
UBRR0 = 0;
UCSR0C =
USART_CSR_C_Master_SPI |
USART_CSR_C_CLK_Phase_Falling |
0;
//USART_CSR_C_CLK_Polarity_High |
//USART_CSR_C_MSB_Last |
UCSR0B |= (
USART_CSR_B_Receiver_EN |
USART_CSR_B_Transmitter_EN
);
};
void Setup_Usart(void)
UCSR1B &=
~(
USART_CSR_B_Receiver_EN |
USART_CSR_B_Transmitter_EN
);
//set the Control status register B
UCSR1B =
0;
UCSR1C =
USART_CSR_C_USART_NumStopBits(1) |
USART_CSR_C_USART_Parity_None |
USART_CSR_C_USART_ModeSelect_ASync |
USART_CSR_C_USART_CharSize_Max8(8) |
0;
UCSR1B |=
USART_CSR_B_Receiver_EN |
USART_CSR_B_Transmitter_EN |
USART_CSR_B_Data_Register_Interrupt_Empty_EN
);
};
void USARTSPI_ReadADS1252(void)
//do nothing
};
_delay_us ( 4);
//PORTC0 = 0
PORTC ^= (1);
//flush adc
UDR0= 0;
//Wait till you've received 8 bits
Data[2] = UDR0;
//flush register
UDR0 = 0;
Data[1] = UDR0;
//flush register
UDR0 = 0;
Data[0] = UDR0;
void USART_RS232_Interfacing(void)
if ( Loop == 0 )
ToUsart1[0] = Data[0];
ToUsart1[1] = Data[1];
ToUsart1[2] = Data[2];
int streamLoc = 0;
UDR1 = ToUsart1[streamLoc];
streamLoc++;
}
};
Right thanks. I wil try that later as I just found some other errors on my
system.
With my ADC reading, I got nice and expected waveforms on oscilloscope.
This is roughly how my code looks like.
void USARTSPI_ReadADS1252(void)
//do nothing
};
_delay_us ( 4);
//PORTC0 = 0
PORTC ^= (1);
UDR0= 0;
Data[2] = UDR0;
UDR0 = 0;
Data[1] = UDR0;
UDR0 = 0;
}
Data[0] = UDR0;
void USART_RS232_Interfacing(void)
if ( Loop == 0 )
ToUsart1[0] = Data[0];
ToUsart1[1] = Data[1];
ToUsart1[2] = Data[2];
int streamLoc = 0;
{
// Do nothing until UDR is ready for more data to be
written to it by checking register empty flag
UDR1 = ToUsart1[streamLoc];
streamLoc++;
};
Both these adc read and rs232 functions are included in an infinite loop.
Please advice. Thanks!
Hello
Can anybody just have a look in my code to find the bug.
I try to transmit 8 bytes in the shape of a char[9] from one atmega164p to
another using usart.
I know the baud settings are correct because one byte works fine to
transmit, several bytes not.
Sender side:
char output[9];
void USART_vInit(void)
{
// Set baud rate
UBRR1H = (uint8_t)(USART_UBBR_VALUE>>8);
UBRR1L = (uint8_t)USART_UBBR_VALUE;
// Set frame format to 8 data bits, no parity, 2 stop bit
UCSR1C = (1<<USBS1)|(3<<UCSZ10);
// Enable receiver and transmitter
UCSR1B = (1<<RXEN1)|(1<<TXEN1);
}
void usart_send_string(char * str) {
while (*str) { // keep going until NULL terminator found
usart_send_char(*str++);
}
}
void usart_send_char(uint8_t byte) {
while ((UCSR1A & (1 << UDRE1)) == 0);
UDR1 = byte;
}
int main()
{
USART_vInit();
while(1)
{
output[0] = 2;
output[1] = 4;
output[2] = 6;
output[3] = 8;
output[4] = 10;
output[5] = 12;
output[6] = 14;
output[7] = 16;
usart_send_string(output);
}
}
Receiver side:
char input[9];
void USART_vReceiveByte()
{
int temp = 0;
while (UDR1 != '\0')
{
// Wait until a byte has been received
while((UCSR1A&(1<<RXC1)) == 0) ;
// Return received data
input[temp] =UDR1;
temp ++;
}
return 1;
}
void USART_vInit(void)
{
// Set baud rate
UBRR1H = (uint8_t)(USART_UBBR_VALUE>>8);
UBRR1L = (uint8_t)USART_UBBR_VALUE;
// Set frame format to 8 data bits, no parity, 2 stop bit
UCSR1C = (1<<USBS1)|(3<<UCSZ10);
// Enable receiver and transmitter
UCSR1B = (1<<RXEN1)|(1<<TXEN1);
}
int main(void)
{
DDRB = 0xFF; // port B output
PORTB = 0x00;
// Initialise USART
USART_vInit();
for(;;)
{
USART_vReceiveByte();
PORTB = input[0];
}
}
Using AVRstudio with Gcc and JTAG MKII
Please help :)
[NOTE: I originally posted this in AVR-GCC, but then browsing the tutorials
found this thread and thought it significantly more relevant. Apologies for the
double post]
Hello,
I have been following the sparkfun "Beginning Embedded Electronics" as well
as this thread tutorial and have overall been successful. I can read adn write
bytes at a time and have no problem receiving/sending from the terminal.
Unfortunately, when I output a chunk of data from the AVR rapidly (say 10
bytes) the code continually finds something to read and loops even though I
do not send it any data. If however, I place a delay in the putchar function of
"5ms" (according to the code - completely uncalibrated obviously) the code
works as advertised.
It seems like something is getting out of sync and my send is clobbering my
receive.
The question: what is going on and how do I get things to work properly with
out the artificial delay?
I am a software engineer by trade trying to learn about microprocessors, so
the hardware side is all new to me (read: ripe for newbie errors). Thinking
this might have had something to do with buffered IO (i.e. stdio.h) I rewrote
printf, etc, but I got the same exact behavior. It seems that when I output a
certain amount of data quickly the chip seems to set the flag that there is
data available. When I print out the UCSR0A, I see that the DOR0 bit is set.
May be relevant?
Anyway, I reverted back to the sparkfun code in order to keep things simple
for debugging. For reference, here is the tutorial:
http://www.sparkfun.com/commerce/tutorial_info.php?tutorials_id=105
and here is the link to the tutorial code (my code is below)
http://www.sparkfun.com/tutorial/BeginningEmbedded/5-Compiling/basic-in-
atmega168.zip
I am using:
avr-gcc 4.0.2
atmega168
16 Mhz crystal
fuse set correctly ( 0xE6 )
avrdude 5.5
ispmkii programmer
USB BUB for usb->serial communication (also tried a FTDI cable)
Mac OSX with zterm and screen (tried both)
9600 Baud (in code and terminal)
Anything else that would be useful to know?
Here is the code:
/*
5-10-07
Nathan Seidle
nathan at sparkfun.com
*/
#include
#include
#define STATUS_LED 0
//Define functions
//======================
uint8_t uart_getchar(void);
static FILE mystdout = FDEV_SETUP_STREAM(uart_putchar, NULL,
_FDEV_SETUP_WRITE);
//======================
uint8_t key_press;
while(1)
key_press = uart_getchar();
return(0);
}
UBRR0L = MYUBRR;
UCSR0B = (1<<RXEN0)|(1<<TXEN0);
delay_ms(5);
loop_until_bit_is_set(UCSR0A, UDRE0);
UDR0 = c;
return 0;
uint8_t uart_getchar(void)
return(UDR0);
void delay_ms(uint16_t x)
uint8_t y, z;
hi all
i debugged USART register via simulator which integrated AVRstudio.I fould
the strange of register like that. i dont know why.
ubrr=F_CPU/16/baudrate-1;
//UBRR0H=0;
//UBRR0L=0x33 (51)
UCSR0B = (1<<RXEN)|(1<<TXEN);
UCSR0C = (0<<USBS)|(3<<UCSZ0);
*/
#include
#include
int main(void)
while (1){
PORTA = 0xFF;
UDR = 'T';
UDR = '^';
UDR = 'S';
UDR = 'M';
UDR = 'S';
UDR = 'O';
PORTA = 0x00;}
return 0;
#include
UCSR0B = (1<<RXEN0)|(1<<TXEN0)|(0<<RXCIE0)|(0<<UDRIE0);
UDR0 = data;
char Usart_Rx(void)
{
return UDR0;
int main(void)
char c;
c=Usart_Rx();
Usart_Tx(c);
return 0;
I have followed this thread from page 1. It's been a great learning
experience to see the potential pitfalls before I actually started to try using
the USART feature of my AVR. I do have a problem that I haven't figured out
yet. Maybe someone might see something that I am not seeing. Transmitting
one character results in a different character being received. The received
character does not change unless the transmitted character is changed. I'm
sure this has to be a timing issue of some sort.
My board uses a 16.000MHz crystal. This AVR has no internal oscillator.
Pages 36-44 in the ATMega128 reference manual describe clock divisors and
such, but none are programmed in my case. The JTAG connector is removed
after programming so as not to interfere with the USART operation.
All I am attempting to do is get my AVR to communicate like a loopback
connector to HyperTerminal in Windows. I am using an ATMega128 (MAVRIC
IIb board) with an Atmel JTAGICE MKII programmer. The code used is based
on the examples provided in this thread. I believe the registers are correctly
adjusted for the ATMega128.
There is a DB9 connector attached to the AVR as follows:
DB9 Pinout
Pin 2 (RD) to TX0 of AVR
Pin 3 (TD) to RX0 of AVR
Pins 4-6 (DTR-DSR)
Pin 5 (GND) to GND of AVR
Pins 7-8 (RTS-CTS)
HyperTerminal and the USB COM Port of my PC are configured to 38400
baud, 8N1 (8 bits / No Parity / 1 Stop bit).
When pin 2 and 3 of the USB COM Port are connected together in a loop-
back fashion, the characters typed do echo back.
From HyperTerminal, in a full loopback form using the AVR as the loopback:
When 'f' is sent, '6' is looped back.
Then if I program the AVR as transmit only to HyperTerminal:
When '0' (zero) is sent, the omega character is returned.
The code shown has the receive section removed for now until I know I can
reliably transmit a character from the AVR to HyperTerminal.
#include
// Defines / Declarations
// char ReceivedByte;
// {
// };
// ReceivedByte = UDR0;
};
Hello everyone,
I am using the atmega8515 and can open up brays terminal and I believe
everything is working fine. My questions are when i send a phrase like hello,
it echoes it back, but when i check the hex that is being sent it doesn't match
up with the ascii? my second question is why can i only open it up in brays
terminal and not in hyper terminal.
#include
char ReceivedByte;
UBRRL = BAUD_PRESCALE;
for(;;)
}
}
why is the following code not transmitting any data through ATMEGA2560 -
STK600......suggest me any changes
frequency : 16000000hz
baud :9600
PIN0 OF PORTE is connected to TXD pin of stk600
PIN1 OF PORTE is connected to RXD pin of stk600
suggest me any further changes required...
code:
Code:
//=====================================================================
=============================//
//=====================================================================
=============================//
//unsigned char t;
//*********************************************************************
*****************************//
// MAIN PROGRAM
//
//*********************************************************************
*****************************//
for(;;)
m='A';
UDR0 =m;
_delay_ms(1);
//transmit(m);
}
}
///////////////////////////////////////////////////////////////////////
///////////////////////////////
///////////////////////////////////////////////////////////////////////
///////////////////////////////
UCSR0C =
(0<<UMSEL01)|(0<<UMSEL00)|(0<<USBS0)|(1<<UCSZ00)|(1<<UCSZ01)|(0<<UCSZ02
);//SETTING THE FRAME FORMAT WITH 8 DATA AND 1 STOP BITS
UCSR0A = (1<<UDRE0);
}
///////////////////////////////////////////////////////////////////////
///////////////////////////////
///////////////////////////////////////////////////////////////////////
///////////////////////////////
UDR0 = data;
}*/
Communication between two entities is important for the information flow to take
place. In general the information transport system can be parallel in which the
complete byte of data is sent at a time, with each bit having a separate dedicated
line or it can be serial where only one communication line is available which is
shared by all the bits sequentially. The pros and cons of these two systems are
Data can be exchanged using parallel or serial techniques. Setup for parallel data
transfer is not cost effective but is a very fast method of communication. Serial
PC. The data is transmitted from the controller using RS232 standard and displayed
iii. Full duplex: Transmission can be done in both the direction simultaneously.
transmitter):
Baud Rate: In simple words baud rate is the rate at which serial data is being
transferred.
Atmega16 USART has following features:
· Different Baud Rates.
· Variable data size with options ranging from 5bits to 9bits.
· One or two stop bits.
· Hardware generated parity check.
· USART can be configured to operate in synchronous mode.
· Three separate interrupts for RX Complete, TX complete and TX data register
empty.
USART Registers
UCSR: USART control and status register. It’s is basically divided into three parts
UCSRA, UCSRB and UCSRC. These registers are basically used to configure the
USART.
UBRR: USART Baud Rate Registers. Basically use to set the baud rate of USART
UDR: USART data register
RXC (USART Receive Complete): RXC flag is set to 1 if unread data exists in
receive buffer, and set to 0 if receive buffer is empty.
TXC (USART Transmit complete): TXC flag is set to 1 when data is completely
transmitted to Transmit shift register and no data is present in the buffer register
UDR.
UDRE (USART Data Register Empty): This flag is set to logic 1 when the transmit
buffer is empty, indicating it is ready to receive new data. UDRE bit is cleared by
writing to the UDR register.
ii. UCSRB: (USART Control and Status Register B)
The USART Data receive and data transmit buffer registers share the same address
referred as USART UDR register, when data is written to the register it is written in
transmit data buffer register (TXB). Received data is read from the Receive data
buffer register (RXB).
The UBRRH register shares the same I/O address with the UCSRC register, The
differentiation is done on the basis of value of URSEL bit.
When URSEL=0; write operation is done on UBRRH register.
When URSEL=1; write operation is done on UCSRC register.
The UBRRH and UBRRL register together stores the 12-bit value of baud rate,
UBRRH contains the 4 most significant bits and UBRRL contains the other 8 least
significant bits. Baud rates of the transmitting and receiving bodies must match for
successful communication to take place.
Code Explanation:
Step 1: First step is to select the Baud rate. Baud rate of two devices must match or
else they will not be able to synchronize with each other.
#define USART_BAUDRATE 9600
Step2: To set a particular Baud Rate in ATmega16, write the corresponding UDRR
value. The UDRR value is calculated by using the formula
#define BAUD_PRESCALE (((F_CPU / (USART_BAUDRATE * 16UL))) - 1)
UCSRB |= (1 << RXEN) | (1 << TXEN); // Turn on the transmission and reception
circuitry
UCSRC |= (1 << URSEL) | (1<<USBS) | (1 << UCSZ0) | (1 << UCSZ1);
// Use 8-bit character sizes
UBRRL = BAUD_PRESCALE;
// Load lower 8-bits of the baud rate value into the low byte of the UBRR register
UBRRH = (BAUD_PRESCALE >> 8); // Load upper 8-bits of the baud rate value..
// into the high byte of the UBRR register
}
/*
Receive data from serial port and display it on LCD
LCD DATA port----PORT A
ctrl port------PORT B
rs-------PB0
rw-------PB1
en-------PB2
using external clock frequency 12MHz
*/
#include<avr/io.h>
#include<util/delay.h>
void usart_init();
void usart_putch(unsigned char send);
unsigned int usart_getch();
int main()
{
unsigned char value;
DDRA=0xff; // LCD_DATA port as output port
DDRB=0x07; // signal as out put
init_LCD(); //initialization of LCD
_delay_ms(50); // delay of 50 milli seconds
usart_init(); // initialization of USART
while(1)
{
value=usart_getch(); // Call a function to get data from serial port
LCD_cmd(0xC0); // to go in second line and zeroth position on LCD
LCD_write(value); // write data to LCD
}
return 0;
}
void init_LCD(void)
{
LCD_cmd(0x38); // initialization of 16X2 LCD in 8bit mode
_delay_ms(1);
LCD_cmd(0x0E); // cursor ON
_delay_ms(1);
void usart_init()
{
UCSRB |= (1 << RXEN) | (1 << TXEN); // Turn on the transmission and reception
circuitry
UCSRC |= (1 << URSEL) | (1<<USBS) | (1 << UCSZ0) | (1 << UCSZ1);
// Use 8-bit character sizes
UBRRL = BAUD_PRESCALE;
// Load lower 8-bits of the baud rate value into the low byte of the UBRR register
UBRRH = (BAUD_PRESCALE >> 8); // Load upper 8-bits of the baud rate value..
// into the high byte of the UBRR register
}
void usart_init();
// --------------------------------------------
int main()
{
usart_init(); // initialization of USART
void usart_init()
{
UCSRB |= (1<<RXCIE) | (1 << RXEN) | (1 << TXEN); // Turn on
//
circuitry and receiver interrupt
UCSRC |= (1 << URSEL) | (1 << UCSZ0) | (1 << UCSZ1); //
Use 8-bit character sizes
ISR (USART_RXC_vect)
{
unsigned char value;
value = UDR; // Fetch the received byte
value into the variable "value"
UDR = value; //Put the value to UDR
}
This article covers data transmission using 8 bit USART. The readers should have a
basic understanding of serial communication and how to receive the serial data
output. More details on these topics are available on Serial communication using
#include<avr/io.h>
#include<util/delay.h>
void usart_init();
void usart_putch(unsigned char send);
unsigned int usart_getch();
int main()
{
unsigned char value;
DDRA=0xff;
DDRB=0x07;
init_LCD(); //initialization of LCD
_delay_ms(50); // delay of 50 mili seconds
usart_init(); // initialization of USART
while(1)
{
value=usart_getch(); // get data from serial port
LCD_cmd(0xC0);
LCD_write(value); // write data to LCD
usart_putch(value); // send data back to the PC (HyperTerminal)
}
return 0;
}
void init_LCD(void)
{
LCD_cmd(0x38); //initialization of 16X2 LCD in 8bit mode
_delay_ms(1);
void usart_init()
{
UCSRB |= (1 << RXEN) | (1 << TXEN);
// Turn on the transmission and reception circuitry
UCSRC |= (1 << URSEL) | (1<<USBS) | (1 << UCSZ0) | (1 << UCSZ1);
// Use 8-bit character sizes
using System;
using System.IO.Ports;
using System.Windows.Forms;
namespace SerialPortExample
{
class SerialPortProgram
{
// Create the serial port with basic settings
private SerialPort port = new SerialPort("COM1",
9600, Parity.None, 8, StopBits.One);
[STAThread]
static void Main(string[] args)
{
// Instatiate this class
new SerialPortProgram();
}
private SerialPortProgram()
{
Console.WriteLine("Incoming Data:");
// Begin communications
port.Open();
To start off, here is sample code in a terminal application which you can try out to see how the
SerialPort class is used. This requires Visual Studio 2010 to compile, which can be obtained free
via C# Express. It is just a simple little application with basic support for text or binary (hex)
modes to send and receive data. A nice feature or two is auto-detection of installed COM ports
that update at runtime if you plugin or remove USB-to-Serial adapters, also you can change the
DTR and RTS levels and monitor the CTS, DSR, and CD lines.
Build Note: You will receive an error that Visual Studio isn't able to find NoahCode.pfx. This is
expected as it is the click-once certificate for publishing and is NOT NEEDED for normal code use.
Just go to Project Properties > Signing > Click on Create Test Certificate. that’s it
Get Connected
You can obtain USB to Serial adapters and have just about as many ports on your PC as you like. I
carry around two adapters with a null modem (wikipedia) between them so I can create a
loopback to send & receive through to separate ports on most any computer. I'd recommend doing
the same for when writing code for the serial port.
If you'd like to quickly and easily create your own external devices to communicate with the PC, I
recommend starting with the Arduino, NetDuino (like an Arduino but programmed in C#),
or Parallax BASIC Stamp modules. All three have many accessories and sensors available (such as
LCDs, RF, Sounds, AD & DA, etc). sparkfun.com is a great place to look. After that you could
migrate to an Atmel Microcontroller (recommended) or Microchip PIC.
// Write a string
port.Write("Hello World");
Sending Files
Here are two helpful little methods for sending files through the serial port. Of course, these are
the bare essentials and as always, you should check to make sure the port is open first
(port.IsOpen) and use try/catch around trying to open a file, but you get the gist with this code.
The binary sending routine is limited to about 2GB (the size of an int), but this should be okay for
most uses.
using System.IO;
- RTS & DTR are binary outputs that can be manually set and held
- DCD, DSR, CTS, and RI are binary inputs that can be read
- RX & TX can not be set manually and are controlled by the UART
- maximum voltages are between -15 volts and +15 volts
- binary outputs are between +5 to +15 volts and -5 to -15 volts
- binary inputs are between +3 to +15 volts and -3 to -15 volts
- input voltages between -3 to +3 are undefined while output voltages
between -5 and +5 are undefined
- positive voltages indicate ON or SPACE, negative voltages indicate
OFF or MARK
Protocol Development
If you are making your own serial interface/protocol, you really must have a good standard in
place. Serial data flows into the com port byte by byte and must be buffered and parsed correctly.
Think of it this way, if a terminal sent your computer "Hello World" it may come in as four
OnComm triggers: "H", "ello", " Wo", and "rld"
The best protocols are usually a mix of these methods. Here are three simple protocol techniques:
Im making a WindowsForm app to simulate current values to a meter. I dont know how
to take the values from the text box and send it trough the COM port. this is the code i
got at the moment
namespace ValueSim1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
if (comboBox1.Text != "")
{
serialPort1.PortName = comboBox1.Text; //comboBox1.Text set to PortName