Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Передача на UART1 (LPC2146)
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > ARM
meister
Никак не могу сделать простую передачу на UART1.

Код
    CODE32

    EXTERN fwu_uart1_impl
    PUBLIC fwu_uart1_asm

fwu_uart1_asm: // я уж думал spurious interrupts мешали.
    SUB lr, lr, #4;
    STMFD sp!, {lr};
    MRS lr, SPSR;
    TST lr, #I_Bit;
    BNE fwu_uart1_asm_ret;

    BL fwu_uart1_impl;

fwu_uart1_asm_ret:
    LDMFD sp!, {pc}^;

//////////////////////////////////////

    struct my_dataseg_t
    {
        u8_t volatile tx;        
        bool volatile tx_ready;
        bool volatile tx_empty;
    };

    __no_init my_dataseg_t ds;

    unsigned const serSOURCE_THRE = 0x02;
    unsigned const serSOURCE_RX_TIMEOUT = 0x0C;
    unsigned const serSOURCE_ERROR = 0x06;
    unsigned const serSOURCE_RX = 0x04;
    unsigned const serINTERRUPT_SOURCE_MASK = 0x0F;

__arm void fwu_uart1_impl(void)
{
    switch (U1IIR & serINTERRUPT_SOURCE_MASK)
    {
    case serSOURCE_ERROR:
        ds.rx_error = true;
        ds.rx_ready = true;
        break;
        
    case serSOURCE_THRE:
        if (ds.tx_ready)
        {
            U1THR = ds.tx;
        }
        else
        {
            ds.tx_empty = true;
        }
        ds.tx_ready = false;            
        break;

    case serSOURCE_RX_TIMEOUT:
    case serSOURCE_RX:
        ds.rx = U1RBR;
        ds.rx_error = false;
        ds.rx_ready = true;
        break;

    default:
        break;
    }

    VICVectAddr = 0;
}

    void send_byte(u8_t B)
    {
        while (true)
        {
            __disable_interrupt();
            if (ds.tx_empty)
            {
                U1THR = b;
                ds.tx_empty = false;
                ds.tx_ready = false;
                __enable_interrupt();
                return;
            }
            else if (!ds.tx_ready)
            {
                ds.tx = b;
                ds.tx_empty = false;
                ds.tx_ready = true;
                __enable_interrupt();
                return;
            }
            else
            {
                __enable_interrupt();
                while (ds.tx_ready) { power_off(); }
            }
        }
    }

    void start_transmit(void)
    {
        U1IER = 0;
        line_driver(true);
        
        ds.tx_ready = false;
        ds.tx_empty = true;
      
        U1FCR_bit.FCRFE = 1;  // FIFO Enable
        U1FCR_bit.TFR = 1;    // TX FIFO RESET
        U1IER_bit.THREIE = 1; // THRE Interrupt Enable
        U1TER_bit.TxEn = 1;            
    }

    void power_off(void) {}

////////////////////////////////////
Вот так передаю.

        start_transmit();

        u8_t const buf[] = {1, 2, 3, 4, 5, 6, 7, 8, '?'};
        for (u8_t const * i = BEGIN_OF_ARY(buf); i != END_OF_ARY(buf); ++i)
        {
            send_byte(*i);
        }

        while (true) {} // тут останавливается и ничего больше не передается. [/font]


Передается только первый байт. Причем в ds.tx остается последний передаваемый байт - '?'. Если отладчик поставить на U1THR = b; - он там остановится. Если нажимать "продолжить" - передаются все байты. Подскажите пожалуйста -- с утра голову ломаю.
Alex03
Если в 214х UART такой же как и в более младших (а это скорее всего так ибо совместимость с '550) то как минимум вот сюда посмотрите:
Код
        U1FCR_bit.FCRFE = 1;  // FIFO Enable
        U1FCR_bit.TFR = 1;    // TX FIFO RESET


FCR не доступен по чтению, поэтому чтение/модификация/запись к нему не катит.
SanvaldYV
Код
void send_byte(u8_t B)
    {
        while (true)
        {
            __disable_interrupt();
            if (ds.tx_empty)
            {
                U1THR = b;
                ds.tx_empty = false;
                ds.tx_ready = false;
                __enable_interrupt();
                return;
            }
            else if (!ds.tx_ready)
            {
                ds.tx = b;
                ds.tx_empty = false;
                ds.tx_ready = true;
                __enable_interrupt();
                return;
            }
            else
            {
                __enable_interrupt();
                while (ds.tx_ready) { power_off(); }
            }
        }
    }


Возможно, причина в том, что вы разрешаете прерывания через какое то время после "U1THR = b" и прерывание по опустошению FIFO передатчика просто пропускается, в результате у вас передается только один символ - 'b'.

Цитата(Alex03 @ Dec 10 2007, 16:40) *
Если в 214х UART такой же как и в более младших (а это скорее всего так ибо совместимость с '550) то как минимум вот сюда посмотрите:
Код
        U1FCR_bit.FCRFE = 1;  // FIFO Enable
        U1FCR_bit.TFR = 1;    // TX FIFO RESET


FCR не доступен по чтению, поэтому чтение/модификация/запись к нему не катит.


И что, если не доступен, а что не так здесь?
Сергей Борщ
Цитата(Юрий Санвальд @ Dec 10 2007, 16:14) *
И что, если не доступен, а что не так здесь?
То, что U1FCR_bit.FCRFE = 1; эквивалентно U1FCR |= ( 1<< FCRFE);, а поскольку регистр недоступен для чтения - в результате в него запишется что-то непредсказуемое с единичкой в бите FCRFE. Поскольку стандартные заголовочные файлы не содержат описания битов, либо дописывать свои и делать RS232_UART->FCR = (0 << UART_RTLS) | (1 << UART_TFR) | (1 << UART_RFR) | (1 << UART_FCRFE); // enable and reset FIFO, 4-bytes int level
либо писать
Код
{
         __uartfcriir_bits Tmp;
        Tmp.FCRFE = 1;        // Enable FIFO
        Tmp.RFR = 1;        // Reset Rx FIFO
        Tmp.TFR = 1;        // Reset Rx FIFO
        Tmp.RTLS = 0;        // 1 byte FIFO
        U1FCR_bit = Tmp;
    }
SanvaldYV
Цитата(Сергей Борщ @ Dec 10 2007, 18:36) *
То, что U1FCR_bit.FCRFE = 1; эквивалентно U1FCR |= ( 1<< FCRFE);, а поскольку регистр недоступен для чтения - в результате в него запишется что-то непредсказуемое с единичкой в бите FCRFE.


Мдя, чето я не подумал... 05.gif
Alex03
Цитата(Сергей Борщ @ Dec 10 2007, 20:36) *
То, что U1FCR_bit.FCRFE = 1; эквивалентно U1FCR |= ( 1<< FCRFE);, а поскольку регистр недоступен для чтения - в результате в него запишется что-то непредсказуемое с единичкой в бите FCRFE.


Я бы сказал что предсказуемость там всё же есть, и
Код
U1FCR_bit.FCRFE = 1
эквивалентно
Код
U1FCR = U1IIR | ( 1<< FCRFE)

Ибо IIR и FCR находятся по одному адресу, только один по чтению а второй на запись. smile.gif

То же самое с RBR/THR, да ещё по биту DLAB регистры "мультиплексируются".
SanvaldYV
Во всяком случае, у меня в проекте при инициализации UART были строки
Код
  U1FCR_bit.FCRFE = 1;  
  U1FCR_bit.RTLS = 0;


и никаких проблем не возникало biggrin.gif
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.