· 6 years ago · Feb 14, 2020, 03:30 PM
1/*
2 ============================================================================
3 Name : ex03.c
4 Author : gbs
5 Version :
6 Copyright : Your copyright notice
7 Description : A simple C program for demonstrating the serial communication.
8 ============================================================================
9 */
10
11//==============================================================================
12// USED INTERFACES
13//==============================================================================
14
15#define _GNU_SOURCE /* See feature_test_macros(7) */
16
17#include <fcntl.h> /* Required by open / write system calls. */
18#include <pthread.h> /* POSIX threads Library. Required by PIGPIO. */
19#include <stdint.h> /* Standard Int Library.(uint32_t, uint8_t...)*/
20#include <stdio.h> /* Standard Input/Ouput Library. (printf...) */
21#include <stdlib.h> /* General (standard) Library. (EXIT_SUCCESS. */
22#include <termios.h> /* Terminal Input/Output interfaces. */
23#include <unistd.h> /* Complement (flags, constants, definitions..)
24 for the POSIX API. */
25
26#include "pigpio.h" /* PIGPIO Library header. */
27
28//==============================================================================
29// MACROS AND DATATYPE DEFINITIONS
30//==============================================================================
31
32/* HW and Interfaces */
33
34#define SERIAL "/dev/ttyS0"
35#define SERIAL_BAUD 115200
36
37//==============================================================================
38// STATIC (PRIVATE) FUNCTION PROTOTYPES
39//==============================================================================
40
41/**
42 * @brief A function to verify if any key was pressed on terminal.
43 *
44 * @return TRUE If a key was pressed.
45 * @return FALSE Otherwise.
46 */
47static int kbhit(void);
48
49/**
50 * @brief Initializes the p_path serial device. Opens the serial device and
51 * sets minimal attributes to get it working.
52 *
53 * @param[in] p_path The serial device path.
54 * @param[out] p_fd A file descriptor to link to the serial device above.
55 * @param[in] speed The serial BAUDRATE.
56 *
57 * @return 1 If the serial device was initialized.
58 * @return 0 If an error has occurred.
59 */
60uint8_t serial_initialize(
61 const char *p_path,
62 int32_t *p_fd,
63 const uint32_t speed);
64
65
66//==============================================================================
67// STATIC GLOBAL VARIABLES
68//==============================================================================
69
70//==============================================================================
71// IMPLEMENTATION OF PUBLIC FUNCTIONS
72//==============================================================================
73
74int main(void)
75{
76 int serial_fd; /* A file descriptor to manipulate the SERIAL.*/
77 uint8_t serial_st; /* A status for the serial_initialize func. */
78
79 /* Opens SERIAL for reading and writing at SERIAL_BAUD baudrate.*/
80 serial_st = serial_initialize(SERIAL, &serial_fd, SERIAL_BAUD);
81
82 if (serial_st == 0)
83 {
84 printf("Error: Failed to open serial %s \r\n", SERIAL);
85 }
86
87 while(!kbhit()) /* While a key from the keyboard isn't pressed... */
88 {
89 write(serial_fd, "Running.. Serial is easy\r\n", sizeof("Running.. Serial is easy\r\n"));
90 }
91
92 close(serial_fd);
93
94 return EXIT_SUCCESS;
95}
96
97
98//==============================================================================
99// IMPLEMENTATION OF STATIC (PRIVATE) FUNCTIONS
100//==============================================================================
101
102static int kbhit(void)
103{
104 struct termios oldt, newt;
105
106 int ch;
107 int oldf;
108
109 /** Gets the attributes from the standard input file descriptor. */
110 tcgetattr(STDIN_FILENO, &oldt);
111
112 /** Enables raw input. (unprocessed). */
113 newt = oldt;
114 newt.c_lflag &= ~(ICANON | ECHO);
115
116 /** Sets the new attributes. */
117 tcsetattr(STDIN_FILENO, TCSANOW, &newt);
118
119 /** Gets the file access mode and status flags. */
120 oldf = fcntl(STDIN_FILENO, F_GETFL, 0);
121
122 /** Sets the same above read values + the O_NONBLOCK flag. */
123 fcntl(STDIN_FILENO, F_SETFL, oldf | O_NONBLOCK);
124
125 /** Checks if there is a char on the standard terminal. (nonblock). */
126 ch = getchar();
127
128 /** Make changes now, without waiting for data to complete. */
129 tcsetattr(STDIN_FILENO, TCSANOW, &oldt);
130
131 /** Removes the O_NONBLOCK flag. */
132 fcntl(STDIN_FILENO, F_SETFL, oldf);
133
134 /** If any key was hitted, return true. And puts back the pressed key onto
135 * the terminal. */
136 if(ch != EOF)
137 {
138 ungetc(ch, stdin);
139 return 1;
140 }
141
142 return 0;
143}
144
145uint8_t serial_initialize(
146 const char *p_path,
147 int32_t *p_fd,
148 const uint32_t speed)
149{
150
151 uint8_t ret;
152
153 /** Tries to open the serial device (p_path).
154 * O_RDWR: Request read and write permissions. */
155 *p_fd = open(p_path, O_RDWR);
156
157 if (p_fd < 0)
158 {
159 printf("Error: Failed to open serial %s \n\n", p_path);
160 ret = 0;
161 }
162 else
163 {
164 printf("Serial (%s) opened!!\n\n", p_path);
165
166 /** The structure to set and get the device parameters. */
167 struct termios config;
168
169 /** Get the current configuration of the serial interface. */
170 if (tcgetattr(*p_fd, &config) < 0)
171 {
172 printf("Error: Could not get the %s attributes!\n\n", p_path);
173 }
174 else
175 {
176 printf("Serial (%s) attributes read.. \n\n", p_path);
177
178 /** Check if the fd is pointing to a TTY device or not. */
179 if (!isatty(*p_fd))
180 {
181 printf("Error: %s isnt pointing to a TTY device!!\n\n", p_path);
182 }
183 else
184 {
185 printf("%s is a tty device. Continuing...\n\n", p_path);
186
187 /** Setting the baudrate. */
188 if (cfsetspeed(&config, (speed_t)speed) < 0)
189 {
190 printf("Error: Couldn't set the %s baudrate!!\n\n", p_path);
191 }
192 else
193 {
194 /** No parity. */
195 config.c_cflag &= ~PARENB;
196 /** One stop bit. */
197 config.c_cflag &= ~CSTOPB;
198 /** Zeroes the char size mask. */
199 config.c_cflag &= ~CSIZE;
200 /** Sets data size = 8 bits. */
201 config.c_cflag |= CS8;
202 /** Disables HW flow control. */
203 config.c_cflag &= ~CRTSCTS;
204 /** Minimum number of characters for read. */
205 config.c_cc[VMIN] = 1;
206 /** Timeout in deciseconds for read. (0.5s) */
207 config.c_cc[VTIME] = 5;
208 /** Enables READ and ignores control lines. */
209 config.c_cflag |= CREAD | CLOCAL;
210
211 /** Set the terminal to "raw mode". */
212 cfmakeraw(&config);
213
214 /** Flushes the serial dev and sets the new attributes. */
215 if (tcsetattr(*p_fd, TCSAFLUSH, &config) < 0)
216 {
217 printf("Error: Couldn't set the %s attributes!!\n\n",
218 p_path);
219 }
220 else
221 {
222 ret = 1;
223 }
224 }
225 }
226 }
227 }
228 return ret;
229}