реклама на сайте
подробности

 
 
> Тема может быть избита. не понимаю как оргнизовать работу UART по прерывания(+)
AlHakim
сообщение Jan 8 2007, 12:58
Сообщение #1


Участник
*

Группа: Участник
Сообщений: 65
Регистрация: 7-02-05
Из: Уфа
Пользователь №: 2 474



Нашел примеры работы UART-a / которые выкладывал VAI? но у него используется только перрывание на прием. Я же хочу чтобы и на передачу и на прием работало по прерваниям

Мой код
в основной программе
Uart0PutChar(0x30); прерывание проходит
Uart0PutStr("qwe"); тут как карта ляжет, программа зацикливается
....
while(*str){
Uart0Tx.PtrWrByte = ++Uart0Tx.PtrWrByte & UART_BUFFER_MASK;
while (Uart0Tx.PtrWrByte == Uart0Tx.PtrRdByte) {} // программа зацикливается
Как я понимаю, происходит изменение указателя а в это время возникает прерывание на TX и указатель Uart0Tx.PtrRdByte принимает значение Uart0Tx.PtrWrByte

-----------------------------------------
Модуль Uart.c
Код
#pragma vector=USART0TX_VECTOR
__interrupt void irq_Uart0_Tx(void)
{
    if (Uart0Tx.PtrWrByte != Uart0Tx.PtrRdByte){
        Uart0Tx.PtrRdByte = ++Uart0Tx.PtrRdByte & UART_BUFFER_MASK;
        TXBUF0 = Uart0Tx.Buffer[Uart0Tx.PtrRdByte];
    }    //
    else{
         //
         // флаг на завершение Tx и необходимости переключится на прием
         //
//         if (EventFlags & fwRxWaitTime){
//             //bSwitchTxToRx = 1;                 // EventFlags |= fwSwitchTxToRx;
//             pRS485Tx = 0;                      // приемопередатчик на Rx
//         }

    }

#pragma vector=USART0RX_VECTOR
__interrupt void irq_Uart0_Rx(void)
{
    volatile char dummy;
    unsigned char RxData;

    if ( FE+PE+OE+BRK+RXERR ){                          // overflow or framing error -
        URCTL1 &= ~ (FE+PE+OE+BRK+RXERR);               // Clear error flags
        dummy = RXBUF0;                                 // dummy read to clear RXE flag
        }
    else{
         RxData = RXBUF0;                               // Read the received data
         if ((Uart0Rx.PtrWrByte + 1) != Uart0Rx.PtrRdByte){
            Uart0Rx.PtrWrByte = ++Uart0Rx.PtrWrByte & UART_BUFFER_MASK;
            Uart0Rx.Buffer[Uart0Rx.PtrWrByte] = RxData;
         }
    }
}

void Uart0PutChar(unsigned char TxData)
{
    Uart0Tx.PtrWrByte = ++Uart0Tx.PtrWrByte & UART_BUFFER_MASK;
    while (Uart0Tx.PtrWrByte == Uart0Tx.PtrRdByte) {
        //
        //  Сброс сторожевого таймера
        //
    }   // Wait for incomming data
    Uart0Tx.Buffer[Uart0Tx.PtrWrByte] = TxData;
    if  ((IFG1 & UTXIFG0) != UTXIFG0)           //    UART0_ENABLE_TX_INTERRUPT;
        IFG1 |= UTXIFG0;
}

void Uart0PutStr(unsigned char *str)
{
//    while(*str) Uart0PutChar(*str++);  //*s++=Tmpchar;
    while(*str){
        Uart0Tx.PtrWrByte = ++Uart0Tx.PtrWrByte & UART_BUFFER_MASK;
        while (Uart0Tx.PtrWrByte == Uart0Tx.PtrRdByte) {}   // Wait for incomming data

        Uart0Tx.Buffer[Uart0Tx.PtrWrByte] = *str++;
        if  ((IFG1 & UTXIFG0) != UTXIFG0)       //UART0_ENABLE_TX_INTERRUPT;
            IFG1 |= UTXIFG0;
    }
}
Go to the top of the page
 
+Quote Post
3 страниц V   1 2 3 >  
Start new topic
Ответов (1 - 30)
HARMHARM
сообщение Jan 8 2007, 13:58
Сообщение #2


читатель даташитов
****

Группа: Свой
Сообщений: 853
Регистрация: 5-11-06
Из: Днепропетровск
Пользователь №: 21 999



Позволю себе сделать несколько замечаний.
1. При работе не атомарными операциями с разделяемыми переменными надо или вводить атомарные флаги или запрещать прерывания, как Вы правильно заметили.
2. При работе с RS485 я лично делаю так: при начале передачи даю разрешение на драйвер и отключаю прерывание RX, чтобы не принять свою собственную посылку если что. В конце передачи запрещаю драйвер, читаю RXBUF дабы очистить флаги и уже потом разрешаю прерывание RX. Такая схема откатана и работает. Делаю так всегда, даже если у чипа RS485 есть запрещение приёма.
3. Не совсем понимаю логику работы с TX. Не проще ли сделать так:
При необходимости передать один байт и подождать завершения передачи - запретить прерывание TX, положить байт в TXBUF и ждать флага.
При необходимости передать один байт и не ждать завершения - запретить прерывание TX, положить байт в TXBUF и больше ничего не делать.
При необходимости передать несколько байт и подождать завершения передачи - разрешить прерывание TX, положить байт в TXBUF и передавать остальные байты по прерыванию.
4. Код прерываний у Вас, похоже, рабочий. Еще не совсем понятна конструкция
Код
    
URCTL1 &= ~ (FE+PE+OE+BRK+RXERR);               // Clear error flags

ибо Reading UxRXBUF resets the receive-error bits, the RXWAKE bit, and URXIFGx. И еще причем здесь URCTL1? Вы ведь испольуете первый USART?

Сообщение отредактировал HARMHARM - Jan 8 2007, 14:31
Go to the top of the page
 
+Quote Post
AlHakim
сообщение Jan 8 2007, 14:24
Сообщение #3


Участник
*

Группа: Участник
Сообщений: 65
Регистрация: 7-02-05
Из: Уфа
Пользователь №: 2 474



Цитата(HARMHARM @ Jan 8 2007, 15:58) *
2. При работе с RS485 я лично делаю так: при начале передачи даю разрешение на драйвер и отключаю прерывание RX, чтобы не принять свою собственную посылку если что. В конце передачи запрещаю драйвер, читаю RXBUF дабы очистить флаги и уже потом разрешаю прерывание RX. Такая схема откатана и работает. Делаю так всегда, даже если у чипа RS485 есть запрещение приёма.

ну вообщем-то код пишетс яне только для работы по Rs485. Так и сделал уже(запрещаю прерывания)
Код прерываний у Вас, похоже, рабочий. Еще не совсем понятна конструкция
Цитата(HARMHARM @ Jan 8 2007, 15:58) *
Код
    
URCTL1 &= ~ (FE+PE+OE+BRK+RXERR);               // Clear error flags

ибо Reading UxRXBUF resets the receive-error bits, the RXWAKE bit, and URXIFGx. И еще причем здесь URCTL1? Вы ведь испольуете первый USART?

Ошибочка закралась, да и точно снимаются они чтением UxRXBUF
Спасибо smile.gif
Go to the top of the page
 
+Quote Post
HARMHARM
сообщение Jan 8 2007, 14:30
Сообщение #4


читатель даташитов
****

Группа: Свой
Сообщений: 853
Регистрация: 5-11-06
Из: Днепропетровск
Пользователь №: 21 999



Не успел добавить комментарии, прочтите моё сообщение еще раз wink.gif
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Jan 8 2007, 14:54
Сообщение #5


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



Цитата(AlHakim @ Jan 8 2007, 11:58) *
Модуль Uart.c
Код
    if  ((IFG1 & UTXIFG0) != UTXIFG0)           //    UART0_ENABLE_TX_INTERRUPT;
        IFG1 |= UTXIFG0;
Не совсем красиво разрешать/запрещать прерывания дергая флаг. Он ведь может измениться аппаратно пока вы пытаетесь его изменить программно. У вас в комментариях написано ENABLE_TX_INTERRUPT, так и делайте это при помощи специально предназначенного для этого бита.
Про атомарность HARMHARM правильно заметил, опять же про volatile не забываем. Вот мой код, в нем обращения атомарны, запреты прерываний не нужны:
Код
#include    <msp430x14x.h>
#include    <stdio.h>
#include    <stdint.h>

#include    "Hardware.h"

#define RX_BUFF_SIZE    32  // must be power of two
#define TX_BUFF_SIZE    16  // must be power of two

char RxBuffer[RX_BUFF_SIZE];
char TxBuffer[TX_BUFF_SIZE];
uint8_t volatile RxHead, RxTail, TxHead, TxTail;

void UART_Init (void) {
    U0BR0 = (SMCLK / UART_BAUDRATE) & 0xFF;
    U0BR1 = (SMCLK / UART_BAUDRATE) >> 8;
    U0MCTL = 0;
    U0CTL = (0 * PENA) | (0 * SPB) | (1 * CHAR) | (0 * LISTEN) | (0 * SYNC) | (0 * SWRST);
    U0TCTL = (1 * SSEL1) | (0 * SSEL0) | (1 * TXEPT);

    ME1 = URXE0 | UTXE0;            // enable tx & rx
    P3SEL |= (1<<5) | (1<<4);       // enable pins
    IE1 = URXIE0;                   // enable RX int
}

#pragma vector = USART0TX_VECTOR
__interrupt void Tx232(void) {
    uint8_t Tmp = TxTail;           // temp. variable because TxTail is volatile

    U0TXBUF = TxBuffer[Tmp++];
    TxTail = (Tmp + 1) & (TX_BUFF_SIZE - 1);

    if(Tmp == TxHead)               // buffer empty
        IE1 &= ~UTXIE0;             // disable tx int
}

#pragma vector = USART0RX_VECTOR
__interrupt void Rx232 (void) {
    uint8_t Tmp = RxHead;           // temp. variable because RxHead is volatile
    
    RxBuffer[Tmp] = U0RXBUF;
    RxHead = (Tmp + 1) & (RX_BUFF_SIZE - 1);
}

int putchar(int symbol) {
    uint8_t Tmp = TxHead;           // temp. variable because TxHead is volatile
    
    while(( (Tmp - TxTail) & (TX_BUFF_SIZE - 1)) == (TX_BUFF_SIZE - 1));    // wait while buffer full

    TxBuffer[Tmp] = symbol;
    TxHead = (Tmp + 1) & (TX_BUFF_SIZE - 1);

    IE1 |= UTXIE0;                  // enable tx int
    return (1);
}

int getchar(void) {
    uint8_t Tmp = RxTail;           // temp. variable because RxTail is volatile
    int Symbol;

    while(RxHead == Tmp);           // wait while buffer empty

    Symbol = RxBuffer[Tmp];
    RxTail = (Tmp + 1) & (RX_BUFF_SIZE - 1);
    return Symbol;
}

int hasinput(void) {
    uint8_t Tmp = RxTail;           // temp. variable because RxTail is volatile
    return RxHead - Tmp;
}

int puts(const char * string) {
    char c;
    while (c = *string++)
        putchar(c);
}



Цитата(HARMHARM @ Jan 8 2007, 12:58) *
2. При работе с RS485 я лично делаю так: при начале передачи даю разрешение на драйвер и отключаю прерывание RX, чтобы не принять свою собственную посылку если что. В конце передачи запрещаю драйвер, читаю RXBUF дабы очистить флаги и уже потом разрешаю прерывание RX.
Зачем такие сложности если можно отключить прием ( ME1 &= ~URXE0 )?


Цитата(HARMHARM @ Jan 8 2007, 15:58) *
Код прерываний у Вас, похоже, рабочий.
Похоже, что нет. Когда все передано прерывание передачи не запрещается и в буфер ничего не пишется. Таким образом программа постоянно после выхода из обработчика передачи снова попадает в него же.


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
AlHakim
сообщение Jan 8 2007, 15:05
Сообщение #6


Участник
*

Группа: Участник
Сообщений: 65
Регистрация: 7-02-05
Из: Уфа
Пользователь №: 2 474



Цитата(Сергей Борщ @ Jan 8 2007, 16:54) *
Похоже, что нет. Когда все передано прерывание передачи не запрещается и в буфер ничего не пишется. Таким образом программа постоянно после выхода из обработчика передачи снова попадает в него же.

я не утвержадю что рабочий на все 100, но повторного вхождни я впрерывание не проихслжит поскольку аппаратно в перрывание снимается бит UTXIFG0

Попробую использовать ваш код

вот еще возникла пролемка, если не сложно прокомментируйте

while(*str) Uart0PutChar(*str++); //*s++=Tmpchar;

странно передает н мой текст а часть его плюс мусор в отлачике по шагам проходит в run-time не всегда, чаще нет, видимо используемые регистры в перрывание изменяются sad.gif
Go to the top of the page
 
+Quote Post
jorikdima
сообщение Jan 8 2007, 15:25
Сообщение #7


тут может быть ваша реклама
*****

Группа: Свой
Сообщений: 1 164
Регистрация: 15-03-06
Из: Санкт-Петербург/CA
Пользователь №: 15 280



Посматрите AppNotes на сайте TI. Для каждого семейства есть примеры работы. Например slac015k
Go to the top of the page
 
+Quote Post
Dog Pawlowa
сообщение Jan 8 2007, 15:27
Сообщение #8


Гуру
******

Группа: Свой
Сообщений: 2 702
Регистрация: 14-07-06
Пользователь №: 18 823



У меня рабочий код. Пока тут в грязь не ткнули smile.gif
Пожалуйста wink.gif
Линейный буфер, slave,
timer декрементируется 1мс, Service вставляется в основной цикл программы.


Код
//pc DOMP protocol
char rx_buf1[RxBufSize1];
char *rx_head1;
char *rx_tail1;
char tx_buf1[TxBufSize1];
char *tx_head1;
char *tx_tail1;
char domp_status;
char usart1_last_received;

void Uart1Configuration9600(void)
{
    U1CTL = CHAR+SWRST;            // 8-bit character and reset, 8N1
      U1TCTL = SSEL0+SSEL1;          // UCLK = SMCLK (8MHz)
      U1BR0 = 0x00;                  // 7372800/9600 - 768 or 300h
      U1BR1 = 0x03;                  //
      U1MCTL = 0x00;           
      ME2 &= ~(UTXE1 | URXE1);  // Disable USART1 TXD/RXD
       U1CTL &=~SWRST;                 // end of reset     
      rx_tail1=rx_buf1;
      rx_head1=rx_buf1;
      IE2 &= ~(URXIE1|UTXIE1);                // Disable USART1 RX and TX interrupt
}

void ClearTxBuffer1(void)
{     __disable_interrupt();    
    tx_tail1 = tx_head1 = tx_buf1;
    __enable_interrupt();
}

void ClearRxBuffer1(void)
{    rx_tail1 = rx_head1 = rx_buf1;
}

void EnableReceiver1 ( void )
{    ClearRxBuffer1();                //
  ME2|= URXE1;  //    receiver enable
  IE2|=URXIE1;        // receive interrupt enable
//    UCSR0A &= ~ ( 1 << RXC0 );        // set receiver empty bit
}    


void Uart1Configuration(void)
{ Uart1Configuration9600();
  tx_tail1 = tx_head1 = tx_buf1; // without interrupt enable
  EnableReceiver1();
}

void EnableTransmitter1 ( void )
{//    tx_tail1=tx_buf1;        // transmitt from beginning
  ME2|= UTXE1;  //    transmitter enable
    IFG2|=UTXIFG1; // set transmitter empty bit
  IE2|=UTXIE1;  //  transmitt interrupt enable
}



#pragma vector=UART1TX_VECTOR
__interrupt void USART1_transmit(void)
{     if ((domp_status==DompTransmitting) &&
     (tx_tail1<tx_head1))
        {      TXBUF1 =*tx_tail1;
            tx_tail1++;
        } else
        { IE2&=~UTXIE1;  //  transmitt interrupt disable
//      ME2&= UTXE1;  //    transmitter enable
      IFG2&=~UTXIFG1; // clear transmitter empty bit
        domp_status_timer = 2;
        domp_status = DompWaitReceiving;
    }
}


#pragma vector = UART1RX_VECTOR
__interrupt void USART1_receive(void)
{    
      usart1_last_received=U1RXBUF;
//    this two lines for Echo
//    TXBUF1 = b;
//    EnableTransmitter1();

      if (domp_status == DompWaiting)
    {    if (usart1_last_received == START_RX_CHAR)
        {    rx_head1 = rx_buf1;
            domp_status = DompReceiving;
        }
        else return;
    }
    if (domp_status == DompReceiving)
    {    *rx_head1 = usart1_last_received;
        rx_head1 ++;
        if (rx_head1 >= rx_buf1+RxBufSize1)
        domp_status=DompProcessing;
        if (usart1_last_received == END_RX_CHAR) domp_status=DompProcessing;

    }
}
/*
#pragma vector = USART0_TXC_vect
__interrupt void USART_transmit_complete(void)
{    usart_status_timer = 2;
    domp_status = UsartWaitReceiving;
}
*/

void DompService(void)
{    char b;
    switch (domp_status)

{    case DompUnconfigured:    
            Uart1Configuration();
//            SetReceiveDirection;
            ClearRxBuffer1();
            domp_status = DompWaiting;
      break;
    case DompWaiting:    
            domp_status_timer = 2000; // time for receiving
            break;
    case DompReceiving:
            if (!domp_status_timer) domp_status = DompUnconfigured;
            break;
    case DompProcessing:    
            b = MyCorrectCommand();
            if (!b)
            {    ExecuteCommandAndPrepareAnswer();
        domp_status = DompWaitTransmitting;
                domp_status_timer=5;
            }
            else     
            {    
        domp_status = DompWaitReceiving;
                domp_status_timer = 1;
            }
            break;
    case DompWaitTransmitting:    
            if     (domp_status_timer == 0)
            {    
        SetTransmitDirection;
                domp_status = DompTransmitting;
                domp_status_timer = 500;
        tx_tail1=tx_buf1;
//                EnableTransmitter1();     !!!
            }
            break;
    case DompTransmitting:    
            if (!domp_status_timer)
              {    domp_status = DompUnconfigured; }
    
            break;
    case DompWaitReceiving:
            if (domp_status_timer == 0)
            {    ClearRxBuffer1();
              SetReceiveDirection;
                domp_status = DompWaiting;//UsartReceiving;
            }
            break;
    }                        
}

char Usart1EchoTest(void)
{   char b;
    Delay(2);
    b=rtc_data[rtcSecond];
    TXBUF1=b;
    ME2|= UTXE1|URXE1;
    Delay(10);
    if (U1RXBUF==b) b=1;
    else b=0;
    domp_status=DompUnconfigured;
    return(b);
}


Жуткие следы выбора размера табуляций и портирования с АВР blink.gif

Сообщение отредактировал Dog Pawlowa - Jan 8 2007, 15:44


--------------------
Уходя, оставьте свет...
Go to the top of the page
 
+Quote Post
rezident
сообщение Jan 8 2007, 15:33
Сообщение #9


Гуру
******

Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882



Цитата(Сергей Борщ @ Jan 8 2007, 16:54) *
Цитата(HARMHARM @ Jan 8 2007, 15:58) *

Код прерываний у Вас, похоже, рабочий.
Похоже, что нет. Когда все передано прерывание передачи не запрещается и в буфер ничего не пишется. Таким образом программа постоянно после выхода из обработчика передачи снова попадает в него же.

Переход по вектору прерывания от передатчика автоматически сбрасывает флаг вызова прерывания. Так что лишний вызов произойдет только один раз по окончании передачи.
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Jan 8 2007, 15:41
Сообщение #10


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



Цитата(AlHakim @ Jan 8 2007, 14:05) *
Цитата(Сергей Борщ @ Jan 8 2007, 16:54) *

Похоже, что нет. Когда все передано прерывание передачи не запрещается и в буфер ничего не пишется. Таким образом программа постоянно после выхода из обработчика передачи снова попадает в него же.

я не утвержадю что рабочий на все 100, но повторного вхождни я впрерывание не проихслжит поскольку аппаратно в перрывание снимается бит UTXIFG0
В каком месте снимается? Я вижу что если передавать больше нечего то все закомментировано.
Цитата
while(*str) Uart0PutChar(*str++); //*s++=Tmpchar;
странно передает н мой текст а часть его плюс мусор в отлачике по шагам проходит в run-time не всегда, чаще нет, видимо используемые регистры в перрывание изменяются sad.gif
Uart0Tx.PtrWrByte и Uart0Tx.PtrRdByte объявлены как volatile? Скорее всего нет, иначе компилятор выдавал бы предупреждения на конструкции вроде if (Uart0Tx.PtrWrByte != Uart0Tx.PtrRdByte). Дальше уже может твориться все что угодно. Еще может не хватать стека - для начала увеличьте его размер.


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
AlHakim
сообщение Jan 8 2007, 15:41
Сообщение #11


Участник
*

Группа: Участник
Сообщений: 65
Регистрация: 7-02-05
Из: Уфа
Пользователь №: 2 474



Сергей Борщ Попробовал использовать Ваш код, получил тоже само что и было у мен явначале
программа зациклилась
Код
    while(( (Tmp - TxTail) & (TX_BUFF_SIZE - 1)) == (TX_BU

причем
Uart0PutChar(0x30); - выполняется,
а
Uart0PutStr("qwe"); зацикливается

Сообщение отредактировал AlHakim - Jan 8 2007, 15:52
Go to the top of the page
 
+Quote Post
VAI
сообщение Jan 8 2007, 15:51
Сообщение #12


Профессионал
*****

Группа: Модераторы
Сообщений: 1 120
Регистрация: 17-06-04
Пользователь №: 37



А я был уверен, что выкладывал и прием и передачу по прерыванию.
Исправляюсь.
Прикрепленные файлы
Прикрепленный файл  UART.rar ( 3.46 килобайт ) Кол-во скачиваний: 164
 


--------------------
Если зайца бить, его можно и спички научить зажигать
Сколько дурака не бей - умнее не будет. Зато опытнее
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Jan 8 2007, 16:15
Сообщение #13


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



Цитата(AlHakim @ Jan 8 2007, 14:41) *
Сергей Борщ Попробовал использовать Ваш код, получил тоже само что и было у мен явначале
программа зациклилась
Код
    while(( (Tmp - TxTail) & (TX_BUFF_SIZE - 1)) == (TX_BU

причем
Uart0PutChar(0x30); - выполняется,
а
Uart0PutStr("qwe"); зацикливается

Извиняюсь, в прерывании ошибку допустил. Должно быть так:
Код
#pragma vector = USART0TX_VECTOR
__interrupt void Tx232(void) {
    uint8_t Tmp = TxTail;           // temp. variable because TxTail is volatile

    U0TXBUF = TxBuffer[Tmp];
    TxTail = Tmp = (Tmp + 1) & (TX_BUFF_SIZE - 1);

    if(Tmp == TxHead)               // buffer empty
        IE1 &= ~UTXIE0;             // disable tx int
}


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
jorikdima
сообщение Jan 8 2007, 16:24
Сообщение #14


тут может быть ваша реклама
*****

Группа: Свой
Сообщений: 1 164
Регистрация: 15-03-06
Из: Санкт-Петербург/CA
Пользователь №: 15 280



http://www.ti.com/litv/zip/slac015k
тут простейшие и наипонятнийшие примеры.
например uart07_09600
Go to the top of the page
 
+Quote Post
AlHakim
сообщение Jan 8 2007, 18:46
Сообщение #15


Участник
*

Группа: Участник
Сообщений: 65
Регистрация: 7-02-05
Из: Уфа
Пользователь №: 2 474



Спасбо всем, а в особенности Сергею
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Jan 8 2007, 21:12
Сообщение #16


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



Цитата(rezident @ Jan 8 2007, 14:33) *
Переход по вектору прерывания от передатчика автоматически сбрасывает флаг вызова прерывания.
Да, про это я забыл, каюсь.


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
zltigo
сообщение May 5 2008, 16:05
Сообщение #17


Гуру
******

Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244



Цитата(Сергей Борщ @ Jan 8 2007, 16:54) *
Вот мой код...

Пытаясь выжать (вдруг я чего-то не понимаю, чего другие понимают sad.gif )из простейшего UART-а MSP430 все возможное, набрел на эту старую тему. По поводу твоего кода, Сергей, перемудрил ты несколько с voltile и c масками. Можно проще, например, передача:
Код
#define TX_BUFF_SIZE    16  // must be power of two
#define TX_BUFF_MASK    (TX_BUFF_SIZE-1)
char TxBuffer[TX_BUFF_SIZE];
uint8_t volatile TxTail;
uint8_t TxHead;

#pragma vector = USART0TX_VECTOR
__interrupt void Tx232(void) {

    U0TXBUF = TxBuffer[TxTail++ & TX_BUFF_MASK];
    if( TxTail == TxHead )               // buffer empty
            IE1 &= ~UTXIE0;             // disable tx int
}

void putchar(int symbol) {

    while( TxHead - TxTail >= TX_BUFF_SIZE );    // wait while buffer full

    TxBuffer[TxHead++ & TX_BUFF_MASK] = symbol;

    IE1 |= UTXIE0;                  // enable tx int
}


--------------------
Feci, quod potui, faciant meliora potentes
Go to the top of the page
 
+Quote Post
AHTOXA
сообщение May 6 2008, 18:30
Сообщение #18


фанат дивана
******

Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684



Цитата(zltigo @ May 5 2008, 22:05) *
Можно проще


Правильно ли я понял, что вы сэкономили одно слово volatile и две (вроде бы) операции &=TX_BUFF_MASK?

Или же здесь что-то более концептуальное? :-)


--------------------
Если бы я знал, что такое электричество...
Go to the top of the page
 
+Quote Post
rezident
сообщение May 6 2008, 18:42
Сообщение #19


Гуру
******

Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882



Цитата(zltigo @ May 5 2008, 22:05) *
Можно проще, например, передача:
Код
void putchar(int symbol) {

    while( TxHead - TxTail >= TX_BUFF_SIZE );    // wait while buffer full

    TxBuffer[TxHead++ & TX_BUFF_MASK] = symbol;

    IE1 |= UTXIE0;                  // enable tx int
}

Для инициации передачи UART недостаточно просто разрешить прерывание. Желательно принудительно (программно) установить флаг UTXIFGx. Иначе нельзя быть на 100% уверенным, что прерывание действительно возникнет. Флаг может быть оказаться сброшен после вызова "лишнего" прерывания при неудачном стечении (программных) обстоятельств.
Go to the top of the page
 
+Quote Post
MrYuran
сообщение May 7 2008, 04:39
Сообщение #20


Беспросветный оптимист
******

Группа: Свой
Сообщений: 4 640
Регистрация: 26-12-07
Из: Н.Новгород
Пользователь №: 33 646



Цитата(rezident @ May 6 2008, 21:42) *
Для инициации передачи UART недостаточно просто разрешить прерывание. Желательно принудительно (программно) установить флаг UTXIFGx. Иначе нельзя быть на 100% уверенным, что прерывание действительно возникнет. Флаг может быть оказаться сброшен после вызова "лишнего" прерывания при неудачном стечении (программных) обстоятельств.

А я вообще не понимаю, зачем запрещать и разрешать прерывания по TX.
wassat.gif
Может просветите?
Я вот так делаю
Код
//------------------------------------------------------------------------------

#pragma vector = UART0TX_VECTOR
__interrupt void uart0_write_interrupt_handler(void)
{
  
  IFG1 &= ~UTXIFG0; // clear flag TXD0    
  if(MessLen0--)U0TXBUF=*cTXbuf0ptr++;
  
}

//------------------------------------------------------------------------------


Закончили передачу сообщения - просто не кидаем в буфер ничего и прерывание не возникнет.
Зачем же его тогда запрещать?


--------------------
Программирование делится на системное и бессистемное. ©Моё :)
— а для кого-то БГ — это Bill Gilbert =)
Go to the top of the page
 
+Quote Post
AHTOXA
сообщение May 7 2008, 04:59
Сообщение #21


фанат дивана
******

Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684



Цитата(MrYuran @ May 7 2008, 10:39) *
Я вот так делаю


Тогда при отсутствии передачи надо первый символ кидать не в буфер, а в U0TXBUF, а то прерывание вообще не возникнет. То есть, нужен какой-то флажок, который отслеживает наличие символа в передатчике.


--------------------
Если бы я знал, что такое электричество...
Go to the top of the page
 
+Quote Post
MrYuran
сообщение May 7 2008, 05:05
Сообщение #22


Беспросветный оптимист
******

Группа: Свой
Сообщений: 4 640
Регистрация: 26-12-07
Из: Н.Новгород
Пользователь №: 33 646



Цитата(AHTOXA @ May 7 2008, 07:59) *
Тогда при отсутствии передачи надо первый символ кидать не в буфер, а в U0TXBUF, а то прерывание вообще не возникнет. То есть, нужен какой-то флажок, который отслеживает наличие символа в передатчике.

ну да, если надо чё-то передать, ставим указатель на нужный буфер, длину сообщения кидаем в MessLen0 и первый байт в U0TXBUF.


--------------------
Программирование делится на системное и бессистемное. ©Моё :)
— а для кого-то БГ — это Bill Gilbert =)
Go to the top of the page
 
+Quote Post
AHTOXA
сообщение May 7 2008, 05:19
Сообщение #23


фанат дивана
******

Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684



Цитата(MrYuran @ May 7 2008, 11:05) *
ну да, если надо чё-то передать, ставим указатель на нужный буфер, длину сообщения кидаем в MessLen0 и первый байт в U0TXBUF.


И не проверяешь перед этим, не идёт ли передача предыдущего блока? :-)))

Такой подход хорош для передачи блоков данных. Для putchar(), который может вызываться в произвольные моменты времени, это не подходит.


--------------------
Если бы я знал, что такое электричество...
Go to the top of the page
 
+Quote Post
Kurt
сообщение May 7 2008, 05:28
Сообщение #24


Участник
*

Группа: Свой
Сообщений: 63
Регистрация: 16-06-04
Из: Россия, Уфа
Пользователь №: 31



вопрос действительно уже не раз поднимавшийся и в этот раз я тыркну сцылку ))
http://kurt.embedders.org/wiki/sources:uart1
Go to the top of the page
 
+Quote Post
zltigo
сообщение May 7 2008, 05:38
Сообщение #25


Гуру
******

Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244



Цитата(AHTOXA @ May 6 2008, 20:30) *
Или же здесь что-то более концептуальное? :-)

Абсолютно ничего концептуального - правки исключительно в рамках заданной Сергеем концепции. Просто проходя мимо взглядом зацепился.


--------------------
Feci, quod potui, faciant meliora potentes
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение May 7 2008, 06:50
Сообщение #26


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



Цитата(zltigo @ May 7 2008, 08:38) *
Просто проходя мимо взглядом зацепился.
Да, согласен. Так лучше.


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
rezident
сообщение May 7 2008, 08:56
Сообщение #27


Гуру
******

Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882



Цитата(MrYuran @ May 7 2008, 10:39) *
А я вообще не понимаю, зачем запрещать и разрешать прерывания по TX.
wassat.gif
Может просветите?
При пакетной передаче я тоже не запрещаю. Потому как в прерывании анализируется состояние буфера передачи (количество символов в очереди). Но для посимвольной передачи прерывание запрещать нужно прямо на выходе из прерывания. Иначе может иметь быть место какое-нибудь дублирование символов.
Цитата(MrYuran @ May 7 2008, 10:39) *
Я вот так делаю

Цитата(MrYuran @ May 7 2008, 10:39) *
Закончили передачу сообщения - просто не кидаем в буфер ничего и прерывание не возникнет.
Дык это у вас как раз случай буферизированной пакетной передачи. Выше же про putchar речь идет, где посимвольная передача.
Цитата(AHTOXA)
Тогда при отсутствии передачи надо первый символ кидать не в буфер, а в U0TXBUF, а то прерывание вообще не возникнет. То есть, нужен какой-то флажок, который отслеживает наличие символа в передатчике.
Флажки все есть UTXIFGx и EPT, нужно только не забывать их проверять.
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение May 7 2008, 10:05
Сообщение #28


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



Цитата(rezident @ May 7 2008, 11:56) *
Флажки все есть UTXIFGx и EPT, нужно только не забывать их проверять.
Да, флажки есть. Но проверка их - лишний код. Приведенный мной код заменой имен регистров и флагов переносится на мегу и AT91SAM7, где флаг сбросить нельзя - он железно связан с признаком пустоты буфера. Зачем мне под каждый процессор специально заточенные алгоритмы, если этот работает так же?


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
Dog Pawlowa
сообщение Sep 20 2014, 18:37
Сообщение #29


Гуру
******

Группа: Свой
Сообщений: 2 702
Регистрация: 14-07-06
Пользователь №: 18 823



Оппа...
Понадобилось перевести передачу на прерывания, не работает так как надо.
У меня особенность - в циклический буфер добавляются байты (или строки) если
- передача идет
- если передача стоит

Если оперировать только разрешением прерывания, как у zltigo, то передача после первого байта блокируется. Это понятно - нет фронта флага, он повис.
Если дергать (устанавливать) флаг готовности передачи в момент добавления в буфер очередного символа, то символы пропадают - тоже понятно - срабатывает прерывание по передаче, когда передача еще идет.

Я конечно найду решение до понедельника, но если кто имеет решение, прошу поделиться.
Спасибо.


--------------------
Уходя, оставьте свет...
Go to the top of the page
 
+Quote Post
Genadi Zawidowsk...
сообщение Sep 20 2014, 19:00
Сообщение #30


Профессионал
*****

Группа: Участник
Сообщений: 1 620
Регистрация: 22-06-07
Из: Санкт-Петербург, Россия
Пользователь №: 28 634



После добавления чего-то в буфер вызвать (запретив прерывания) обычную функцию проверки готовности и разрешения прерывания - первый байт выйдет по опросу, остальные пойдут по прерываниям.
Go to the top of the page
 
+Quote Post
Dog Pawlowa
сообщение Sep 20 2014, 19:56
Сообщение #31


Гуру
******

Группа: Свой
Сообщений: 2 702
Регистрация: 14-07-06
Пользователь №: 18 823



Цитата(Genadi Zawidowski @ Sep 20 2014, 22:00) *
обычную функцию проверки готовности и разрешения прерывания

Ага, спасибо!
Уже запустил с отдельным флагом, в принципе можно в качестве флага разрешение и использовать, но переделывать уже не буду:

Инициализация:
Код
    OffFlag(tx_over);
    tx_head0=tx_tail0=0;
    IE1 |= URXIE0+UTXIE0;


Укладка в буфер (DI/EI обязательны!)

Код
        __disable_interrupt();    
        PUT_TO_BUFFER(c);

#ifdef TX_INTERRUPT
        if (GetFlag(tx_over))
        {    IFG1 |= UTXIFG0;
            OffFlag(tx_over);
        }
#endif
        __enable_interrupt();


Ну и прерывание:
Код
    if (tx_tail0!=tx_head0)
    {    d=tx_buf0[tx_tail0];
        tx_tail0++;
        if (tx_tail0==TxBufSize0)
            tx_tail0=0;
        TXBUF0 = d;
    }
#ifdef TX_INTERRUPT
    else
        OnFlag(tx_over);
#endif



--------------------
Уходя, оставьте свет...
Go to the top of the page
 
+Quote Post

3 страниц V   1 2 3 >
Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 25th June 2025 - 11:32
Рейтинг@Mail.ru


Страница сгенерированна за 0.0176 секунд с 7
ELECTRONIX ©2004-2016