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

 
 
> Тема может быть избита. не понимаю как оргнизовать работу 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
 
Start new topic
Ответов
Сергей Борщ
сообщение Jan 8 2007, 14:54
Сообщение #2


Гуру
******

Группа: Модераторы
Сообщений: 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
zltigo
сообщение May 5 2008, 16:05
Сообщение #3


Гуру
******

Группа: Свой
Сообщений: 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
rezident
сообщение May 6 2008, 18:42
Сообщение #4


Гуру
******

Группа: Свой
Сообщений: 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
Сообщение #5


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

Группа: Свой
Сообщений: 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
Сообщение #6


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

Группа: Свой
Сообщений: 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
Сообщение #7


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

Группа: Свой
Сообщений: 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
Сообщение #8


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

Группа: Свой
Сообщений: 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

Сообщений в этой теме
- AlHakim   Тема может быть избита. не понимаю как оргнизовать работу UART по прерывания(+)   Jan 8 2007, 12:58
- - HARMHARM   Позволю себе сделать несколько замечаний. 1. При р...   Jan 8 2007, 13:58
- - AlHakim   Цитата(HARMHARM @ Jan 8 2007, 15:58) 2. П...   Jan 8 2007, 14:24
- - HARMHARM   Не успел добавить комментарии, прочтите моё сообще...   Jan 8 2007, 14:30
|- - rezident   Цитата(Сергей Борщ @ Jan 8 2007, 16:54) Ц...   Jan 8 2007, 15:33
||- - Сергей Борщ   Цитата(rezident @ Jan 8 2007, 14:33) Пере...   Jan 8 2007, 21:12
|- - AHTOXA   Цитата(zltigo @ May 5 2008, 22:05) Можно ...   May 6 2008, 18:30
||- - zltigo   Цитата(AHTOXA @ May 6 2008, 20:30) Или же...   May 7 2008, 05:38
||- - Сергей Борщ   Цитата(zltigo @ May 7 2008, 08:38) Просто...   May 7 2008, 06:50
|- - rezident   Цитата(MrYuran @ May 7 2008, 10:39) А я в...   May 7 2008, 08:56
|- - Сергей Борщ   Цитата(rezident @ May 7 2008, 11:56) Флаж...   May 7 2008, 10:05
- - AlHakim   Цитата(Сергей Борщ @ Jan 8 2007, 16:54) П...   Jan 8 2007, 15:05
|- - Dog Pawlowa   У меня рабочий код. Пока тут в грязь не ткнули ...   Jan 8 2007, 15:27
|- - Сергей Борщ   Цитата(AlHakim @ Jan 8 2007, 14:05) Цитат...   Jan 8 2007, 15:41
- - jorikdima   Посматрите AppNotes на сайте TI. Для каждого семей...   Jan 8 2007, 15:25
- - AlHakim   Сергей Борщ Попробовал использовать Ваш код, полу...   Jan 8 2007, 15:41
|- - Сергей Борщ   Цитата(AlHakim @ Jan 8 2007, 14:41) Серге...   Jan 8 2007, 16:15
- - VAI   А я был уверен, что выкладывал и прием и передачу ...   Jan 8 2007, 15:51
- - jorikdima   http://www.ti.com/litv/zip/slac015k тут простейшие...   Jan 8 2007, 16:24
- - AlHakim   Спасбо всем, а в особенности Сергею   Jan 8 2007, 18:46
- - Kurt   вопрос действительно уже не раз поднимавшийся и в ...   May 7 2008, 05:28
- - Dog Pawlowa   Оппа... Понадобилось перевести передачу на прерыва...   Sep 20 2014, 18:37
- - Genadi Zawidowski   После добавления чего-то в буфер вызвать (запретив...   Sep 20 2014, 19:00
- - Dog Pawlowa   Цитата(Genadi Zawidowski @ Sep 20 2014, 22...   Sep 20 2014, 19:56


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

 


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


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