Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- //
- // Драйвер UART
- //
- #include "uart.h"
- #include "gpio.h"
- #include "clock.h"
- #include <stm32f4xx.h>
- #include <string.h>
- #define BUFFER_SIZE 16
- typedef struct
- {
- USART_TypeDef * USART;
- uint32_t (* GetClock)(void);
- volatile uint32_t * RCCRegister;
- uint32_t RCCMask;
- IRQn_Type IRQn;
- uint32_t AlternateFunction;
- TPin TX;
- TPin RX;
- } TUartPort;
- typedef struct
- {
- void (* onBreak)(uint32_t);
- void (* onReceive)(uint32_t, uint8_t);
- void (* onTransmitted)(uint32_t);
- void (* onTransmitCompleted)(uint32_t);
- uint32_t Index;
- uint8_t Buffer[BUFFER_SIZE];
- uint32_t IndexToSend;
- uint32_t IndexToAdd;
- bool Completed;
- } TUartState;
- // Таблица UART'ов
- static const TUartPort Ports[] = {
- { USART1, &clock_GetAPB2, &RCC->APB2ENR, RCC_APB2ENR_USART1EN, USART1_IRQn, 7, {PA, 9}, {PA, 10} },
- { USART2, &clock_GetAPB1, &RCC->APB1ENR, RCC_APB1ENR_USART2EN, USART2_IRQn, 7, {PD, 5}, {PD, 6} },
- { USART3, &clock_GetAPB1, &RCC->APB1ENR, RCC_APB1ENR_USART3EN, USART3_IRQn, 7, {PB, 10}, {PB, 11} },
- };
- static TUartState States[sizeof(Ports) / sizeof(Ports[0])];
- static const int PortCount = sizeof(Ports) / sizeof(Ports[0]);
- // Оповестить о Break
- static void uart_onBreak(TUart Uart)
- {
- if(States[Uart].onBreak) States[Uart].onBreak(States[Uart].Index);
- }
- // Принять байт
- static void uart_onReceive(TUart Uart, uint8_t Data)
- {
- if(States[Uart].onReceive) States[Uart].onReceive(States[Uart].Index, Data);
- }
- // Оповестить о опустошении передающего буфера
- static void uart_onTransmitted(TUart Uart)
- {
- if(States[Uart].onTransmitted) States[Uart].onTransmitted(States[Uart].Index);
- }
- // Оповестить о завершении передачи
- static void uart_onTransmitCompleted(TUart Uart)
- {
- if(States[Uart].onTransmitCompleted) States[Uart].onTransmitCompleted(States[Uart].Index);
- }
- void USART_IRQHandler(TUart Uart)
- {
- USART_TypeDef * USART = Ports[Uart].USART;
- uint32_t Status = USART->SR;
- // Принят байт
- if(Status & USART_SR_RXNE)
- {
- uint8_t Data = USART->DR;
- if(Status & USART_SR_FE)
- {
- uart_onBreak(Uart);
- }
- else
- {
- uart_onReceive(Uart, Data);
- }
- }
- // Буфер пуст
- if(Status & USART_SR_TXE)
- {
- if(States[Uart].IndexToSend != States[Uart].IndexToAdd)
- {
- uart_SendByte(Uart, States[Uart].Buffer[States[Uart].IndexToSend]);
- States[Uart].IndexToSend++;
- if(States[Uart].IndexToSend >= BUFFER_SIZE) States[Uart].IndexToSend = 0;
- }
- else
- {
- States[Uart].Completed = true;
- uart_onTransmitted(Uart);
- }
- }
- if(Status & USART_SR_TC)
- {
- if(States[Uart].IndexToSend == States[Uart].IndexToAdd)
- {
- USART->CR1 &= ~(USART_CR1_TXEIE | USART_CR1_TCIE); // Transmitter empty interrupt enable
- uart_onTransmitCompleted(Uart);
- }
- }
- }
- // Прерывание от USART
- void USART1_IRQHandler(void) { USART_IRQHandler(UART1); }
- void USART2_IRQHandler(void) { USART_IRQHandler(UART2); }
- void USART3_IRQHandler(void) { USART_IRQHandler(UART3); }
- // Инициализация модуля USART
- // Аргументы: 2
- // Index - номер модуля
- // BaudRate - скорость
- // Результаты: нет
- void uart_Init(TUart Uart, uint32_t BaudRate)
- {
- if(Uart >= PortCount) return;
- memset(&States[0], 0, sizeof(States));
- {
- USART_TypeDef * USART = Ports[Uart].USART;
- // Тактирование
- *Ports[Uart].RCCRegister |= Ports[Uart].RCCMask;
- USART->CR1 = USART_CR1_UE | // USART Enable
- 0;
- uart_SetBaudrate(Uart, BaudRate);
- NVIC_EnableIRQ(Ports[Uart].IRQn);
- }
- // Выводы - режим альтернативной функции
- gpio_HighLevel(&Ports[Uart].TX);
- gpio_SetAlternateFunction(&Ports[Uart].TX, Ports[Uart].AlternateFunction);
- gpio_SetAlternateFunction(&Ports[Uart].RX, Ports[Uart].AlternateFunction);
- }
- // Установить номер порта (для обратной связи)
- void uart_SetPortIndex(TUart Uart, uint32_t Index)
- {
- if(Uart >= PortCount) return;
- States[Uart].Index = Index;
- }
- // Режим GPIO при передаче (заданное состояние линии)
- void uart_GPIOMode(TUart Uart, bool Value)
- {
- if(Uart >= PortCount) return;
- if(Value)
- {
- gpio_HighLevel(&Ports[Uart].TX);
- }
- else
- {
- gpio_LowLevel(&Ports[Uart].TX);
- }
- gpio_DigitalOutput(&Ports[Uart].TX);
- }
- // Количество стоповых бит
- void uart_StopBits(TUart Uart, TUartStopBits StopBits)
- {
- USART_TypeDef * USART;
- if(Uart >= PortCount) return;
- USART = Ports[Uart].USART;
- USART->CR2 &= ~USART_CR2_STOP;
- switch(StopBits)
- {
- case STOP_BITS_0_5: // 0b01
- USART->CR2 |= USART_CR2_STOP_0;
- break;
- case STOP_BITS_1: // 0b00
- break;
- case STOP_BITS_1_5: // 0b11
- USART->CR2 |= USART_CR2_STOP_0 | USART_CR2_STOP_1;
- break;
- case STOP_BITS_2: // 0b10
- USART->CR2 |= USART_CR2_STOP_1;
- break;
- }
- }
- // Разрешить прим
- void uart_ReceiveEnable(TUart Uart, bool Enable)
- {
- USART_TypeDef * USART;
- if(Uart >= PortCount) return;
- USART = Ports[Uart].USART;
- if(Enable)
- {
- USART->CR1 |= USART_CR1_RXNEIE | // RXNE interrupt enable
- USART_CR1_RE | // Receiver enable
- 0;
- }
- else
- {
- USART->CR1 &= ~(USART_CR1_RXNEIE | // RXNE interrupt enable
- USART_CR1_RE | // Receiver enable
- 0);
- }
- }
- // Разрешить передачу
- void uart_TransmitEnable(TUart Uart, bool Enable)
- {
- USART_TypeDef * USART;
- if(Uart >= PortCount) return;
- USART = Ports[Uart].USART;
- if(Enable)
- {
- USART->CR1 |= USART_CR1_TCIE | // Transmission complete interrupt enable
- USART_CR1_TE | // Transmitter enable
- 0;
- }
- else
- {
- USART->CR1 &= ~(USART_CR1_TCIE | // Transmission complete interrupt enable
- USART_CR1_TE | // Transmitter enable
- 0);
- }
- }
- // Режим передачи данных
- void uart_UARTMode(TUart Uart)
- {
- if(Uart >= PortCount) return;
- gpio_SetAlternateFunction(&Ports[Uart].TX, Ports[Uart].AlternateFunction);
- }
- // Отправка байта
- void uart_SendByte(TUart Uart, uint8_t Data)
- {
- if(Uart >= PortCount) return;
- States[Uart].Completed = false;
- Ports[Uart].USART->DR = Data;
- if(!(Ports[Uart].USART->CR1 & USART_CR1_TXEIE))
- Ports[Uart].USART->CR1 |= USART_CR1_TXEIE | USART_CR1_TCIE; // Transmitter empty interrupt enable
- }
- static int32_t uart_GetFreeBytesCount(TUart Uart)
- {
- if(States[Uart].IndexToAdd >= States[Uart].IndexToSend)
- {
- return BUFFER_SIZE - (States[Uart].IndexToAdd - States[Uart].IndexToSend);
- }
- else
- {
- return BUFFER_SIZE - (BUFFER_SIZE + States[Uart].IndexToAdd - States[Uart].IndexToSend);
- }
- }
- // Отправка буфера
- void uart_Send(TUart Uart, uint8_t * Data, int32_t BytesToSend, int32_t * BytesSended)
- {
- int32_t Sended = 0;
- int32_t FreeBytes = 0;
- int i;
- if(BytesSended) *BytesSended = 0;
- if(Uart >= PortCount) return;
- FreeBytes = uart_GetFreeBytesCount(Uart);
- {
- uint8_t * Buffer = &States[Uart].Buffer[0];
- uint32_t Index = States[Uart].IndexToAdd;
- if(BytesToSend > FreeBytes - 1) BytesToSend = FreeBytes - 1;
- // Добавим
- for(i = 0; i < BytesToSend; i++)
- {
- Buffer[Index] = Data[i];
- Sended++;
- Index++;
- if(Index >= BUFFER_SIZE) Index = 0;
- }
- States[Uart].IndexToAdd = Index;
- }
- // Если ждМ, то отправим
- if(States[Uart].Completed && Sended)
- {
- uart_SendByte(Uart, States[Uart].Buffer[States[Uart].IndexToSend]);
- States[Uart].IndexToSend++;
- if(States[Uart].IndexToSend >= BUFFER_SIZE) States[Uart].IndexToSend = 0;
- }
- *BytesSended = Sended;
- }
- // Установить скорость передачи
- void uart_SetBaudrate(TUart Uart, uint32_t Baudrate)
- {
- USART_TypeDef * USART;
- if(Uart >= PortCount) return;
- USART = Ports[Uart].USART;
- // Ждм завершения передачи
- while(!(USART->SR & USART_SR_TC)) {}
- Ports[Uart].USART->BRR = Ports[Uart].GetClock() / Baudrate;
- }
- // Установить обработчик
- void uart_SetHandler(TUart Uart, TUartEvent Event, void * Handler)
- {
- if(Uart >= PortCount) return;
- switch(Event)
- {
- case UART_EVENT_ONBREAK: States[Uart].onBreak = (void(*)(uint32_t))Handler; break;
- case UART_EVENT_ONRECEIVE: States[Uart].onReceive = (void(*)(uint32_t, uint8_t))Handler; break;
- case UART_EVENT_ONTRANSMITTED: States[Uart].onTransmitted = (void(*)(uint32_t))Handler; break;
- case UART_EVENT_ONTRANSMITCOMPLETED: States[Uart].onTransmitCompleted = (void(*)(uint32_t))Handler; break;
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement