AlHakim 0 8 января, 2007 Опубликовано 8 января, 2007 · Жалоба Нашел примеры работы 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; } } Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
HARMHARM 0 8 января, 2007 Опубликовано 8 января, 2007 (изменено) · Жалоба Позволю себе сделать несколько замечаний. 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? Изменено 8 января, 2007 пользователем HARMHARM Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
AlHakim 0 8 января, 2007 Опубликовано 8 января, 2007 · Жалоба 2. При работе с RS485 я лично делаю так: при начале передачи даю разрешение на драйвер и отключаю прерывание RX, чтобы не принять свою собственную посылку если что. В конце передачи запрещаю драйвер, читаю RXBUF дабы очистить флаги и уже потом разрешаю прерывание RX. Такая схема откатана и работает. Делаю так всегда, даже если у чипа RS485 есть запрещение приёма. ну вообщем-то код пишетс яне только для работы по Rs485. Так и сделал уже(запрещаю прерывания) Код прерываний у Вас, похоже, рабочий. Еще не совсем понятна конструкция URCTL1 &= ~ (FE+PE+OE+BRK+RXERR); // Clear error flags ибо Reading UxRXBUF resets the receive-error bits, the RXWAKE bit, and URXIFGx. И еще причем здесь URCTL1? Вы ведь испольуете первый USART? Ошибочка закралась, да и точно снимаются они чтением UxRXBUF Спасибо :) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
HARMHARM 0 8 января, 2007 Опубликовано 8 января, 2007 · Жалоба Не успел добавить комментарии, прочтите моё сообщение еще раз ;) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Сергей Борщ 140 8 января, 2007 Опубликовано 8 января, 2007 · Жалоба Модуль 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); } 2. При работе с RS485 я лично делаю так: при начале передачи даю разрешение на драйвер и отключаю прерывание RX, чтобы не принять свою собственную посылку если что. В конце передачи запрещаю драйвер, читаю RXBUF дабы очистить флаги и уже потом разрешаю прерывание RX.Зачем такие сложности если можно отключить прием ( ME1 &= ~URXE0 )? Код прерываний у Вас, похоже, рабочий.Похоже, что нет. Когда все передано прерывание передачи не запрещается и в буфер ничего не пишется. Таким образом программа постоянно после выхода из обработчика передачи снова попадает в него же. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
AlHakim 0 8 января, 2007 Опубликовано 8 января, 2007 · Жалоба Похоже, что нет. Когда все передано прерывание передачи не запрещается и в буфер ничего не пишется. Таким образом программа постоянно после выхода из обработчика передачи снова попадает в него же. я не утвержадю что рабочий на все 100, но повторного вхождни я впрерывание не проихслжит поскольку аппаратно в перрывание снимается бит UTXIFG0 Попробую использовать ваш код вот еще возникла пролемка, если не сложно прокомментируйте while(*str) Uart0PutChar(*str++); //*s++=Tmpchar; странно передает н мой текст а часть его плюс мусор в отлачике по шагам проходит в run-time не всегда, чаще нет, видимо используемые регистры в перрывание изменяются :( Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jorikdima 0 8 января, 2007 Опубликовано 8 января, 2007 · Жалоба Посматрите AppNotes на сайте TI. Для каждого семейства есть примеры работы. Например slac015k Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
DogPawlowa 0 8 января, 2007 Опубликовано 8 января, 2007 (изменено) · Жалоба У меня рабочий код. Пока тут в грязь не ткнули :) Пожалуйста ;) Линейный буфер, 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: Изменено 8 января, 2007 пользователем Dog Pawlowa Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
rezident 0 8 января, 2007 Опубликовано 8 января, 2007 · Жалоба Код прерываний у Вас, похоже, рабочий.Похоже, что нет. Когда все передано прерывание передачи не запрещается и в буфер ничего не пишется. Таким образом программа постоянно после выхода из обработчика передачи снова попадает в него же. Переход по вектору прерывания от передатчика автоматически сбрасывает флаг вызова прерывания. Так что лишний вызов произойдет только один раз по окончании передачи. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Сергей Борщ 140 8 января, 2007 Опубликовано 8 января, 2007 · Жалоба Похоже, что нет. Когда все передано прерывание передачи не запрещается и в буфер ничего не пишется. Таким образом программа постоянно после выхода из обработчика передачи снова попадает в него же. я не утвержадю что рабочий на все 100, но повторного вхождни я впрерывание не проихслжит поскольку аппаратно в перрывание снимается бит UTXIFG0 В каком месте снимается? Я вижу что если передавать больше нечего то все закомментировано. while(*str) Uart0PutChar(*str++); //*s++=Tmpchar; странно передает н мой текст а часть его плюс мусор в отлачике по шагам проходит в run-time не всегда, чаще нет, видимо используемые регистры в перрывание изменяются :( Uart0Tx.PtrWrByte и Uart0Tx.PtrRdByte объявлены как volatile? Скорее всего нет, иначе компилятор выдавал бы предупреждения на конструкции вроде if (Uart0Tx.PtrWrByte != Uart0Tx.PtrRdByte). Дальше уже может твориться все что угодно. Еще может не хватать стека - для начала увеличьте его размер. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
AlHakim 0 8 января, 2007 Опубликовано 8 января, 2007 (изменено) · Жалоба Сергей Борщ Попробовал использовать Ваш код, получил тоже само что и было у мен явначале программа зациклилась while(( (Tmp - TxTail) & (TX_BUFF_SIZE - 1)) == (TX_BU причем Uart0PutChar(0x30); - выполняется, а Uart0PutStr("qwe"); зацикливается Изменено 8 января, 2007 пользователем AlHakim Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
VAI 0 8 января, 2007 Опубликовано 8 января, 2007 · Жалоба А я был уверен, что выкладывал и прием и передачу по прерыванию. Исправляюсь. UART.rar Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Сергей Борщ 140 8 января, 2007 Опубликовано 8 января, 2007 · Жалоба Сергей Борщ Попробовал использовать Ваш код, получил тоже само что и было у мен явначале программа зациклилась 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 } Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jorikdima 0 8 января, 2007 Опубликовано 8 января, 2007 · Жалоба http://www.ti.com/litv/zip/slac015k тут простейшие и наипонятнийшие примеры. например uart07_09600 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
AlHakim 0 8 января, 2007 Опубликовано 8 января, 2007 · Жалоба Спасбо всем, а в особенности Сергею Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться