/* RS232/TTL/RS485 communication * comport.c * * Created on: Feb 15, 2023 * Author: Think */ #include "comport.h" #include "miscdev.h" //#define CONFIG_COMPORT_DEBUG #ifdef CONFIG_COMPORT_DEBUG #define com_print(format,args...) printf(format, ##args) #else #define com_print(format,args...) do{} while(0) #endif #define ARRAY_SIZE(x) sizeof(x)/sizeof(x[0]) comport_t comports[] = { {.fd=-1, .devname="WiFi", .huart=&huart2 }, // ESP8266(WiFi)/ESP32(WiFi/BLE) {.fd=-1, .devname="RS232", .huart=&huart3 }, // RS232/TTL/MikroBUS {.fd=-1, .devname="RS485", .huart=&hlpuart1 }, // RS485 }; static inline comport_t *comport_find(UART_HandleTypeDef *huart) { comport_t *comport = NULL; int i; for(i=0; ifd = 1; comport->huart = huart; comport->rxch = rxch; rb_init(&comport->rb, rxbuf, size); return comport; } /* +----------------------------------------+ * | printf and interrupt receive functions | * +----------------------------------------+*/ /* printf callback function on USART1 */ int __io_putchar(int ch) { HAL_UART_Transmit(&huart1 , (uint8_t *)&ch, 1, 0xFFFF); return ch; } /* USART interrupt receive callback funciton */ void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) { comport_t *comport = NULL; uint8_t byte; /* Find the corresponding comport in the array */ comport = comport_find(huart); if( !comport ) { goto cleanup; } /* Check comport receive ring buffer */ if( comport->fd<0 || !comport->rb.buffer || ! rb_free_size(&comport->rb) ) { goto cleanup; } /* Receive and put the byte into receive ring buffer */ HAL_UART_Receive_IT(comport->huart, comport->rxch, 1); rb_write(&comport->rb, comport->rxch, 1); return ; cleanup: HAL_UART_Receive_IT(huart, &byte, 1); return ; } /* +------------------------+ * | UART/TTL API functions | * +------------------------+*/ comport_t *comport_open(UART_HandleTypeDef *huart) { comport_t *comport = NULL; if( !huart ) return NULL; /* Find the corresponding comport in the array */ comport = comport_find(huart); if( comport ) comport->fd = 1; return comport; } void comport_flush(comport_t *comport) { if( !comport || !comport->huart) return; if( comport->rb.buffer ) { rb_clear( &comport->rb ); } return; } void comport_term(comport_t *comport) { if( !comport || !comport->huart) return; comport->fd = -1; if( comport->rb.buffer ) { rb_clear( &comport->rb ); } return; } int comport_send(comport_t *comport, char *data, int bytes) { if( !comport || !data || bytes<=0 ) return -1; com_print("Send %d bytes data: %s\r\n", bytes, data); HAL_UART_Transmit(comport->huart, (uint8_t *)data, bytes, 0xFFFF); return bytes; } int comport_recv(comport_t *comport, char *buf, int size, uint32_t timeout) { uint32_t tickstart = 0; size_t bytes = 0; if( !comport || !buf || size<=0 ) return -1; if( !comport->rb.buffer ) return -2; tickstart = HAL_GetTick(); while((HAL_GetTick() - tickstart) < timeout) { bytes = rb_data_size(&comport->rb); HAL_Delay( 10 ); /* comport received data before but not receive in 10ms now, maybe data receive over */ if( bytes>0 && rb_data_size(&comport->rb)==bytes ) { break; } } bytes = rb_data_size(&comport->rb); if( !bytes ) { return 0; } bytes = bytes>size ? size : bytes; rb_read(&comport->rb, (uint8_t *)buf, bytes); com_print("Receive %d bytes data: %s\r\n", bytes, buf); return bytes; } /* +------------------------+ * | RS485 API functions | * +------------------------+*/ /* Direction Pin set to be high level will be send mode, and low level will be receive mode */ #define rs485_set_dirTx() HAL_GPIO_WritePin(RS485_Dir_GPIO_Port, RS485_Dir_Pin, GPIO_PIN_SET) #define rs485_set_dirRx() HAL_GPIO_WritePin(RS485_Dir_GPIO_Port, RS485_Dir_Pin, GPIO_PIN_RESET) comport_t *rs485_open(UART_HandleTypeDef *huart) { return comport_find(huart); } void rs485_term(comport_t *comport) { return comport_term(comport); } int rs485_send(comport_t *comport, char *data, int bytes) { int rv; rs485_set_dirTx(); rv = comport_send(comport, data, bytes); rs485_set_dirRx(); return rv; } int rs485_recv(comport_t *comport, char *buf, int size, uint32_t timeout) { rs485_set_dirRx(); return comport_recv(comport, buf, size, timeout); }