/* 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; i<ARRAY_SIZE(comports); i++)
|
{
|
if( huart==comports[i].huart )
|
{
|
comport = &comports[i];
|
}
|
}
|
|
return comport;
|
}
|
|
comport_t *comport_init(UART_HandleTypeDef *huart, uint8_t *rxch, uint8_t *rxbuf, size_t size)
|
{
|
comport_t *comport = NULL;
|
|
if( !huart )
|
return NULL;
|
|
/* Find the corresponding comport in the array */
|
comport = comport_find(huart);
|
if( !comport )
|
return NULL;
|
|
comport->fd = 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);
|
}
|