-
Notifications
You must be signed in to change notification settings - Fork 2
/
uartSerialCommunication.c
316 lines (273 loc) · 9.67 KB
/
uartSerialCommunication.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
//Abaixo os importes necessários para o funcionamento do código.
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <termios.h>
#include <string.h>
#include <sys/time.h>
#include <sys/types.h>
#include <pthread.h>
#include <stdlib.h>
//Struct para acesso dessas variáveis em varias funções inclusive a main (função principal).
struct ThreadData {
int arquivoSerial;
int tam;
unsigned char *bufferRxTx;
int parar;
};
//Função que mostra as opções disponíveis para o leitor.
void tabela();
//Função para limpar o buffer.
void limparBufferEntrada();
//Função para escrever na porta serial.
void escrever_Porta_Serial(int, unsigned char[], int);
//Função para ler da porta serial.
void ler_Porta_Serial(int, unsigned char[], int);
//Thread para o sensoriamento contínuo de temperatura.
void *sensoriamento_Temp(void *arg);
//Thread para o sensoriamento contínuo de umidade.
void *sensoriamento_Umid(void *arg);
int main() {
//Declaração de variáveis.
int arquivoSerial, tam;
unsigned int requisicao;
unsigned int endereco_sensor;
unsigned char bufferRxTx[255];
//Configuração das portas seriais.
struct termios options;
//O endereço é por convenção a primeira porta serial disponível.
arquivoSerial = open("/dev/ttyS0", O_RDWR | O_NDELAY | O_NOCTTY);
//Verifica se não conseguiu abrir o arquivo por algum motivo.
if (arquivoSerial < 0) {
perror("\x1b[31mErro ao abrir porta serial\x1b[0m\n");
return -1;
}
//Configurando a porta serial.
options.c_cflag = B9600 | CS8 | CLOCAL | CREAD; //Baud: 9600, CS8: tamanho do envio de dados.
options.c_iflag = IGNPAR;
options.c_oflag = 0;
options.c_lflag = 0;
//Aplicando as configurações.
tcflush(arquivoSerial, TCIFLUSH); //Limpa o buffer do arquivoSerial.
tcsetattr(arquivoSerial, TCSANOW, &options); //Aplique agora, neste instante.
while(1){
//Criando a thread.
pthread_t thread, thread1;
//Criando a struct dos argumentos que vão na thread.
struct ThreadData data;
//Atribuindo dados da main nas variáveis da struct.
data.arquivoSerial = arquivoSerial;
data.bufferRxTx = bufferRxTx;
data.tam = tam;
data.parar = 0;
//Chamando a tabela de requisições.
tabela();
//Recebendo a requisição e o endereço do sensor.
scanf("%d %d", &requisicao, &endereco_sensor);
//Validação das entradas.
while(requisicao < 1 || requisicao > 7 || endereco_sensor < 1 || endereco_sensor > 32){
printf("Escolha uma requisição e sensor valido!\n");
scanf("%d %d", &requisicao, &endereco_sensor);
system("clear");
}
//Switch case para atribuir os dados corretos na variável requisicao, de acordo com a opção escolhida.
switch(requisicao){
case 1:
requisicao = 0xAC;
break;
case 2:
requisicao = 0x01;
break;
case 3:
requisicao = 0x02;
break;
case 4:
requisicao = 0x03;
break;
case 5:
requisicao = 0x04;
break;
case 6:
requisicao = 0x05;
break;
case 7:
requisicao = 0x06;
break;
default:
break;
}
//Switch case para atribuir os dados corretos na variável endereco_sensor, de acordo com a opção escolhida.
switch (endereco_sensor)
{
case 1:
endereco_sensor = 0x01;
break;
default:
printf("Esse sensor não está em funcionamento!\n");
break;
}
limparBufferEntrada();
//Juntando e convertendo para string.
sprintf(bufferRxTx, "%c%c", requisicao, endereco_sensor);
//Requisições válidas.
switch (requisicao)
{
case 0xAC:
break;
case 0x01:
break;
case 0x02:
break;
case 0x03:
break;
case 0x04:
break;
case 0x05:
break;
case 0x06:
break;
default:
printf("\x1b[31mRequisição inválida, por favor escolha uma requisição válida da próxima vez.\x1b[0m\n");
break;
}
escrever_Porta_Serial(arquivoSerial, bufferRxTx, tam);
ler_Porta_Serial(arquivoSerial, bufferRxTx, tam);
//Switch case responsável por verificar a resposta da placa, e realizar uma operação de saída adequada, no caso printf().
unsigned int resposta = (unsigned int) bufferRxTx[0];
switch(resposta){
case 0x1F:
printf("\x1b[31mSensor com problema.\x1b[0m\n");
sleep(3);
break;
case 0x07:
printf("Sensor funcionando normalmente.\n");
sleep(3);
break;
case 0x08:
printf("\nMedida de umidade: %02d %% RH.\n",bufferRxTx[1]);
sleep(3);
break;
case 0x09:
printf("\nMedida de temperatura: %02d °C.\n",bufferRxTx[1]);
sleep(3);
break;
case 0x0A:
printf("Confirmação de desativação de sensoriamento contínuo de temperatura.\n");
sleep(3);
break;
case 0x0B:
printf("Confirmação de desativação de sensoriamento contínuo de umidade.\n");
sleep(3);
break;
case 0x0D:
// Cria a thread de sensoriamento de temperatura e passa os dados como argumento.
if (pthread_create(&thread, NULL, sensoriamento_Temp, &data) != 0) {
fprintf(stderr, "Erro ao criar a thread.\n");
return 1;
}
printf("Pressione Enter para parar sair do Sensoriamento Contínuo.\n");
getchar(); // Aguarda a entrada do usuário.
// Define a variável 'parar' como verdadeira para encerrar a thread de sensoriamento de temperatura.
data.parar = 1;
// Aguarda a thread de sensoriamento de temperatura terminar
if (pthread_join(thread, NULL) != 0) {
fprintf(stderr, "Erro ao esperar pela thread.\n");
return 1;
}
printf("Sensoriamento Contínuo de temperatura encerrado.\n");
break;
case 0x0E:
// Cria a thread de sensoriamento de umidade e passa os dados como argumento.
if (pthread_create(&thread1, NULL, sensoriamento_Umid, &data) != 0) {
fprintf(stderr, "Erro ao criar a thread.\n");
return 1;
}
printf("Pressione Enter para parar sair do Sensoriamento Contínuo.\n");
getchar(); // Aguarda a entrada do usuário.
// Define a variável 'parar' como verdadeira para encerrar a thread de sensoriamento de umidade.
data.parar = 1;
// Aguarda a thread de sensoriamento de umidade terminar.
if (pthread_join(thread1, NULL) != 0) {
fprintf(stderr, "Erro ao esperar pela thread.\n");
return 1;
}
printf("Sensoriamento Contínuo de umidade encerrado.\n");
break;
case 0xFF:
printf("\x1b[31mComando inválido devido a ativação do sensoriamento contínuo.\x1b[0m\n");
sleep(3);
break;
case 0xAA:
printf("\x1b[31mComando inválido pois o sensoriamento contínuo não foi ativado.\x1b[0m\n");
sleep(3);
break;
case 0xAB:
printf("\x1b[31mErro na máquina de estados.\x1b[0m\n");
sleep(3);
break;
default:
printf("\x1b[31mErro de leitura, observe se o sensor se encontra conectado! \x1b[0m\033[0m\n");
sleep(3);
break;
}
}
//Fecho o arquivoSerial para evitar possíveis erros.
close(arquivoSerial);
return 0;
}
void tabela(){
system("clear");
printf("\033[32m-------------------------------------------------------------------------------------------------------\n");
printf("| Tabela Requisição | Endereço Sensor |\n");
printf("-------------------------------------------------------------------------------------------------------\n");
printf("| | DHT11 => 1: 0x01 9: 0x09 17: 0xAB 25: 0xBD |\n");
printf("| 1: Situação atual do sensor. | 2: 0x02 10: 0x0A 18: 0xAC 26: 0xBE |\n");
printf("| 2: Medida de temperatura atual. | 3: 0x03 11: 0x0B 19: 0xAD 27: 0xBF |\n");
printf("| 3: Medida de umidade atual. | 4: 0x04 12: 0x0C 20: 0xAE 28: 0xCA |\n");
printf("| 4: Ativa sensoriamento contínuo de temperatura. | 5: 0x05 13: 0x0D 21: 0xAF 29: 0xCB |\n");
printf("| 5: Ativa sensoriamento contínuo de umidade. | 6: 0x06 14: 0x0E 22: 0xBA 30: 0xCC |\n");
printf("| 6: Desativa sensoriamento contínuo de temperatura.| 7: 0x07 15: 0x0F 23: 0xBB 31: 0xCD |\n");
printf("| 7: Desativa sensoriamento contínuo de umidade. | 8: 0x08 16: 0xAA 24: 0xBC 32: 0xCE |\n");
printf("| | |\n");
printf("-------------------------------------------------------------------------------------------------------\n");
}
void escrever_Porta_Serial(int arquivoSerial, unsigned char bufferRxTx[], int tam){
tam = strlen(bufferRxTx);
tam = write(arquivoSerial, bufferRxTx, tam);
printf("Escreveu %d bytes em UART\n", tam);
sleep(3);
}
void ler_Porta_Serial(int arquivoSerial, unsigned char bufferRxTx[], int tam){
memset(bufferRxTx, 0, 255);
tam = read(arquivoSerial, bufferRxTx, 2);
printf("Recebeu %d bytes\n", tam);
sleep(1);
}
void *sensoriamento_Temp(void *arg){
//Manipulação para acesso das variáveis contidas na struct nessa função.
struct ThreadData *data = (struct ThreadData *)arg;
while (!data->parar) {
system("clear");
ler_Porta_Serial(data->arquivoSerial, data->bufferRxTx, data->tam);
printf("Temperatura atual: %d °C\n", data->bufferRxTx[1]);
sleep(3);
}
return NULL;
}
void *sensoriamento_Umid(void *arg){
//Manipulação para acesso das variáveis contidas na struct nessa função.
struct ThreadData *data = (struct ThreadData *)arg;
while (!data->parar) {
system("clear");
ler_Porta_Serial(data->arquivoSerial, data->bufferRxTx, data->tam);
printf("Umidade atual: %d %% RH\n", data->bufferRxTx[1]);
sleep(3);
}
return NULL;
}
void limparBufferEntrada(){
int c;
while((c = getchar()) != '\n' && c != EOF){
}
}