Implemented RS485 driver (TX only)
This commit is contained in:
parent
c01cb4f742
commit
2ca6c41260
|
@ -15,6 +15,7 @@
|
||||||
#include <fxp_basic.h>
|
#include <fxp_basic.h>
|
||||||
|
|
||||||
#include "led_chplex.h"
|
#include "led_chplex.h"
|
||||||
|
#include "rs485.h"
|
||||||
#include "charge_pump.h"
|
#include "charge_pump.h"
|
||||||
#include "power_switch.h"
|
#include "power_switch.h"
|
||||||
|
|
||||||
|
@ -45,6 +46,9 @@ static void init_clock(void)
|
||||||
|
|
||||||
// Port B is needed for the LEDs
|
// Port B is needed for the LEDs
|
||||||
rcc_periph_clock_enable(RCC_GPIOB);
|
rcc_periph_clock_enable(RCC_GPIOB);
|
||||||
|
|
||||||
|
// USART1 is used for RS485
|
||||||
|
rcc_periph_clock_enable(RCC_USART1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -108,6 +112,7 @@ int main(void)
|
||||||
init_clock();
|
init_clock();
|
||||||
init_gpio();
|
init_gpio();
|
||||||
|
|
||||||
|
rs485_init();
|
||||||
charge_pump_init();
|
charge_pump_init();
|
||||||
power_switch_init();
|
power_switch_init();
|
||||||
|
|
||||||
|
@ -116,6 +121,8 @@ int main(void)
|
||||||
|
|
||||||
init_systick(1000);
|
init_systick(1000);
|
||||||
|
|
||||||
|
rs485_enqueue("LNSC-2420 v" VERSION " initialized.\n");
|
||||||
|
|
||||||
// triggered every 1 ms
|
// triggered every 1 ms
|
||||||
while (1) {
|
while (1) {
|
||||||
|
|
||||||
|
|
|
@ -35,4 +35,12 @@
|
||||||
#define ANALOG_INPUT_I_SOLAR 3
|
#define ANALOG_INPUT_I_SOLAR 3
|
||||||
#define ANALOG_INPUT_I_LOAD 4
|
#define ANALOG_INPUT_I_LOAD 4
|
||||||
|
|
||||||
|
/* RS485 */
|
||||||
|
|
||||||
|
#define RS485_PORT GPIOB
|
||||||
|
|
||||||
|
#define RS485_DE_PIN GPIO5 // High = Driver enabled
|
||||||
|
#define RS485_TX_PIN GPIO6
|
||||||
|
#define RS485_RX_PIN GPIO7
|
||||||
|
|
||||||
#endif // PINOUT_H
|
#endif // PINOUT_H
|
||||||
|
|
122
src/rs485.c
Normal file
122
src/rs485.c
Normal file
|
@ -0,0 +1,122 @@
|
||||||
|
#include <libopencm3/stm32/usart.h>
|
||||||
|
#include <libopencm3/stm32/gpio.h>
|
||||||
|
#include <libopencm3/cm3/nvic.h>
|
||||||
|
|
||||||
|
#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();
|
||||||
|
}
|
||||||
|
}
|
9
src/rs485.h
Normal file
9
src/rs485.h
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
#ifndef RS485_H
|
||||||
|
#define RS485_H
|
||||||
|
|
||||||
|
void rs485_init(void);
|
||||||
|
void rs485_periodic(void);
|
||||||
|
|
||||||
|
void rs485_enqueue(const char *str);
|
||||||
|
|
||||||
|
#endif // RS485_H
|
Loading…
Reference in a new issue