Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: UART MSP430F1611
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > MSP430
/Sergeant/
Добрый день. Изучил весь фак и все темы про UART, посмотрел примеры производителя, но так и не понял в чём у меня проблема.
Суть такова: есть некий чёрный ящик(как он устроен - не знаю). Обмениваюсь с ним по UART со скоростью 8889 бит/с. В ответ на определённую последовательность байт, он(ЧЯ) выдаёт свою последовательность. У меня выходит так: шлю по TXD байты - всё хорошо, в ответ приходит тоже последовательность байт - смотрел осциллографом, но RD буффер получает только последний байт. Вернее выставляется флаг ОЕ, то есть все байты "наслаиваются" друг на друга, не вызывая прерывания. И только после последнего байта срабатывет процедура обработки прерывания.

Вот кусок кода:

Код
#include <io430x16x.h>
#include <iostream.h>
#include <intrinsics.h>

static char string1[20];
char i;
char j = 0;

void Init()                     // Начальные установки
{
  WDTCTL = WDTPW+WDTHOLD;       // Отключаем WDT
  __enable_interrupt();       // Разрешение прерываний
  
  P5DIR = 0xFE;                // Р5.0 - ввод, остальные - вывод
  P6DIR = 0xFF;                 // Неиспользуемые выводы
  P6OUT = 0xFF;
  P3SEL = 0x30;           // Р3.4 и Р3.5 - в режиме UART
  P3DIR = 0xDF;                // P3.5: на ввод, остальные: на вывод
  
// Устанавливаем MCLK, SMCLK и выводим SMCLK на Р1.4
  BCSCTL1 = 0x00;            // "0" - включение ХТ2
  P1DIR = 0x9C;                 // P1.4(F8МГЦ), P1.3(WR), P1.2(RD#), P1.7(ВКЛ) конфигурируем на вывод
  P1OUT = 0x00;
  P1SEL = 0x10;                // P1.4 = SMCLK
  
  unsigned int i;
  do
  {
    IFG1 &= ~OFIFG;             // Очищаем флаг прерывания ошибки генератора OFIFG
    for (i = 0xFF; i > 0; i--); // Временная задержка (~50мкс)
  }
  while ((IFG1 & OFIFG));       // Флаг OFIFG ещё установлен?
  BCSCTL2 = SELM_2;             // Выбираем MCLK - биты 7-6 регистра BCSCTL2
                                // в конфигурации "10" - XT2CLK
  BCSCTL2 |= SELS;              // Выбор SMCLK: ХТ2CLK
}

/*----------------Обработка прерываний по приёму-----------------------*/
#pragma vector = USART0RX_VECTOR
__interrupt void Uart_RX(void)          // Обработка прерываний на приём от UART
{
  //IE1 &= ~URXIE0;       // Запрещение прерывания RX
  string1[j++] = U0RXBUF;
  //IE1 |= URXIE0;    // Разрешение прерывания RX
}
/*---------------------------------------------------------------*/

int main( void )
{
  Init();

  ME1 = UTXE0+URXE0;  // Разрешаем передачу/приём UART0
  U0CTL = CHAR+SWRST; // Инициализация(ресет) UART0
  U0TCTL = 0x20 /*+ URXSE*/;        // Выбор тактовой частоты SMCLK
  U0BR0 = 0x84;         //  Выбираем делитель тактовой частоты - 0х384
  U0BR1 = 0x03;         //
  U0CTL &= ~SWRST;    // Вкл UART - снимаем RST
  IE1 |= URXIE0;             // Прерывание по приёму
  
  /*---Начинается передача последовательности байт---*/
  __no_operation();
  while(!IFG1_bit.UTXIFG0);   // Ждём, пока освободится буфер на передачу
  U0TXBUF = 0x55;
  while(!IFG1_bit.UTXIFG0);
  U0TXBUF = 0xAD;
    while(!IFG1_bit.UTXIFG0);
  U0TXBUF = 0x01;
  while(!IFG1_bit.UTXIFG0);
  U0TXBUF = 0x00;
  while(!IFG1_bit.UTXIFG0);
  U0TXBUF = 0x00;
  while(!IFG1_bit.UTXIFG0);
  U0TXBUF = 0x10;
  while(!IFG1_bit.UTXIFG0);
  U0TXBUF = 0xEE;  
    while(!IFG1_bit.UTXIFG0);
  U0TXBUF = 0x55;
  while(!IFG1_bit.UTXIFG0);
  U0TXBUF = 0x92;
   __no_operation();
/*---Передачу закончили, ждём ответ---*/
   while(1)  {}
}


Запись в строку здесь взята из примера TI, вообще будет не так, но главное, что не срабатывает прерывание после приёма каждого байта. Или же здесь получается, что приходят скопом прерывания от всех байтов и обрабатывается только последнее? Но с отключением прерываний(закоменарены вкл/откл) выходит всё так же.
Передача временно сделана по опросу флага, но она работает и меня пока не беспокоит.

ЗЫ заранее прошу извинить, если еть очевидные косяки, ибо программированием проца занимаюсь недавно.
MrYuran
мне кажется, j надо объявить как volatile char j
aag
Скорость точно 8889 бит/с ?

Такое ощущение, что скрость другая, поэтому происходит рассинхронизация...

Вот такой пример попробуйте:
Код
#include <msp430x16x.h>

char rx_buffer[64]; //буффер на прием
int rx_size;  // размер буффера

char tx_buffer[32]; //буффер на передачу
int tx_size; //размер буффера
int tx_sent; //номер отправленного байта

int main()
{
  WDTCTL = WDTPW + WDTHOLD; //отключаем сторожевой таймер

  P3DIR = 0x0F;
  P3SEL = 0x30; // 00110000  (ноги 3.4 и 3.5 - uart)
  
  BCSCTL1 |= XTS;
  // тактирование происходит от кварцевого резонатора, подключенного к выходам XIn, XOut (первый резонатор)
  
  UCTL0 = SWRST;
  UCTL0 |= CHAR;
  UTCTL0 = SSEL0;
  UBR10 = 0x01;  //  эти числа выбранны для скорости 9600
  UBR00 = 0xA0;  //  при частоте резонатора 4 МГц
  UMCTL0 = 109;  //  (в вашем случае их надо изменить)
  ME1 |= (UTXE0 | URXE0);
  UCTL0 &= ~SWRST;
  IE1 |= URXIE0;
  IE1 |= UTXIE0;

  rx_size = 0;
  tx_sent = 0;
  tx_buffer[0] = 0x55;  // записываем байты,
  tx_buffer[1] = 0xAD; // которые будем отправлять
  tx_buffer[2] = 0x01;
  tx_buffer[3] = 0x00;
  tx_buffer[4] = 0x00;
  tx_buffer[5] = 0x10;
  tx_buffer[6] = 0xEE;
  tx_buffer[7] = 0x55;
  tx_buffer[8] = 0x92;
  tx_size = 9; // будем отравлять 9 байт из буффера
  
  _BIS_SR(GIE);

  TXBUF0 = tx_buffer[tx_sent++]; // отправка первого (нулевого) байта

  for(;;);
}

#pragma vector=USART0RX_VECTOR
__interrupt void RxD(void)
{
  if (rx_size < 63)
    rx_buffer[rx_size++] = RXBUF0; // запись полученных байтов
}

#pragma vector=USART0TX_VECTOR
__interrupt void TxD()
{
  if (tx_sent < tx_size)
    TXBUF0 = ts_buffer[tx_sent++]; // передача байтов из буффера
  else
  {
    tx_sent = 0;
    tx_size = 0;
  }
}
/Sergeant/
Цитата(aag @ Apr 22 2008, 12:50) *
Скорость точно 8889 бит/с ?

Такое ощущение, что скрость другая, поэтому происходит рассинхронизация...

Вот такой пример попробуйте:
Код
int main()
{

...

  TXBUF0 = tx_buffer[tx_sent++]; // здесь какой-то глюк, tx_sent автоматически увеличивается на
                                                  // единицу, после того как сделал так: TXBUF0 = tx_buffer[tx_sent];
                                                  // стало на отправку работать правильно

  for(;;);
}

#pragma vector=USART0RX_VECTOR
__interrupt void RxD(void)
{
  if (rx_size < 63)
    rx_buffer[rx_size++] = RXBUF0; // запись полученных байтов
}

#pragma vector=USART0TX_VECTOR
__interrupt void TxD()
{
  if (tx_sent < tx_size)
    TXBUF0 = ts_buffer[tx_sent++]; // передача байтов из буффера
  else
  {
    tx_sent = 0;
    tx_size = 0;
  }
}


Такой пример попробовал(обозначил небольшой глюк выше), но всё по-прежнему - на проц приходит пакет байтов, но обрабатывать их он не желает. Скорость с которой приходят байты, судя по осциилографу, именно 8889 бит/с или очень близко к тому. Что там можно ещё наковырять? Значение модуляции менять? На какое?
Сергей Борщ
Цитата(/Sergeant/ @ Apr 22 2008, 14:48) *
Что там можно ещё наковырять? Значение модуляции менять? На какое?
Не нужно методом "тыка" подкручивать регистры с непонятными названиями. Если бы у вас проблема была в скорости, то данные принимались бы с искажениями, но принимались. Посмотрите внимательно на свой обработчик передачи. Что происходит после того, как переданы все данные? Вы обнуляете переменные и выходите. Что происходит с флагом, вызвавшим прерывание? Н-и-ч-е-г-о. Что произойдет после выхода из обработчика? Вы снова попадете в этот же обработчик передачи. Вам надо не только обнулить переменные, но и запретить прерывание передачи. И помните, что все переменные, которые у вас используются и в прерывании и в основной программе должны быть volatile

Добавлено: Извиняюсь. Сходил по ссылке от VAI и нашел там упоминание, что TXIFG сбрасывается при переходе по вектору. Жаль, что это не описано в user guide в описании самого бита, там есть только UTXIFG0 is set when U0TXBUF is empty, что несколько сбивает с толку. Второй раз попадаюсь sad.gif
VAI
Посмотрите там мой пост, я выкладывал рабочий код? который использую для msp430а149 и 1611
http://electronix.ru/forum/index.php?showtopic=25624&hl=
/Sergeant/
Цитата(Сергей Борщ @ Apr 22 2008, 16:26) *
Не нужно методом "тыка" подкручивать регистры с непонятными названиями. Если бы у вас проблема была в скорости, то данные принимались бы с искажениями, но принимались. Посмотрите внимательно на свой обработчик передачи. Что происходит после того, как переданы все данные? Вы обнуляете переменные и выходите. Что происходит с флагом, вызвавшим прерывание? Н-и-ч-е-г-о. Что произойдет после выхода из обработчика? Вы снова попадете в этот же обработчик передачи. Вам надо не только обнулить переменные, но и запретить прерывание передачи. И помните, что все переменные, которые у вас используются и в прерывании и в основной программе должны быть volatile


Спасибо за напоминание про volatile. А про передачу - в первом варианте у меня передача была не по прерыванию, а по опросу флага и прерывания по передаче были запрещены. Думаю, что на приём это никоим образом не повлияло в данном случае. Или я что-то неправильно понял? Естественно поравлю запрет прерывания передачи.


Цитата(VAI @ Apr 22 2008, 16:28) *
Посмотрите там мой пост, я выкладывал рабочий код? который использую для msp430а149 и 1611
http://electronix.ru/forum/index.php?showtopic=25624&hl=


Спасибо. Читал эту тему, но код не пробовал. Сейчас попробую.
/Sergeant/
Цитата(VAI @ Apr 22 2008, 16:28) *
Посмотрите там



Уф, огромное спасибо. Хоть и "играл" с Вашей программой целый день, но получил то, чего хотел.
smile3046.gif
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.