Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: LPC_UART (550-совместимый)
Форум разработчиков электроники ELECTRONIX.ru > Сайт и форум > В помощь начинающему > ARM, 32bit
_Артём_
Вечер добрый.

Пытаюсь посылать данные через UART, использую fifo.
Непонятно как правильно это делать.
Код
extern "C" void UART_IRQ_Handler()
{
    LedBlink();
}

volatile uint16_t index;
const uint8_t TestStr[]="0123456789\n";
void main()
{
    InitUART();
    LPC_UART->IER=1<<LPC_UART_IER_THRE;
    NVIC_EnableIRQ(UART_IRQn);
    for (index=0; TestStr[index]; index++)
        LPC_UART->THR=TestStr[index];
    while (1);
}


Поставил breakpoint в UART_IRQ_Handler, программа попала в него, когда данные уже пришли в терминал.

Получается, что нужно в основной программе послать хотя бы один байт в THR, чтобы возникло прерывание по опустошению буфера передачи?

Попытка записывать данные в THR и проверять состояние флага LSR.THRE приводит к тому, что посылается только 1 байт - буфер не пуст, если в нём есть хотя бы 1 байт. Получается нет нормальной индикации, того что есть ещё место в буфере?

Нет ли у кого-нибудь примера передачи с использованием FIFO и прерываний?

Спасибо.
Сергей Борщ
Ну вот такой этот УАСПП загадочный, хотя zltigo нравится. Да, для начала передачи надо положить байт в THR. И увеличить счетчик на 1. Если счетчик меньше глубины FIFO, то можно докладывать данные. Если обнаружили LSR.THRE - счетчик сбрасываем на 0. Ну нету у него флага fifo.not_full, есть только empty. Где-то тут было обсуждение, где zltigo объяснял прелести этого, но не убедил.

Добавлено: нашел раз и два
haker_fox
QUOTE (Сергей Борщ @ Sep 17 2012, 14:12) *
Да, для начала передачи надо положить байт в THR.

Да, часик помучался, пока смог отправить пакет через прерывания) Сейчас уже недельку стабильно работает прием и передача по прерываниям. Этот момент, ИМХО, в документации мутновато отражен. Но если прочитать несколько раз, то доходит rolleyes.gif rolleyes.gif rolleyes.gif
_Артём_
Спасиба за ссылки.

В первом приближении получился такой код
Код
#define TX_FIFO_SIZE 128
struct TUartTxBuffer {
    volatile uint8_t TxBuffer[TX_FIFO_SIZE];
    volatile uint8_t TxNext;
    volatile uint8_t TxFirst;
    volatile int8_t IntEnabled;
    INLINE_FUNCTION    void Send_Handler() {
        uint32_t iir=LPC_UART->IIR;
        uint8_t tx_next=TxNext, tx_first=TxFirst;
        uint_fast8_t fifo_free_size=16;
        while (tx_next!=tx_first && fifo_free_size) {
            LPC_UART->THR=TxBuffer[tx_first++];
            fifo_free_size--;
            if (tx_first==TX_FIFO_SIZE)
                tx_first=0;
        }
        TxFirst=tx_first;
        if (tx_next==tx_first) {
            LPC_UART->IER=0;
            IntEnabled=0;
        }
    }
    void SendBuffer(const uint8_t *data_for_send, uint8_t byte_count);
};
void TUartTxBuffer::SendBuffer(const uint8_t *data_for_send, uint8_t byte_count) {
    uint8_t tx_next=TxNext;
    for (uint_fast8_t i=0; i<byte_count; i++) {
        TxBuffer[tx_next++]=*data_for_send++;
        if (tx_next>=TX_FIFO_SIZE)
            tx_next=0;
    }
    NVIC_DisableIRQ(UART_IRQn);
    TxNext=tx_next;
    if (IntEnabled==0) {
        uint8_t tx_first=TxFirst;
        LPC_UART->THR=TxBuffer[tx_first++];
        if (tx_first==TX_FIFO_SIZE)
            tx_first=0;
        TxFirst=tx_first;
        LPC_UART->IER=1<<LPC_UART_IER_THRE;
        IntEnabled=1;
    }
    NVIC_EnableIRQ(UART_IRQn);
}
TUartTxBuffer UartTxBuffer;
extern "C" void UART_IRQ_Handler()
{
    UartTxBuffer.Send_Handler();
}

Вроде работает.
SII
Цитата(_Артём_ @ Sep 17 2012, 02:02) *
Получается, что нужно в основной программе послать хотя бы один байт в THR, чтобы возникло прерывание по опустошению буфера передачи?


По моему опыту выходит так, что запрос прерывания по наличию места в буфере передачи выдаётся не по самому факту наличия свободного места, а лишь по факту завершения передачи очередного байта из буфера. Таким образом, если разрешить прерывания при заведомо пустом буфере, прерывание так и не произойдёт -- передачи-то не было; однако, если разрешить прерывание и после этого пихнуть в буфер хотя бы один байт -- произойдёт, когда он будет передан (или когда будет переписан из буфера в сдвиговый регистр передатчика).

Лично у меня впечатление, что изначальной причиной такого странного поведения послужила аппаратная ошибка, которую не заметили и растиражировали, а дальше тянут из-за совместимости. Ведь куда логичней, если прерывание по наличию места будет "висеть" постоянно, пока в буфере есть хотя бы один свободный байт и само это прерывание разрешено.
haker_fox
QUOTE (SII @ Sep 18 2012, 00:10) *
Ведь куда логичней, если прерывание по наличию места будет "висеть" постоянно, пока в буфере есть хотя бы один свободный байт и само это прерывание разрешено.

В AVR, например, так и сделано. Нужно что-то передать - подготовил буфер, разрешил прерывание "по пустому FIFO", и все. Буфер передался. А по завершению передачи последнего байта прерывание можно выключить...
_Артём_
Цитата(SII @ Sep 17 2012, 18:10) *
По моему опыту выходит так, что запрос прерывания по наличию места в буфере передачи выдаётся не по самому факту наличия свободного места, а лишь по факту завершения передачи очередного байта из буфера.

Похоже так, только не очередного, а последнего байта. И байт при этом уже передался в RS (программно можно RS485 делать).


Цитата(SII @ Sep 17 2012, 18:10) *
Таким образом, если разрешить прерывания при заведомо пустом буфере, прерывание так и не произойдёт -- передачи-то не было;

Выглядит именно так.

Цитата(SII @ Sep 17 2012, 18:10) *
По моему опыту выходит так, что запрос прерывания по наличию места в буфере передачи выдаётся не Лично у меня впечатление, что изначальной причиной такого странного поведения послужила аппаратная ошибка, которую не заметили и растиражировали

Может быть.

Цитата(haker_fox @ Sep 17 2012, 18:56) *
В AVR, например, так и сделано. Нужно что-то передать - подготовил буфер, разрешил прерывание "по пустому FIFO", и все. Буфер передался. А по завершению передачи последнего байта прерывание можно выключить...

Не только в АВР так сделано, думаю.
Но в общем работает, зато писать можно не байт как в АВР, а аж 16.

haker_fox
QUOTE (_Артём_ @ Sep 18 2012, 04:08) *
Но в общем работает, зато писать можно не байт как в АВР, а аж 16.

В AVR FIFO двухуровневый)
Кстати, Вы так и делаете (я имею ввиду по прерыванию THRE сразу 16 байт отправляете)? rolleyes.gif Работает? rolleyes.gif Я пока машинально на каждый байт прерывание дергаю, на скорую руку писал обработчик)

Обработчик в контексте scmRTOS, но думаю, не суть важно...
CODE
OS_INTERRUPT void uart0ISRHandler()
{
    OS::TISRW ISRW;
    uint32_t iir;

    // While there are pending interrupts
    while( !( ( iir = U0IIR ) & 1 ) )
    {
        switch( ( iir >> 1 ) & 7UL )
        {
        case 2:
            // Receive data available
        case 6:
            // CTI
            rx_isr_byte = U0RBR;
            getPacketEF.signal_isr();
            break;

        case 1:
            // THRE Interrupt
            U0THR = *pOutBuffer++;
            if( pOutBuffer == pEndBuffer )
            {
                // Disable THRE Interrupt
                U0IER &= ~THRE_IE;
                pOutBuffer = outBuffer;
                sendFinishedEF.signal_isr();
            }
            break;
        }
    }

    IRQ_DONE();
}

Но это, конечно, у меня не оптимальный вариант. Создавался как тестовый вариант разбора полетов с USART ISR...
Сергей Борщ
Вот мои страх и ужас (которые, как известно, всего лишь спутники Марса - Демос и Фобос). Да, использую FIFO. Но насколько все это можно было бы написать проще, если бы был флаг "FIFO не полное"...

CODE
template<uint_fast8_t rx_size, uint_fast8_t tx_size>
void buffered_uart<rx_size, tx_size>::send(uint8_t byte)
{
    TCritSect cs;
    if(!Tx_buffer.get_count())
    {
        uint_fast8_t FIFO_counter_cache = Tx_fifo_counter;
        if(pUART->LSR & UART_LSR_THRE)    // FIFO empty
            FIFO_counter_cache = 0;

        if(FIFO_counter_cache < 16)
        {
            if(pUART->LSR & UART_LSR_THRE)    // FIFO empty
                FIFO_counter_cache = 0;
            pUART->THR = byte;
            Tx_fifo_counter = FIFO_counter_cache + 1;
            return;
        }
    }
    Tx_buffer.push(byte);
    pUART->IER = UART_IER_RBRINT_EN | UART_IER_THREINT_EN;
}

template<uint_fast8_t rx_size, uint_fast8_t tx_size>
void buffered_uart<rx_size, tx_size>::send(char const* string)
{
    TCritSect cs;
    if(!Tx_buffer.get_count())
    {
        uint_fast32_t FIFO_counter_cache = Tx_fifo_counter;
        if(pUART->LSR & UART_LSR_THRE)    // FIFO empty
            FIFO_counter_cache = 0;
        while(FIFO_counter_cache < 16)
        {
            char c = *string++;
            if(!c)
            {
                Tx_fifo_counter = FIFO_counter_cache;
                return;
            }
            if(pUART->LSR & UART_LSR_THRE)    // FIFO empty
                FIFO_counter_cache = 0;

            pUART->THR = c;
            ++FIFO_counter_cache;
        }
        Tx_fifo_counter = FIFO_counter_cache;
    }

    while(char c = *string++)
    {
        Tx_buffer.push(c);
        pUART->IER = UART_IER_RBRINT_EN | UART_IER_THREINT_EN;
    }
}

template<uint_fast8_t rx_size, uint_fast8_t tx_size>
void buffered_uart<rx_size, tx_size>::handler()
{
    uint_fast32_t Tmp = pUART->IIR;
    while (!(Tmp & UART_IIR_INTSTAT_PEND))
    {
        switch((Tmp & UART_IIR_INTID_MASK) >> 1)
        {
        case UART_IIR_INTID_CTI >> 1:
        case UART_IIR_INTID_RDA >> 1:
            while (pUART->LSR & UART_LSR_RDR)       // while bytes in RX FIFO
            {
                uint8_t Data = pUART->RBR;          // read anyway
                if(Rx_buffer.get_free_size())
                    Rx_buffer.push(Data);           // if overflow - sorry
            }
            break;

        case UART_IIR_INTID_THRE >> 1:              // Tx interrupt
            {
                uint_fast16_t Queued_bytes = Tx_buffer.get_count();
                if(Queued_bytes)
                {
                    if(Queued_bytes > 16)
                        Queued_bytes = 16;
                    do
                    {
                        uint8_t Data;
                        Tx_buffer.pop(Data, 1);
                        pUART->THR = Data;
                    }
                    while(--Queued_bytes);
                    Tx_fifo_counter = Queued_bytes;
                }
                else
                {
                    Tx_fifo_counter = 0;
                    pUART->IER = UART_IER_RBRINT_EN;

                }
            }
            break;

        case UART1_IIR_INTID_MODEM >> 1:
        case UART_IIR_INTID_RLS >> 1:             // Rx error (OE, PE, FE)
        default:
                break;
        }
        Tmp = pUART->IIR;
    }
}
_Артём_
Цитата(haker_fox @ Sep 18 2012, 02:39) *
В AVR FIFO двухуровневый)

Ну, это он двухуровневый, пока в него не пишешь долго, а потом всё равно в прерывании по одному байту пишешь.


Цитата(haker_fox @ Sep 18 2012, 02:39) *
Кстати, Вы так и делаете (я имею ввиду по прерыванию THRE сразу 16 байт отправляете)? rolleyes.gif Работает? rolleyes.gif Я пока машинально на каждый байт прерывание дергаю, на скорую руку писал обработчик)

Работоспособность буфера сомнений не вызывает.

Цитата(haker_fox @ Sep 18 2012, 02:39) *
IRQ_DONE();

P.S. А это кто? IRQ_DONE в смысле.

Цитата(Сергей Борщ @ Sep 18 2012, 10:05) *
Да, использую FIFO. Но насколько все это можно было бы написать проще, если бы был флаг "FIFO не полное"...

Спасибо за пример.

Да уж, трёхэтажно получилось, а всего лишь бит незаполненности фифо зажали.
haker_fox
QUOTE (_Артём_ @ Sep 18 2012, 21:30) *
P.S. А это кто? IRQ_DONE в смысле.

А это VICVectAddr = 0 в данном случае. Просто инлайн-функция операционной системы.

А отправка и прием организованы примерно так
CODE
void sendBuffer()
{
    pEndBuffer = pOutBuffer;
    pOutBuffer = outBuffer;

    U0THR = *pOutBuffer++;
    sendFinishedEF.clear();
    // Enable THRE interrupt
    U0IER |= THRE_IE;
    sendFinishedEF.wait();

    getPacketEF.clear();
}

bool wakePHYGet( uint8_t* byte )
{
    if( !getPacketEF.wait( FWAKE_ONE_BYTE_RX_TIMEOUT ) )
        return false;

    *byte = rx_isr_byte;
    return true;
}
_Артём_
Цитата(haker_fox @ Sep 18 2012, 16:40) *
А это VICVectAddr = 0 в данном случае. Просто инлайн-функция операционной системы.

Оно на выходе каждого прерывания вызывается?
Если так, то что бы его не запихнуть в ~TISRW?
haker_fox
QUOTE (_Артём_ @ Sep 18 2012, 22:50) *
Оно на выходе каждого прерывания вызывается?
Если так, то что бы его не запихнуть в ~TISRW?

Да, на выходе каждого. Наверно можно. Это нужно у авторов операционной системы консультироваться)

Поскольку у меня полудуплекс, и более, чем 16 байт за раз не передается, то сделал в прерывании совсем просто
CODE
        case 1:
            // THRE Interrupt
            while( pOutBuffer < pEndBuffer )
                U0THR = *pOutBuffer++;

            // Disable THRE Interrupt
            U0IER &= ~THRE_IE;
            pOutBuffer = outBuffer;
            sendFinishedEF.signal_isr();
            break;

Вроде полет нормальный)
pitt
К моему глубокому сожалению, ожидаю ту же проблему (прерывание по фронту, а не поуровню) с CAN sad.gif. Похоже это ТМ Phillips.
http://electronix.ru/forum/index.php?showt...p;#entry1104240
_Артём_
Цитата(pitt @ Oct 21 2012, 19:23) *
ожидаю ту же проблему (прерывание по фронту, а не поуровню) с CAN sad.gif.

Не знаю, как там с lpc17 с CAN, но с UART-ом проблема не в прерываниях, а в некотором неудобстве работы с ним из-за отсутствия флага, показывающего что FIFO не до конца заполнено.
Это решается добавлением в программу пары десятков строк (ну может чуть больше).

Цитата(pitt @ Oct 21 2012, 19:23) *
Похоже это ТМ Phillips.

Думаете у других производителей будет качественно лучше? Скажите тогда кто эти производители.
pitt
Цитата(_Артём_ @ Oct 21 2012, 14:31) *
Не знаю, как там с lpc17 с CAN, но с UART-ом проблема не в прерываниях, а в некотором неудобстве работы с ним из-за отсутствия флага, показывающего что FIFO не до конца заполнено.
Это решается добавлением в программу пары десятков строк (ну может чуть больше).


Думаете у других производителей будет качественно лучше? Скажите тогда кто эти производители.

Кроме как у Phillips прерывания по фронту для флага стстус-регистра ни у кого не встречал.
Если приложению надо мютекс с обработчиком прерывания, прерывание по фронту ликвидирует возмоцность маскирования и требует более сложных и вязких методов. Мне в корне непонятна сама идея такого прерывания. Подчеркиваю, не внешнего, а именно для флага стстус-регистра. Проблему с FIFO я решил достаточно просто: обработчик из HAL, освободив FIFO перезагружает его до завершения сообщения, а если и оно завершено, находит следующее ожидающее своей очереди, а если и очередь пустая, то упираюсь в проблему как инициировать прерывание из приложения, которой бы не было если бы не прерывание по фронту...
_Артём_
Цитата(pitt @ Oct 21 2012, 23:46) *
Кроме как у Phillips прерывания по фронту для флага стстус-регистра ни у кого не встречал.

Возможно есть у кого-нибудь, кто сделал совместимый с 550 UART. А может и нет.

Цитата(pitt @ Oct 21 2012, 23:46) *
Мне в корне непонятна сама идея такого прерывания. Подчеркиваю, не внешнего, а именно для флага стстус-регистра.

Несколькими сообщениями выше было высказано предположение, что это ошибка, ставшая стандартом.

Цитата(pitt @ Oct 21 2012, 23:46) *
Проблему с FIFO я решил достаточно просто: обработчик из HAL, освободив FIFO перезагружает его до завершения сообщения, а если и оно завершено, находит следующее ожидающее своей очереди, а если и очередь пустая, то упираюсь в проблему как инициировать прерывание из приложения, которой бы не было если бы не прерывание по фронту...

Не буду утверждать ничего насчёт типа прерывания THRE, потому что нет под рукой платы с LPC - проверить не могу.

Алгоритм проверки простой:
Код
InitUart();
    __disable_irq();
    LPC_UART->IER=0;
    LPC_UART->THR='1';
    Delay1s();
    LPC_UART->IER=(1<<LPC_UART_IER_THRE_EN);
    NVIC_EnableIRQ(UART_IRQn);
    __enable_irq();

THRE станет равным 1 когда буфер опустеет. Если прерывание не возникнет, значит оно по фронту.

Почему-то кажется что возникнет...В любом случае никто не мешает разрешать прерывание по THRE перед посылкой байта.
pitt
мне не нужен тест, я уже убедился. С CAN еще не убедился, но с большой уверенностью предполагаю. С прерываниями по фронту, прерывания маскировать нельзя вообще, а запрещать глобально очень дурная манера.
_Артём_
Цитата(pitt @ Oct 22 2012, 00:27) *
мне не нужен тест, я уже убедился

Мне нужен - я не убедился. sm.gif
Спасибо, что указали мне на этот новый нюанс.

Цитата(pitt @ Oct 22 2012, 00:27) *
С CAN еще не убедился, но с большой уверенностью предполагаю.

CAN и UART, как мне кажется имеют очень мало общего между собой - бессмысленно обобщать.

Цитата(pitt @ Oct 22 2012, 00:27) *
С прерываниями по фронту, прерывания маскировать нельзя вообще,

Можно запрещать прерывания только UART-а.

Цитата(pitt @ Oct 22 2012, 00:27) *
а запрещать глобально очень дурная манера.

Или понижать его приоритет.

И мало ли ещё что можно придумать...
pitt
Цитата(_Артём_ @ Oct 21 2012, 17:57) *
Мне нужен - я не убедился. sm.gif
Спасибо, что указали мне на этот новый нюанс.


CAN и UART, как мне кажется имеют очень мало общего между собой - бессмысленно обобщать.


Можно запрещать прерывания только UART-а.


Или понижать его приоритет.

И мало ли ещё что можно придумать...

Общее между CAN и UART производитель и его концепт. Я работал с CAN IP для FPGA от Phillips и там столкнулся с их, простите, идиотским прерыванием по фронту...Когда сейчас тот же концепт от того же производителя в другом месте - это становится системой. Если доберусь(в смысле не переключимся на другой MCU) сообщу результат.
Запрещать все прерывания опасно: в RTOS могут вытеснить, чтобы не приходится включать критическую секцию и прочиее прочее прочее и все из-за непонятно чего... Обидно.
_Артём_
Цитата(pitt @ Oct 22 2012, 01:35) *
Общее между CAN и UART производитель и его концепт.

Производитель - NXP, да.
Но ядро от ARM, UART - чей-то стандарт (не от NXP).

Цитата(pitt @ Oct 22 2012, 01:35) *
Я работал с CAN IP для FPGA от Phillips и там столкнулся с их, простите, идиотским прерыванием по фронту...Когда сейчас тот же концепт от того же производителя в другом месте - это становится системой. Если доберусь(в смысле не переключимся на другой MCU) сообщу результат.

Не знаю, кокой процент прерываний у NXP от edge, какой от level... пишут, что есть и те и другие.


Цитата(pitt @ Oct 22 2012, 01:35) *
Запрещать все прерывания опасно:


Запрещайте не все прерывания, а только от UART (NVIC_DisableIRQ). Или скажите, что может не сработать?

pitt
Цитата(_Артём_ @ Oct 21 2012, 19:12) *
Производитель - NXP, да.
Но ядро от ARM, UART - чей-то стандарт (не от NXP).
Не знаю, кокой процент прерываний у NXP от edge, какой от level... пишут, что есть и те и другие.
Запрещайте не все прерывания, а только от UART (NVIC_DisableIRQ). Или скажите, что может не сработать?

Ядро ядром, а периферия у всех своя и в этом главная разница. Я в данном конкретном случае про UART.
Я об'яснил почему запрещать прерывания в реальном времени очень плохо, даже если только UART: application task is preemptable, locking could cause priority inversion and as a result - data loss. Я в предыдущем посте писал по-русски, но видимо, непонятно.
_Артём_
Цитата(_Артём_ @ Oct 22 2012, 00:21) *
Алгоритм проверки простой:
Код
    InitUart();
    __disable_irq();
    LPC_UART->IER=0;
    LPC_UART->THR='1';
    Delay1s();
    LPC_UART->IER=(1<<LPC_UART_IER_THRE_EN);
    NVIC_EnableIRQ(UART_IRQn);
    __enable_irq();

Проверил - прерывание возникает сразу после __enable_irq.
_Артём_
Цитата(pitt @ Oct 22 2012, 02:24) *
Я об'яснил почему запрещать прерывания в реальном времени очень плохо, даже если только UART:

Да, в запрете прерываний ничего хорошего.

Цитата(pitt @ Oct 22 2012, 02:24) *
application task is preemptable, locking could cause priority inversion and as a result - data loss.

То есть ни FIFO, на DMA (у вас LPC17, кажется) не спасают?
А нельзя тогда не запрещать прерывания от UART?

pitt
Цитата(_Артём_ @ Oct 22 2012, 19:06) *
Да, в запрете прерываний ничего хорошего.
То есть ни FIFO, на DMA (у вас LPC17, кажется) не спасают?
А нельзя тогда не запрещать прерывания от UART?

Артем, если хотите, я могу Вам по skype в выходные ответить. У меня все работает, но совершрнно непонятно зачем я должен прилагать столько услий из-за дурацкого фронта! Я под RTX и все что я делаю: запрещаю переключение контекста: это просто флаг, никаких прерываний не запрещаю, затем:
Код
if (((LPC_UART->LSR & (1<<THRE))&&((LPC_UART->LSR & (1<<THRE))) {
  // тут файфо пустое и никаких прерыаний по пустому файфо не будет
  // посылаю первый байт нового сообщения
}
else {
  // а тут инициировать нельзя: обработчик сам увидет, что надо посылать новое сообщение
}

Пояснение: обработчик по пустому файфо или заполняет его текущим сообщением, а если оно закончилось пытается взять следущее. Если его нет, то тогда код выше начнет посылать его когда оно появится.
А вот зачем я два раза подряд один и тот же регистр читаю - догадайтесь сами wink.gif
_Артём_
Цитата(pitt @ Oct 23 2012, 02:36) *
Артем, если хотите, я могу Вам по skype в выходные ответить.

Отвечайте. Если можно сюда или Личные сообщения.

Цитата(pitt @ Oct 23 2012, 02:36) *
У меня все работает, но совершрнно непонятно зачем я должен прилагать столько услий из-за дурацкого фронта!

А что остаётся делать - всегда находятся какие-нибудь недостатки...

Цитата(pitt @ Oct 23 2012, 02:36) *
Я под RTX и все что я делаю: запрещаю переключение контекста: это просто флаг, никаких прерываний не запрещаю, затем:
[code]if (((LPC_UART->LSR & (1<<THRE))&&((LPC_UART->LSR & (1<<THRE))) {
// тут файфо пустое и никаких прерыаний по пустому файфо не будет
// посылаю первый байт нового сообщения
}
А вот зачем я два раза подряд один и тот же регистр читаю - догадайтесь сами wink.gif

Пока не понял зачем 2 раза читать...достаточно одного чтения. Или нет?
pitt
Цитата(_Артём_ @ Oct 23 2012, 08:25) *
Отвечайте. Если можно сюда или Личные сообщения.
А что остаётся делать - всегда находятся какие-нибудь недостатки..
Пока не понял зачем 2 раза читать...достаточно одного чтения. Или нет?

Не люблю печатать, особенно по-русски...Лучше голосом, потому скайп
Обычно, есть причина, чтобы сделать так, а не иначе. Вот и пытаюсь ее отыскать, ну не от балды же так сделано!
Все имеет смысл, думайте, догадывайтесь, я не NXP, читаю 2 раза с умыслом, хотя приходится так делать именно из-за NXP sm.gif
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.