Communicating with the Penguino AVR over UART
Penguino Code
The Penguino AVR can communicate using serial UART over the USB connection to a computer.
The Penguino software library lets you set up UART communication to act as if it were standard I/O in a console C program. The following example using the Penguino library shows a simple program that uses UART:
1
2 #include <stdio.h>
3
4 #include "penguino/uart/uart.h"
5 #include "penguino/uart/uart-stdio.h"
6 #include "penguino/time.h"
7
8 #define UART_BAUD_RATE 115200
9
10 int main( void ) {
11 char name[80];
12 int age = 0;
13
14 // initalise UART
15 uart_init( UART_BAUD_RATE );
16
17 // enable UART as stdio
18 uart_stdio_init( );
19
20 // enable echo on the UART stdin so the user can see what they are typing
21 uart_stdio_echo( true );
22
23 while ( 1 ) {
24 printf( "\r\n\r\nHello there, I'm a Penguino AVR!\r\n\r\n" );
25
26 printf( "What's your name? " );
27 scanf( "%s", name ); // N.B. this is a format vulnerability in C! example only
28
29 printf( "\r\n\r\n" );
30
31 printf( "Why hello, %s! How old are you? ", name );
32 scanf( "%d", &age );
33
34 printf( "\r\n\r\n" );
35
36 printf( "Thanks, %s, for telling me you're %d years old!\r\n\r\n", name, age );
37
38 // snooze
39 delay_ms( 300 );
40 }
41
42 return 0;
43 }
Things to Note:
- The suggested UART baud rate is either 115200 or 250000
- The maximum tested UART baud rate is 500000
- High baud rates may not work at the same time as JTAG (e.g. during programming) or other USB communication, unless the device is in reset
- When running at 16MHz, do not use "Double Speed Operation (U2X)" UART mode or the USB controller may not be able to synch at an ideal baud rate
- The standard way to specify a new line over serial is to use both \r and \n characters together for 1 new line.
Computer-Side
Terminal Applications
This serial communication can be displayed in a terminal on the computer using:
- Hyperterminal on Windows
- the 'screen' commandline program on OSX or ZTerm
screen /dev/cu.penguino-uart 115200 (ctrl-A then ctrl-\ to quit)
- minicom on any linux/POSIX system
Device Name
The Penguino AVR appears as the following device names (after installing the required drivers):
- COMX on Windows, where X is the port number Windows has decided to use for the USB device (e.g. COM3)
- /dev/cu.penguino-uart on OSX
- /dev/ttyACM0 on Linux
PySerial
To communicate with the Penguino AVR over UART in python, a python serial package is available called PySerial.
A PySerial program to communicate with the Penguino AVR may look like:
1
2 import serial
3
4 serialConnection = serial.Serial( '/dev/cu.penguino-uart', 115200, timeout=1 )
5
6 while ( True ):
7 line = serialConnection.readline( )
8 print( line )
9 serialConnection.write( "received line" )
10
11 serialConnection.close( )
C Program
A C program on a POSIX or similar (linux/unix/OSX) machine to communicate with the Penguino AVR over UART may look like:
1
2 #include <stdio.h> /* Standard input/output definitions */
3 #include <string.h> /* String function definitions */
4 #include <unistd.h> /* UNIX standard function definitions */
5 #include <fcntl.h> /* File control definitions */
6 #include <errno.h> /* Error number definitions */
7 #include <termios.h> /* POSIX terminal control definitions */
8
9 #define FD_ERROR (-1)
10 #define BUF_SIZE 1024
11
12 int open_port( char *device, int baudConstant ) {
13 int fd = FD_ERROR;
14
15 fd = open( device, O_RDWR | O_NOCTTY | O_NDELAY );
16
17 if ( fd == FD_ERROR ) {
18 perror( "Unable to open device" );
19 } else {
20 fcntl( fd, F_SETFL, 0 );
21 }
22
23
24 // set the baud rate
25 struct termios options;
26
27 tcgetattr( fd, &options );
28
29 cfsetispeed( &options, baudConstant );
30 cfsetospeed( &options, baudConstant );
31
32 options.c_cflag |= (CLOCAL | CREAD);
33
34 tcsetattr( fd, TCSANOW, &options );
35
36 return fd;
37 }
38
39 void set_port_nonblocking( int fd ) {
40 fcntl( fd, F_SETFL, FNDELAY );
41 }
42
43 void set_port_blocking( int fd ) {
44 fcntl( fd, F_SETFL, 0 );
45 }
46
47 int main( int argc, char *argv[] ) {
48
49 // replace the device name with the appropriate name for your system
50 int serial = open_port( "/dev/cu.penguino-uart", B115200 );
51 set_port_nonblocking( serial );
52
53 char receive_buffer[BUF_SIZE];
54 char send_buffer[BUF_SIZE] = "received line";
55 char line[BUF_SIZE] = "";
56 char *lineCursor = line;
57
58 while ( 1 ) {
59
60 // read bytes from the UART link into 'buffer'
61 int bytesRead = read( serial, receive_buffer, BUF_SIZE );
62
63 if ( bytesRead > 0 ) {
64 // bytes were received!
65
66
67 // go through each byte, and print out lines
68 int i;
69 for ( i = 0; i < bytesRead; ++i ) {
70
71 if ( receive_buffer[i] == '\r' || receive_buffer[i] == '\n' ) {
72 // one of the new line characters was found
73
74 // we only care about one of them, ignore the other
75 if ( receive_buffer[i] == '\n' ) {
76
77 // terminate the line string
78 *lineCursor = '\0';
79 // reset the character pointer
80 // to the start of the line
81 lineCursor = line;
82
83 // print this line
84 printf( "%s\n", line );
85
86 // reply that we've read a line
87 write( serial, send_buffer, BUF_SIZE );
88 }
89
90 } else {
91 // not a new line character, add it to the line buffer
92 *lineCursor = receive_buffer[i];
93 ++lineCursor;
94 }
95 }
96 }
97 }
98
99 return 0;
100 }
![icy [labs]](/moin_static171/common/wikilogo.png)