STM32–USART FIFO

18 Апреля 2011 К комментариям

Перенес реализацию FIFO буфера с STM8L, вроде работает Улыбка, пока не уверен только на счет правильности в чтении ошибок и при передачи 9-бит нужно поправить код.

Код для проверки работы (простой эхо-ответ):

//-----------------------------------------------------------------------------
int main(void)
{
	uint8_t rx_data;

	// инициализируем систему тактирования
	RCC_Configuration();

	// инициализируем контроллер прерываний
	NVIC_Configuration();

	// настраиваем линии ввода-вывода
	PIN_CONFIGURATION(USART1_RXD);
	PIN_CONFIGURATION(USART1_TXD);
	PIN_CONFIGURATION(PIN_TEST);

	// конфигурируем USART1
	mcu_usart1_init(38400);

	while (1)
	{
		// ожидаем приема данных
		while (mcu_usart1_fifo_receive(&rx_data) & USART_FIFO_NO_DATA)
		{
		}
		// передаем принятый байт
		mcu_usart1_fifo_transmit(rx_data);
	}

	return 0;
}

Реализация самого буфера:

/*
 * File: mcu_usat.c
 * Date: 18.04.2011
 * Denis Zheleznjakov http://ziblog.ru
 */

#include "mcu_usart.h"

struct usart_fifo
{
	volatile uint8_t rx_last_error;
	volatile uint8_t rx_buffer[USART_RX_BUFFER_SIZE];
	volatile uint8_t rx_buffer_head;
	volatile uint8_t rx_buffer_tail;
	volatile uint8_t tx_buffer[USART_TX_BUFFER_SIZE];
	volatile uint8_t tx_buffer_head;
	volatile uint8_t tx_buffer_tail;
} usart1_fifo;

//------------------------------------------------------------------------------
void mcu_usart1_init(uint32_t baud_rate)
{
	USART_InitTypeDef USART_InitStructure;

	// инициализируем буфер
	usart1_fifo.rx_buffer_head = 0;
	usart1_fifo.rx_buffer_tail = 0;
	usart1_fifo.rx_last_error = 0;
	usart1_fifo.tx_buffer_head = 0;
	usart1_fifo.tx_buffer_tail = 0;

	// разрешаем тактирование модуля
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);

	// конфигурируем USART1
	USART_InitStructure.USART_BaudRate = baud_rate;
	USART_InitStructure.USART_WordLength = USART_WordLength_8b;
	USART_InitStructure.USART_StopBits = USART_StopBits_1;
	USART_InitStructure.USART_Parity = USART_Parity_No;
	USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
	USART_InitStructure.USART_HardwareFlowControl
			= USART_HardwareFlowControl_None;

	USART_Init(USART1, &USART_InitStructure);

	// разрешаем прерывания по приёму
	USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);

	// разрешаем работу модуля
	USART_Cmd(USART1, ENABLE);
}

//------------------------------------------------------------------------------
void mcu_usart1_fifo_transmit(uint8_t data)
{
	uint8_t tx_head;

	tx_head = (uint8_t)((usart1_fifo.tx_buffer_head + 1) & (uint8_t)(
			USART_TX_BUFFER_SIZE - 1));

	while (tx_head == usart1_fifo.tx_buffer_tail)
	{
	}

	usart1_fifo.tx_buffer[tx_head] = data;
	usart1_fifo.tx_buffer_head = tx_head;

	USART_ITConfig(USART1, USART_IT_TXE, ENABLE);
}

//------------------------------------------------------------------------------
void handler_usart1_tx(void)
{
	uint8_t tx_tail;
	uint8_t tx_head;

	tx_head = usart1_fifo.tx_buffer_head;
	tx_tail = usart1_fifo.tx_buffer_tail;

	if (tx_head != tx_tail++)
	{
		tx_tail &= USART_TX_BUFFER_SIZE - 1;

		usart1_fifo.tx_buffer_tail = tx_tail;

		USART1->DR = usart1_fifo.tx_buffer[tx_tail];
	}
	else
	{
		USART_ITConfig(USART1, USART_IT_TXE, DISABLE);
	}
}

//------------------------------------------------------------------------------
uint8_t mcu_usart1_fifo_receive(uint8_t * data)
{
	uint8_t rx_head;
	uint8_t rx_tail;

	rx_head = usart1_fifo.rx_buffer_head;

	if (rx_head == usart1_fifo.rx_buffer_tail)
		return USART_FIFO_NO_DATA;

	rx_tail = (uint8_t)((usart1_fifo.rx_buffer_tail + 1) & (uint8_t)(
			USART_RX_BUFFER_SIZE - 1));

	usart1_fifo.rx_buffer_tail = rx_tail;

	*data = usart1_fifo.rx_buffer[rx_tail];

	return usart1_fifo.rx_last_error;
}

//------------------------------------------------------------------------------
void handler_usart1_rx(void)
{
	uint16_t status;
	uint8_t rx_data;
	uint8_t rx_last_error;
	uint8_t rx_head;

	status = USART1->SR;
	rx_data = USART1->DR;
	rx_last_error = 0;

	if (status & USART_SR_FE)
		rx_last_error |= USART_FIFO_ERROR_FRAME;

	if (status & USART_SR_ORE)
		rx_last_error |= USART_FIFO_ERROR_OVERRUN;

	if (status & USART_SR_NE)
		rx_last_error |= USART_FIFO_ERROR_NOISE;

	rx_head = (uint8_t)((usart1_fifo.rx_buffer_head + 1) & (uint8_t)(
			USART_RX_BUFFER_SIZE - 1));

	if (rx_head == usart1_fifo.rx_buffer_tail)
	{
		rx_last_error |= USART_FIFO_ERROR_BUFFER_OVERFLOW;
	}
	else
	{
		usart1_fifo.rx_buffer[rx_head] = rx_data;
		usart1_fifo.rx_buffer_head = rx_head;
	}

	usart1_fifo.rx_last_error = rx_last_error;
}

проект целиком (для STM32F103CB):



comments powered by Disqus