#include #include #include #include "pinout.h" #include "rs485.h" #define RS485_BUFFER_SIZE 128 static volatile char debugBuffer[RS485_BUFFER_SIZE]; static volatile uint16_t readPos, writePos; static volatile uint8_t bufferFull, bufferEmpty, usartActive; void rs485_init(void) { // initialize the ring buffer readPos = 0; writePos = 0; bufferFull = 0; bufferEmpty = 1; usartActive = 0; /* Initialize GPIOs */ // RS485 drive enable signal gpio_clear(RS485_PORT, RS485_DE_PIN); gpio_mode_setup(RS485_PORT, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, RS485_DE_PIN); // RX and TX pins gpio_mode_setup(RS485_PORT, GPIO_MODE_AF, GPIO_PUPD_NONE, RS485_TX_PIN | RS485_RX_PIN); gpio_set_af(RS485_PORT, GPIO_AF0, RS485_TX_PIN | RS485_RX_PIN); // enable interrupt nvic_enable_irq(NVIC_USART1_IRQ); /* Setup USART1 parameters. */ usart_set_baudrate(USART1, 115200); usart_set_databits(USART1, 8); usart_set_stopbits(USART1, USART_CR2_STOPBITS_1); usart_set_mode(USART1, USART_MODE_TX); usart_set_parity(USART1, USART_PARITY_NONE); usart_set_flow_control(USART1, USART_FLOWCONTROL_NONE); /* Enable the USART. */ usart_enable(USART1); /* Enable the USART1 TX Interrupt */ usart_enable_tx_interrupt(USART1); usart_enable_tx_complete_interrupt(USART1); } static void rs485_transfer(void) { if(bufferEmpty) { usart_disable_tx_interrupt(USART1); usartActive = 0; return; } usart_send(USART1, debugBuffer[readPos]); readPos++; if(readPos == RS485_BUFFER_SIZE) { readPos = 0; } if(readPos == writePos) { bufferEmpty = 1; } bufferFull = 0; usart_enable_tx_interrupt(USART1); } void usart1_isr(void) { if(USART1_ISR & USART_ISR_TXE) { rs485_transfer(); } if(USART1_ISR & USART_ISR_TC) { USART1_ICR |= USART_ICR_TCCF; if(!usartActive) { gpio_clear(RS485_PORT, RS485_DE_PIN); } } } void rs485_enqueue(const char *str) { while(*str) { if(bufferFull) { break; } debugBuffer[writePos] = *str; writePos++; if(writePos == RS485_BUFFER_SIZE) { writePos = 0; } if(writePos == readPos) { bufferFull = 1; } bufferEmpty = 0; str++; } if(!usartActive) { usartActive = 1; gpio_set(RS485_PORT, RS485_DE_PIN); rs485_transfer(); } } void rs485_deepsleep_prepare(void) { // force the transceiver to RX mode gpio_clear(RS485_PORT, RS485_DE_PIN); } void rs485_deepsleep_resume(void) { // if a transmission is still in progress, switch to TX mode again if(usartActive) { gpio_set(RS485_PORT, RS485_DE_PIN); } }