You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

108 lines
3.3 KiB
C

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <termios.h>
// --- FUNCIÓN DE INICIALIZACIÓN ---
// Devuelve el descriptor de archivo (fd) o -1 si falla.
int init_uart(const char *puerto, speed_t baudrate) {
// Abrir el puerto: Lectura/Escritura, no ser la terminal controladora, no bloquear.
int fd = open(puerto, O_RDWR | O_NOCTTY | O_NDELAY);
if (fd == -1) {
perror("Error al abrir el puerto UART");
return -1;
}
struct termios tty;
if (tcgetattr(fd, &tty) != 0) {
perror("Error al obtener los atributos del puerto");
close(fd);
return -1;
}
// Configurar Baudios
cfsetispeed(&tty, baudrate);
cfsetospeed(&tty, baudrate);
// MODO CRUDO: 8N1 (8 bits, Sin paridad, 1 bit de parada)
tty.c_cflag &= ~PARENB; // Sin paridad
tty.c_cflag &= ~CSTOPB; // 1 bit de parada
tty.c_cflag &= ~CSIZE; // Limpiar máscara de tamaño
tty.c_cflag |= CS8; // 8 bits de datos
// Desactivar control de flujo por hardware y señales de módem
tty.c_cflag &= ~CRTSCTS;
tty.c_cflag |= CREAD | CLOCAL;
// Desactivar procesamiento de software (Modo crudo absoluto)
tty.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
tty.c_oflag &= ~OPOST;
tty.c_iflag &= ~(IXON | IXOFF | IXANY);
tty.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL);
// Configuración de tiempos de espera (Timeout)
tty.c_cc[VMIN] = 0; // No exigir un mínimo de bytes
tty.c_cc[VTIME] = 20; // Esperar máximo 2 segundos (20 decimas)
// Limpiar basura del búfer y aplicar la configuración
tcflush(fd, TCIFLUSH);
if (tcsetattr(fd, TCSANOW, &tty) != 0) {
perror("Error al aplicar la configuración UART");
close(fd);
return -1;
}
// Quitar el modo "No Bloqueante" para que VTIME y VMIN funcionen correctamente
fcntl(fd, F_SETFL, 0);
return fd;
}
// --- FUNCIÓN PARA ENVIAR ---
void send_uart(int fd, unsigned char *trama, int longitud) {
tcflush(fd, TCIOFLUSH); // Limpiar tubería antes de hablar
int escritos = write(fd, trama, longitud);
if (escritos < 0) {
perror("Error al escribir en el puerto");
}
}
// --- FUNCIÓN PARA RECIBIR ---
int receive_uart(int fd, unsigned char *buffer, int longitud_esperada) {
int bytes_leidos = read(fd, buffer, longitud_esperada);
return bytes_leidos;
}
// --- FUNCION PRINCIPAL ---
int main() {
int uart_fd = init_uart("/dev/serial0", B9600);
if (uart_fd == -1) return 1;
unsigned char comando[] = {0xFF, 0x01, 0x86, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79};
unsigned char respuesta[9];
while(1) {
send_uart(uart_fd, comando, sizeof(comando));
usleep(100000); // 100ms para que el sensor responda
int bytes = receive_uart(uart_fd, respuesta, 9);
if (bytes == 9) {
// 1. Calcular el valor real
int co2_ppm = (respuesta[2] * 256) + respuesta[3];
// 2. Imprimir en consola (para tu propio monitoreo)
printf("Respuesta OK: CO2 = %d ppm\n", co2_ppm);
} else {
printf("Error: Bytes recibidos = %d\n", bytes);
}
sleep(10);
}
close(uart_fd);
return 0;
}