#include "uart.h" #include "ch32v003fun.h" #define RS485_TX_EN (1 << 14) // PB14 #define RS485_RX_EN (1 << 15) // PB15 // Write multiple chars to UART int _write(__attribute__((unused)) int fd, const char *buf, int size) { for (int i = 0; i < size; i++) { while (!(USART2->STATR & USART_FLAG_TC)); // Wait for transmission complete USART2->DATAR = *buf++; // Send character } return size; } // Write a single char to UART int putchar(int c) { while (!(USART2->STATR & USART_FLAG_TC)); // Wait for transmission complete USART2->DATAR = (uint8_t)c; // Send character return (unsigned char)c; } void uart2_init(int uart_brr) { RCC->APB2PCENR |= RCC_APB2Periph_GPIOA; // Enable GPIOA on APB2 RCC->APB1PCENR |= RCC_APB1Periph_USART2; // Enable USART2 on APB1 GPIOA->CFGLR &= ~(0xf << (4 * 2)); // Clear bits for PA2 GPIOA->CFGLR |= (GPIO_Speed_10MHz | GPIO_CNF_OUT_PP_AF) << (4 * 2); // Set PA2 as AF // USART configuration: 115200 baud rate, 8 data bits, no parity, 1 stop bit USART2->CTLR1 = USART_WordLength_8b | USART_Parity_No | USART_Mode_Tx; USART2->CTLR2 = USART_StopBits_1; USART2->CTLR3 = USART_HardwareFlowControl_None; USART2->BRR = uart_brr; // Enable USART2 USART2->CTLR1 |= CTLR1_UE_Set; } void rs485_init(int uart_brr) { RCC->APB2PCENR |= RCC_APB2Periph_GPIOA | // Enable GPIOA RCC_APB2Periph_GPIOB | // Enable GPIOB RCC_APB2Periph_USART1; // Enable USART1 // configure uart1 pins (PA9=TX, PA10=RX) GPIOA->CFGHR &= ~(0xf << (4 * 1) | 0xf << (4 * 2)); // Clear PA9 & PA10 config GPIOA->CFGHR |= (GPIO_Speed_10MHz | GPIO_CNF_OUT_PP_AF) << (4 * 1); // PA9 (TX) GPIOA->CFGHR |= GPIO_CNF_IN_FLOATING << (4 * 2); // PA10 (RX) // configure rs485 direction control pins (PB14=TX_EN, PB15=RX_EN) GPIOB->CFGHR &= ~(0xf << (4 * 6) | 0xf << (4 * 7)); // Clear PB14 & PB15 config GPIOB->CFGHR |= (GPIO_Speed_10MHz | GPIO_CNF_OUT_PP) << (4 * 6); // PB14 (TX_EN) GPIOB->CFGHR |= (GPIO_Speed_10MHz | GPIO_CNF_OUT_PP) << (4 * 7); // PB15 (RX_EN) // initial state: rx mode GPIOB->BCR = RS485_TX_EN; // TX_EN low GPIOB->BSHR = RS485_RX_EN; // RX_EN high // uart1 configuration USART1->CTLR1 = USART_WordLength_8b | USART_Parity_No | USART_Mode_Tx | USART_Mode_Rx; USART1->CTLR2 = USART_StopBits_1; USART1->CTLR3 = USART_HardwareFlowControl_None; USART1->BRR = uart_brr; USART1->CTLR1 |= CTLR1_UE_Set; } void rs485_send(uint8_t *buf, uint16_t len) { // enable tx mode GPIOB->BSHR = RS485_TX_EN; // TX_EN high GPIOB->BSHR = RS485_RX_EN; // RX_EN low for (uint16_t i = 0; i < len; i++) { while (!(USART1->STATR & USART_FLAG_TXE)); USART1->DATAR = buf[i]; } while (!(USART1->STATR & USART_FLAG_TC)); // switch back to rx mode GPIOB->BCR = RS485_TX_EN; // TX_EN low GPIOB->BCR = RS485_RX_EN; // RX_EN high } uint8_t rs485_available(void) { return (USART1->STATR & USART_FLAG_RXNE) != 0; } uint8_t rs485_read(void) { return USART1->DATAR & 0xFF; }