Загрузка данных


#include "MDR32Fx.h"
#include "MDR32F9Qx_port.h"
#include "MDR32F9Qx_rst_clk.h"

// Светодиоды (порт A, линии 0–7)
#define LED_PORT        MDR_PORTA
#define RX_BUF_SIZE     64

// Кольцевой буфер для приёма
volatile uint8_t rx_buf[RX_BUF_SIZE];
volatile uint8_t rx_head = 0;
volatile uint8_t rx_tail = 0;
volatile uint8_t rx_count = 0;

// ---------------------------------------------------------------------
// Инициализация светодиодов (порт A как выход)
void init_leds(void) {
    RST_CLK_PCLKcmd(RST_CLK_PCLK_PORTA, ENABLE);
    
    PORT_InitTypeDef PortInit;
    PORT_StructInit(&PortInit);   // значения по умолчанию
    PortInit.PORT_Pin   = 0xFF;
    PortInit.PORT_OE    = PORT_OE_OUT;
    PortInit.PORT_FUNC  = PORT_FUNC_PORT;
    PortInit.PORT_MODE  = PORT_MODE_DIGITAL;
    PortInit.PORT_SPEED = PORT_SPEED_SLOW;
    PORT_Init(LED_PORT, &PortInit);
    
    PORT_Write(LED_PORT, 0x00);   // все светодиоды выключены
}

// ---------------------------------------------------------------------
// Инициализация UART1 (PB5 – TX, PB6 – RX) на 57600 бод, 8N1
void init_uart(void) {
    // Включаем тактирование порта B и UART1
    RST_CLK_PCLKcmd(RST_CLK_PCLK_PORTB | RST_CLK_PCLK_UART1, ENABLE);

    // Настройка TX (PB5) как альтернативной функции UART
    PORT_InitTypeDef PortInit;
    PORT_StructInit(&PortInit);
    PortInit.PORT_Pin   = PORT_Pin_5;
    PortInit.PORT_OE    = PORT_OE_OUT;
    PortInit.PORT_FUNC  = PORT_FUNC_ALTER;
    PortInit.PORT_MODE  = PORT_MODE_DIGITAL;
    PortInit.PORT_SPEED = PORT_SPEED_FAST;
    PORT_Init(MDR_PORTB, &PortInit);

    // Настройка RX (PB6) как альтернативной функции UART
    PortInit.PORT_Pin   = PORT_Pin_6;
    PortInit.PORT_OE    = PORT_OE_IN;
    PORT_Init(MDR_PORTB, &PortInit);

    // --- Прямая настройка регистров UART1 ---
    // Настройка скорости: UARTCLK = HCLK = 8 МГц
    // Делитель = 8000000 / (16 * 57600) = 8.68
    // Целая часть = 8, дробная = 0.68 * 64 ≈ 44
    MDR_UART1->IBRD = 8;
    MDR_UART1->FBRD = 44;

    // Формат кадра: 8 бит, 1 стоп, без паритета, FIFO отключен
    MDR_UART1->LCR_H = (3 << 5)    // длина слова 8 бит (0b11)
                      | (0 << 4)    // FIFO выключен
                      | (0 << 3)    // 1 стоп-бит
                      | (0 << 2)    // без паритета
                      | (0 << 1)    // проверка паритета выключена
                      | (0 << 0);   // разрыв линии выключен

    // Включение UART (приём, передача) и прерывания по приёму
    MDR_UART1->CR = (1 << 9)   // RXE – приём разрешён
                  | (1 << 8)   // TXE – передача разрешена
                  | (1 << 0);  // UARTEN – модуль включен

    // Разрешить прерывание по приёму в регистре маски
    MDR_UART1->IMSC |= (1 << 4);   // RXIM

    // Включить прерывание в NVIC
    NVIC_EnableIRQ(UART1_IRQn);
}

// ---------------------------------------------------------------------
// Обработчик прерывания UART1 – приём байта
void UART1_IRQHandler(void) {
    // Проверяем, что прерывание вызвано приёмом (RX)
    if (MDR_UART1->MIS & (1 << 4)) {
        uint8_t data = MDR_UART1->DR;   // чтение сбрасывает прерывание
        
        rx_buf[rx_head] = data;
        rx_head = (rx_head + 1) % RX_BUF_SIZE;
        if (rx_count < RX_BUF_SIZE) rx_count++;
    }
}

// ---------------------------------------------------------------------
// Вспомогательная функция: получить байт из кольцевого буфера по смещению
uint8_t get_byte_from_buf(uint8_t index) {
    return rx_buf[(rx_tail + index) % RX_BUF_SIZE];
}

// ---------------------------------------------------------------------
// Главная функция
int main(void) {
    init_leds();
    init_uart();

    while (1) {
        // Пока в буфере есть хотя бы 7 байт (заголовок 5 + данные 1 + CRC 1)
        while (rx_count >= 7) {
            // Проверяем заголовок
            if (get_byte_from_buf(0) == 0xFF &&
                get_byte_from_buf(1) == 0xFE &&
                get_byte_from_buf(2) == 0xFF &&
                get_byte_from_buf(3) == 0x88 &&
                get_byte_from_buf(4) == 0x15) {
                
                uint8_t data = get_byte_from_buf(5);
                uint8_t crc  = get_byte_from_buf(6);
                
                // Вычисляем CRC: сумма всех 7 байт должна быть 0x00 (по модулю 256)
                uint8_t sum = 0;
                for (int i = 0; i < 7; i++) sum += get_byte_from_buf(i);
                
                if (sum == 0) {
                    PORT_Write(LED_PORT, data);   // отображаем данные на светодиодах
                }
                
                // Удаляем обработанный пакет из буфера
                rx_tail = (rx_tail + 7) % RX_BUF_SIZE;
                rx_count -= 7;
            } else {
                // Сдвигаем буфер на 1 байт
                rx_tail = (rx_tail + 1) % RX_BUF_SIZE;
                rx_count--;
            }
        }
        // Небольшая задержка, чтобы не нагружать ядро
        for (volatile int i = 0; i < 10000; i++);
    }
}