|
|||||||
| Did you know...
|
|
||||||
![]() |
![]() |
The code below is relatively simple. It:
| The code below works good on my eee PC when I plug in
an Edgeport Serial to USB adapter, which shows up under
/dev/ttyUSB0 . Under cygwin, the port is whatever your
COM port number is, minus one. Be sure to use the
/dev/tty## interface, and not the /dev/COM## interface,
as only the tty interface provides all of the POSIX
functionality. The only problem I ran into was that the FIONREAD constant wasn't defined on my eee Linux distribution. Ideally, I'd like to check the number of received bytes then read, rather than looking for an arbitrary number and timing out if we don't get them. |
Special thanks to Michael Sweet for
creating the Serial
Programming Guide for POSIX Operating Systems. It's
fantastic!
Anyways, without further delay, here's the code:
#include <stdio.h>
#include <termios.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>
typedef unsigned char uint8;
typedef unsigned short uint16;
typedef enum {
LOW = 0,
HIGH = 1,
INPUT = 2,
UNCHANGED = 3
} state_t;
// The pin defines below are specific to the Olemex development board.
#define REDLEDPIN 34
#define GREENLEDPIN 35
#define LCDRWPIN 20
#define LCDEPIN 21
#define LCDBACKLIGHTPIN 22
#define B2PIN 37
// device id for the serial port
int serial_port;
// Since only one transaction can happen at a time, so we can
// use one set of buffers. We only use the first 8 bytes.
// The 9th byte holds a null string termintor to simplify
// string calls which act on the buffers
uint8 rxbuffer[9];
uint8 txbuffer[9];
void resync();
void print_transaction();
void set_pin(uint8 pin, state_t state);
uint16 get_public_data(uint8 pin);
void set_pwm(uint8 pin, uint16 PWM);
void put_text_lcd(char* string, uint8 position);
int main(int argc, char *argv[])
{
struct termios options;
int i;
rxbuffer[8] = '\0';
printf("Opening port...\n");
serial_port = open("/dev/ttyUSB0",O_RDWR | O_NOCTTY );
// serial_port = open("/dev/ttyS13",O_RDWR | O_NOCTTY ); // for cygwin. use COM Port # - 1.
sleep (1);
if (serial_port == -1)
{
perror("Couldn't open port");
}
else
{
fcntl(serial_port,F_SETFL,0);
}
tcgetattr(serial_port,&options);
cfsetispeed(&options,B9600); // Baud rate 9600
cfsetospeed(&options,B9600);
options.c_cflag &= ~CSIZE; // 8 data bits
options.c_cflag &= ~PARENB; // no parity
options.c_cflag &= ~CSTOPB; // No hw flow control
options.c_cflag &= ~CRTSCTS;
options.c_cflag |= CS8;
options.c_lflag &= ~(ICANON|ECHO|ECHOE|ISIG); // No terminal processing
options.c_oflag &= ~OPOST;
options.c_cc[VMIN] = 0; // Timeout before packet (unused)
options.c_cc[VTIME] = 10; // Timeout between characters
options.c_iflag &= ~(IXON|IXOFF|IXANY); // Disable sw flow control
options.c_cflag |= (CLOCAL|CREAD);
tcsetattr(serial_port,TCSANOW, &options);
fcntl(serial_port,F_SETFL,0);
printf("Resyncing...\n");
resync(); // Send U to sync and set baud
set_pwm(LCDBACKLIGHTPIN,32768); //50% . No reason, except to show
// we can do it
set_pin(LCDRWPIN,LOW); //HD44780 pin mode assumes LCD RW line
//Is always low
if (get_public_data(REDLEDPIN)) // Get the public data for RED
// LED pin. If it's 1, set it
// to zero, and vice-versa.
// This will toggle the red/green
// LED each time the program is run.
{
set_pin(REDLEDPIN,LOW);
set_pin(GREENLEDPIN,HIGH);
}
else
{
set_pin(REDLEDPIN,HIGH);
set_pin(GREENLEDPIN,LOW);
}
txbuffer[0] = 200; // Configure pin command 1
txbuffer[1] = LCDEPIN; // Pin 21 is the 'E' pin for the lcd
// (see documentation for HD44780 generic
// driver on serialwombat.com
txbuffer[2] = 27; // HD44780 generic driver mode
txbuffer[3] = 19; // RS PIN
txbuffer[4] = 27; // D4 pin
txbuffer[5] = 28; // D5 pin
txbuffer[6] = 29; // D6 pin
txbuffer[7] = 30; // D7 pin
transfer(txbuffer,rxbuffer);
print_transaction();
txbuffer[0] = 201; // Second command. Puts text on LCD
txbuffer[1] = LCDEPIN;
txbuffer[2] = 27;
txbuffer[3] = 0; // Start at address 0
txbuffer[4] = 'E';
txbuffer[5] = 'e';
txbuffer[6] = 'e';
txbuffer[7] = ' ';
transfer(txbuffer,rxbuffer);
print_transaction();
txbuffer[3] += 4; // Address 4. txbuffer[0-2] unchanged.
txbuffer[4] = 'P';
txbuffer[5] = 'C';
txbuffer[6] = ' ';
txbuffer[7] = 'A';
transfer(txbuffer,rxbuffer);
print_transaction();
txbuffer[3] += 4; // Address 8, and so on...
txbuffer[4] = 'n';
txbuffer[5] = 'd';
txbuffer[6] = ' ';
txbuffer[7] = ' ';
transfer(txbuffer,rxbuffer);
print_transaction();
txbuffer[3] += 4;
txbuffer[4] = ' ';
txbuffer[5] = ' ';
txbuffer[6] = ' ';
txbuffer[7] = ' ';
transfer(txbuffer,rxbuffer);
print_transaction();
txbuffer[3] = 0x40; // Second line starts at 0x40
txbuffer[4] = 'S';
txbuffer[5] = 'e';
txbuffer[6] = 'r';
txbuffer[7] = 'i';
transfer(txbuffer,rxbuffer);
print_transaction();
txbuffer[3] += 4;
txbuffer[4] = 'a';
txbuffer[5] = 'l';
txbuffer[6] = ' ';
txbuffer[7] = 'W';
transfer(txbuffer,rxbuffer);
print_transaction();
txbuffer[3] += 4;
txbuffer[4] = 'o';
txbuffer[5] = 'm';
txbuffer[6] = 'b';
txbuffer[7] = 'a';
transfer(txbuffer,rxbuffer);
print_transaction();
txbuffer[3] += 4;
txbuffer[4] = 't';
txbuffer[5] = ' ';
txbuffer[6] = ' ';
txbuffer[7] = ' ';
transfer(txbuffer,rxbuffer);
print_transaction();
while (get_public_data(B2PIN) != 0)
{
sleep(1);
}
put_text_lcd("Goodbye! ",0);
put_text_lcd(" ",0x40);
close(serial_port);
return(serial_port);
}
// Dump all of the data out of the receive buffer
// Ideally, we'd use FIONREAD to see if any are available, and
// read them. But FIONREAD doesn't appear to be implemented
// in the distribution I'm using, so I'll try a read and let it
// timeout if there's no data. This is inefficient, but I can't
// think of any better way without FIONREAD
void flush(void)
{
uint8 dummy[1002];
int i,j ;
printf("Flushing...\n");
do
{
i = read(serial_port,dummy,1000);
if (i > 0)
{
printf ("Flushed bytes: ");
for (j = 0; j < i ; ++j)
{
printf ("%2X ", dummy[j]);
}
printf("\n");
}
} while (i > 0);
}
// This function sends 8 bytes from the array tx, and waits for an 8
// byte return. If 8 bytes are not received without a timeout then
// a series of ReSync characters is sent, and the buffer is flushed.
// A second transmission is then attempted.
int transfer(uint8* tx, uint8* rx)
{
int i;
int rxbytes = 0; // Number of bytes received
uint8 rxtemp[9];
if (rx == NULL)
{
rx = rxtemp; // If no rxarray was specified, put the result
// into a temp variable
}
rx[0] = 'E'; // Assume a bad result
write(serial_port,tx,8); //Send the transmit
// Now, read bytes until we get 8 bytes, or a timeout with
// no bytes read.
do {
i = read(serial_port,&rx[rxbytes],8);
rxbytes += i;
} while (rxbytes < 8 && i > 0);
if (rxbytes < 8 || rx[0] == 'E')
{
// Try again if error, or less than 8 bytes received
// Print what we did get for debugging purposes.
printf("Incomplete response received. ");
for (i =0; i < rxbytes; ++i)
{
printf("%d = %2X ",i,rx[i]);
}
printf("\n");
// Send resync characters
write(serial_port,"UUUUUUUUUU",10);
//flush the buffer...
flush();
//Try send again
write(serial_port,tx,8);
rxbytes = read(serial_port,rx,8);
}
return(rxbytes);
}
void resync ()
{
int i;
uint8 tempbuffer[20];
for (i = 0; i < 20; ++i)
{
tempbuffer[i] = 'U';
}
write(serial_port,tempbuffer,20);
flush();
}
// A utility function to print out txbuffer & rxbuffer in hex
void print_transaction()
{
int i;
for (i = 0; i < 8; ++i)
{
printf ("%2X ",txbuffer[i]);
}
printf(" ");
for (i = 0; i < 8; ++i)
{
printf ("%2X ",rxbuffer[i]);
}
printf("\n");
}
void set_pin(uint8 pin, state_t state)
{
txbuffer[0] = 'P';
txbuffer[1] = pin / 10 + '0';
txbuffer[2] = pin % 10 + '0';
switch (state)
{
case LOW:
txbuffer[3] = '0';
break;
case HIGH:
txbuffer[3] = '1';
break;
case INPUT:
txbuffer[3] = 'I';
break;
default:
txbuffer[3] = 'U';
break;
}
txbuffer[4] = 'U';
txbuffer[5] = 'U';
txbuffer[6] = 'U';
txbuffer[7] = 'U';
transfer(txbuffer,rxbuffer);
print_transaction();
}
uint16 get_public_data(uint8 pin)
{
uint16 result = 0;
txbuffer[0] = 'A';
txbuffer[1] = pin / 10 + '0';
txbuffer[2] = pin % 10 + '0';
txbuffer[3] = 'D';
transfer(txbuffer,rxbuffer);
result = rxbuffer[3] - '0';
result *= 10;
result += rxbuffer[4] - '0';
result *= 10;
result += rxbuffer[5] - '0';
result *= 10;
result += rxbuffer[6] - '0';
result *= 10;
result += rxbuffer[7] - '0';
printf ("Pin %d public data %d\n",pin,result);
print_transaction();
return(result);
}
void set_pwm(uint8 pin, uint16 PWM)
{
txbuffer[0] = 200;
txbuffer[1] = pin;
txbuffer[2] = 18;
txbuffer[3] = PWM/256;
txbuffer[4] = PWM%256;
transfer(txbuffer,rxbuffer);
}
void put_text_lcd(char* string, uint8 position)
{
int i = 0;
int counter = 0;
printf ("%c %X \n",string[i],string[i]);
while (string[i] != '\0')
{
txbuffer[0] = 201; // Second command. Puts text on LCD
txbuffer[1] = LCDEPIN;
txbuffer[2] = 27;
txbuffer[3] = position;
txbuffer[4 + counter] = string[i];
++counter;
++i;
if (counter == 4)
{
transfer(txbuffer,rxbuffer);
print_transaction();
counter = 0;
position += 4;
}
}
if (counter != 0)
{
txbuffer[0] = 201; // Second command. Puts text on LCD
txbuffer[1] = LCDEPIN;
txbuffer[2] = 27;
txbuffer[3] = position;
while (counter < 4)
{
txbuffer[4 + counter] = ' ';
++counter;
}
transfer(txbuffer,rxbuffer);
print_transaction();
}
}
Copyright Wombat Interface Products, 2005-2008. All Rights Reserved.