Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: софтовый уарт
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > MSP430
Zelepuk
нужно организовать дополнительный уарт в устройстве на МСП430, где заняты все аппаратные уарт. В сети есть примеры с использованием аппаратного таймера, но таймер тоже задействован. Таким образом, остаются два варианта:
1) совтовый на GPIO
2) мост SPI->UART

что лучше применить?
rezident
Цитата(Zelepuk @ Sep 14 2011, 16:13) *
нужно организовать дополнительный уарт в устройстве на МСП430, где заняты все аппаратные уарт. В сети есть примеры с использованием аппаратного таймера, но таймер тоже задействован. Таким образом, остаются два варианта:
1) совтовый на GPIO
В этом случае таймер все равно понадобится.
Цитата(Zelepuk @ Sep 14 2011, 16:13) *
2) мост SPI->UART
А потребление для вас рояли не играет? Или где вы такой нашли малопотребляющий мост?
Цитата(Zelepuk @ Sep 14 2011, 16:13) *
что лучше применить?
Взять другой кристалл с требуемым кол-вом UART.
Zelepuk
Цитата(rezident @ Sep 14 2011, 16:43) *
А потребление для вас рояли не играет? Или где вы такой нашли малопотребляющий мост?


http://www.gaw.ru/html.cgi/txt/ic/Maxim/in...RTs/max3100.htm

150 mkA - это много?

а ещё наверное можно доп. микроконтроллер взять и, связав его по SPI с основным, передавать через его UART данные.
rezident
Цитата(Zelepuk @ Sep 14 2011, 18:32) *
150 mkA - это много?
Откуда же я знаю, много это для вас или мало? Если у вас, допустим, в питании ионистор на пару Фарад, то 150мкА это дополнительный час (или даже два часа) работы прибора в автономном режиме.
MrYuran
Цитата(Zelepuk @ Sep 14 2011, 15:13) *
нужно организовать дополнительный уарт в устройстве на МСП430, где заняты все аппаратные уарт. В сети есть примеры с использованием аппаратного таймера, но таймер тоже задействован.

А второй? Обычно их два, и в каждом ещё минимум по три CCR.
Неужто все заняты?
Zelepuk
кроме того, еще нехватает GPIO как таковых, так что думаю идея поставить доп. микроконтроллер тут предпочтительнее. Ну например поставить младший мсп430 с потреблением порядка 200 мкА на 1МГц.
sensor_ua
Если ещё есть возможность, то лучше взять MSP по-жирнее. Мост типа MAX3100 достаточно дорогое удовольствие. Второй камень - экстенсивное решение - может сначала переделать работу таймеров? У меня, например, несколько проектов, где все интервалы реализованы на одном постоянно включенном таймере от подкалибровывающегося VLO, причем с уходом в LPM3. Изменяется шкала побудки по совпадению, а тайминги в конкретных местах (задачах - маленькая ОС) считаются по разнице отсчетов времени. Просто буквально вчера разгребал чужой проект на C8051F130, так там были задействованы все(!) PCA-модули и каждый для одной задержки - выбросил всё и оставил постоянно включенный таймер PCA0 - программа работает не хуже, а аппаратные ресурсы высвободились, объём кода уменьшился, да и стал он более прозрачным (и портируемым - подтягиваю к MSP).
Dog Pawlowa
Цитата(sensor_ua @ Sep 20 2011, 09:27) *
все интервалы реализованы на одном постоянно включенном таймере

А с дуплексом?
sensor_ua
Цитата
А с дуплексом?
Вопроса не понял
Dog Pawlowa
Ну если софтовый Уарт должен одновременно передавать и принимать, то его реализация на одном счетчике получается сложнее, не так ли?
Поэтому интересуюсь.
sensor_ua
Цитата
Если софтовый Уарт должен одновременно передавать и принимать

Набросал как в первом приближении (без подкалибровывания VLO и с низким разрешением) это могло бы выглядеть:

Код
typedef unsigned int CPU_Time_t;
CPU_Time_t CPU_Time(void){
  return TAR;
}
CPU_Time_t CPU_Elapsed(CPU_Time_t ts){
   return (CPU_Time() - ts);
}

int SW_UART_Rx_Byte(void){
  static CPU_Time_t ts;
  static int st;
  static unsigned char mask;
  static unsigned char Rx_byte;
  int rc = -1;

  switch(st)
  case 0:
    if(START_DETECT()){
      ts = CPU_Time(); st++;
    }
    break;
  case 1:
    if(CPU_Elapsed(ts) > CPU_uS(HALF_BIT_TIME_uS)){
      if(START_PIN_GET() == 0){
        ts = CPU_Time(); st++; // valid START received
        mask = 0x01; Rx_byte = 0;
      }else{
        st = 0;
      }  
    }
    break;
  case 2:
    if(CPU_Elapsed(ts) > CPU_uS(BIT_TIME_uS)){
      ts = CPU_Time();
      if(Rx_PIN_State_GET()) Rx_byte |= mask;
      mask <<= 1;
      if(!(mask & 0xFF)) st++; // 8 bits received
    }
    break;
  case 3:
    if(CPU_Elapsed(ts) > CPU_uS(BIT_TIME_uS)){
      if(Rx_PIN_State_GET()) rc = Rx_byte; // valid STOP received
      st = 0;
    }
    break;
  }
  return rc;
}

int SW_UART_Tx_Byte(int Tx_Byte){
  static CPU_Time_t ts;
  static int st;
  static unsigned char mask;
  static unsigned char Tx_tmp;
  int rc = -1;  

  if(TxByte & 0xFF00){// Tx break
    st = 0;
    return TxByte;
  }
  switch (st){
  case 0:
    Tx_tmp = Tx_Byte; mask = 0x01;
    TX_OUT_DOWN(); // START post
    ts = CPU_Time();
    st++;
    break;
  case 1:
    if(CPU_Elapsed(ts) > CPU_uS(BIT_TIME_uS)){
      ts = CPU_Time();
      if(Tx_tmp & mask) TX_OUT_UP();
      else TX_OUT_DOWN();
      mask <<= 1;
      if(!(mask & 0xFF)) st++; // 8 bits post
    }
    break;
  case 2:
    if(CPU_Elapsed(ts) > CPU_uS(BIT_TIME_uS)){
      ts = CPU_Time();
      TX_OUT_UP(); // STOP post
      st++;
    }
    break;
  case 3:
    if(CPU_Elapsed(ts) > CPU_uS(BIT_TIME_uS)){// end of STOP-bit
      rc = Tx_tmp;
      st = 0;
    }  
    break;
  }
  return(rc);
}

void echo(void){
  static int st;
  static int ch;
  int rx_tmp;

  rx_tmp =  SW_UART_Rx_Byte();
  switch (st){
    case 0:
      ch = rx_tmp;
      if( ch & 0xFF00) break;
      st++;
    case 1:
      if(SW_UART_Tx_Byte(ch) != ch) break;
      st = 0;
  }

}

Такое для низких скоростей и небольшой загрузки могло бы прокатить
GinRider
Если MCU всегда мастер, проще поставить внешний коммутатор на UART.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.