From: Martin Ling Date: Sun, 2 Feb 2020 10:51:07 +0000 (+0000) Subject: Add example of sending and receiving data. X-Git-Tag: libserialport-0.1.2~26 X-Git-Url: https://sigrok.org/gitaction?a=commitdiff_plain;h=cd1a7d4361a4074d0c6ce55527c735afd7bcad88;p=libserialport.git Add example of sending and receiving data. --- diff --git a/examples/.gitignore b/examples/.gitignore index afe6f4a..997de03 100644 --- a/examples/.gitignore +++ b/examples/.gitignore @@ -3,3 +3,4 @@ handle_errors list_ports port_info port_config +send_receive diff --git a/examples/send_receive.c b/examples/send_receive.c new file mode 100644 index 0000000..e1aabf0 --- /dev/null +++ b/examples/send_receive.c @@ -0,0 +1,136 @@ +#include +#include +#include +#include + +/* Example of how to send and receive data. + * + * This example file is released to the public domain. */ + +/* Helper function for error handling. */ +int check(enum sp_return result); + +int main(int argc, char **argv) +{ + /* This example can be used with one or two ports. With one port, it + * will send data and try to receive it on the same port. This can be + * done by connecting a single wire between the TX and RX pins of the + * port. + * + * Alternatively it can be used with two serial ports connected to each + * other, so that data can be sent on one and received on the other. + * This can be done with two ports with TX/RX cross-connected, e.g. by + * a "null modem" cable, or with a pair of interconnected virtual ports, + * such as those created by com0com on Windows or tty0tty on Linux. */ + + /* Get the port names from the command line. */ + if (argc < 2 || argc > 3) { + printf("Usage: %s []\n", argv[0]); + return -1; + } + int num_ports = argc - 1; + char **port_names = argv + 1; + + /* The ports we will use. */ + struct sp_port *ports[2]; + + /* Open and configure each port. */ + for (int i = 0; i < num_ports; i++) { + printf("Looking for port %s.\n", port_names[i]); + check(sp_get_port_by_name(port_names[i], &ports[i])); + + printf("Opening port.\n"); + check(sp_open(ports[i], SP_MODE_READ_WRITE)); + + printf("Setting port to 9600 8N1, no flow control.\n"); + check(sp_set_baudrate(ports[i], 9600)); + check(sp_set_bits(ports[i], 8)); + check(sp_set_parity(ports[i], SP_PARITY_NONE)); + check(sp_set_stopbits(ports[i], 1)); + check(sp_set_flowcontrol(ports[i], SP_FLOWCONTROL_NONE)); + } + + /* Now send some data on each port and receive it back. */ + for (int tx = 0; tx < num_ports; tx++) { + /* Get the ports to send and receive on. */ + int rx = num_ports == 1 ? 0 : ((tx == 0) ? 1 : 0); + struct sp_port *tx_port = ports[tx]; + struct sp_port *rx_port = ports[rx]; + + /* The data we will send. */ + char *data = "Hello!"; + int size = strlen(data); + + /* We'll allow a 1 second timeout for send and receive. */ + unsigned int timeout = 1000; + + /* On success, sp_blocking_write() and sp_blocking_read() + * return the number of bytes sent/received before the + * timeout expired. We'll store that result here. */ + int result; + + /* Send data. */ + printf("Sending '%s' (%d bytes) on port %s.\n", + data, size, sp_get_port_name(tx_port)); + result = check(sp_blocking_write(tx_port, data, size, timeout)); + + /* Check whether we sent all of the data. */ + if (result == size) + printf("Sent %d bytes successfully.\n", size); + else + printf("Timed out, %d/%d bytes sent.\n", result, size); + + /* Allocate a buffer to receive data. */ + char buf[size + 1]; + + /* Try to receive the data on the other port. */ + printf("Receiving %d bytes on port %s.\n", + size, sp_get_port_name(rx_port)); + check(sp_blocking_read(rx_port, buf, size, timeout)); + + /* Check whether we received the number of bytes we wanted. */ + if (result == size) + printf("Received %d bytes successfully.\n", size); + else + printf("Timed out, %d/%d bytes received.\n", result, size); + + /* Check if we received the same data we sent. */ + buf[result] = '\0'; + printf("Received '%s'.\n", buf); + } + + /* Close ports and free resources. */ + for (int i = 0; i < num_ports; i++) { + check(sp_close(ports[i])); + sp_free_port(ports[i]); + } + + return 0; +} + +/* Helper function for error handling. */ +int check(enum sp_return result) +{ + /* For this example we'll just exit on any error by calling abort(). */ + char *error_message; + + switch (result) { + case SP_ERR_ARG: + printf("Error: Invalid argument.\n"); + abort(); + case SP_ERR_FAIL: + error_message = sp_last_error_message(); + printf("Error: Failed: %s\n", error_message); + sp_free_error_message(error_message); + abort(); + case SP_ERR_SUPP: + printf("Error: Not supported.\n"); + abort(); + case SP_ERR_MEM: + printf("Error: Couldn't allocate memory.\n"); + abort(); + case SP_OK: + default: + return result; + } +} diff --git a/libserialport.h b/libserialport.h index 1ff0b68..45dadc5 100644 --- a/libserialport.h +++ b/libserialport.h @@ -68,6 +68,7 @@ * - @ref list_ports.c - Getting a list of ports present on the system. * - @ref port_info.c - Getting information on a particular serial port. * - @ref port_config.c - Accessing configuration settings of a port. + * - @ref send_receive.c - Sending and receiving data. * - @ref await_events.c - Awaiting events on multiple ports. * - @ref handle_errors.c - Handling errors returned from the library. * @@ -1289,6 +1290,8 @@ SP_API enum sp_return sp_set_flowcontrol(struct sp_port *port, enum sp_flowcontr * * Reading, writing, and flushing data. * + * See @ref send_receive.c for an example of sending and receiving data. + * * @{ */ @@ -1812,6 +1815,7 @@ SP_API const char *sp_get_lib_version_string(void); * @example list_ports.c Getting a list of ports present on the system. * @example port_info.c Getting information on a particular serial port. * @example port_config.c Accessing configuration settings of a port. + * @example send_receive.c Sending and receiving data. * @example await_events.c - Awaiting events on multiple ports. * @example handle_errors.c - Handling errors returned from the library. */