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

 
 
 
Reply to this topicStart new topic
> MSP430F2132. И снова UART, Прошу помощи новичку в MSP430
Зураб
сообщение Aug 11 2010, 15:35
Сообщение #1





Группа: Участник
Сообщений: 10
Регистрация: 11-11-07
Пользователь №: 32 244



Доброго времени суток, уважаемые коллеги!
Волею судеб, так сказать, перешёл от AVR и 51-х к MSP430 и вот уже три дня бьюсь с UART на MSP430F2132. Почитал форум, использовал примеры, но всё напрасно. Короче, помогите. Итак: пишу программу в ИАР 5.10.1, запускаю в Протеусе 7.7, пробовал и в железе. Частота кварца 7372800Hz, хочу получить битрейд 9600. Вот код:
Код
#include  "msp430x21x2.h"

#define RX_BUFFER_SIZE 24
unsigned char rx_buffer[RX_BUFFER_SIZE];

unsigned char rx_wr_index=0,rx_rd_index=0;
volatile unsigned char rx_counter=0;
unsigned char rx_buffer_overflow=0;
unsigned char i, b, command, ks, valid, addr[2], dat[16];
unsigned char *pdat = dat;

void pins_init(void){
  P1DIR=0xFF;
  P1OUT=0x11;
}

void osc_init(void){
  BCSCTL1 |= XTS;                           // ACLK = LFXT1 = HF XTAL
  BCSCTL3 |= LFXT1S1;                       // 3 – 16MHz crystal or resonator
  do
  {
    IFG1 &= ~OFIFG;                         // Clear OSCFault flag
    for (i = 0xFF; i > 0; i--);             // Time for flag to set
  }
  while (IFG1 & OFIFG);                     // OSCFault flag still set?
  BCSCTL2 |= SELM_3 + SELS;                 // MCLK = SMCLK = LFXT1 (safe)  
}

void uart_init(void){
  P3DIR |= BIT4;
  P3SEL = 0x30;
  UCA0CTL1 |= UCSSEL_3;                     // SMCLK
  //UCA0CTL0 = UCMSB;
  UCA0BR0 = 0x00;                           // 7372800Hz/9600 = 0x0300
  UCA0BR1 = 0x03;
  UCA0MCTL = 0;                             // Modulation UCBRSx = 0
  UCA0CTL1 &= ~UCSWRST;                     // **Initialize USCI state machine**
  IE2 |= UCA0RXIE;  
}  

unsigned char get(void)
{
  unsigned char data;
  //wdt_reset();
  while(rx_counter==0){};
  data=rx_buffer[rx_rd_index];
  if(++rx_rd_index == RX_BUFFER_SIZE){
    rx_rd_index=0;
  }    
  __bic_SR_register(GIE);
  --rx_counter;
  __bis_SR_register(GIE);
  return data;
}

void put(unsigned char data){
    while (!(IFG2 & UCA0TXIFG));
    UCA0TXBUF = data;
}

void put0(unsigned char num){
    for(i=0;i<num;i++)put(0);
}

unsigned char receivedata(void){
    command=get(); //приняли команду 1 байт
    // принимаем адрес 2 байта
    for(i=0;i<2;i++){      
        addr[i]=get();
    }          
    //вычисляем контрольную сумму и ...
    b=0x55^command^addr[0]^addr[1];
    // ... одновременно принимаем данные 16 байт
    for(i=0;i<16;i++){
        dat[i]=get();
        b=b^dat[i];
    }
    ks=get();//приняли контрольную сумму
    //далее проверка контрольной суммы
    if(b!=ks){
    // контрольная сумма некорректна
        put(0x55);
        put(0x41);
        put(0x01);
        put0(17);
        put(0x15);
    return 1;
    }else return 0;        
}

void main(void){
  WDTCTL = WDTPW + WDTHOLD;
  pins_init();
  osc_init();
  uart_init();
  __bis_SR_register(GIE);

  while(1){
    b=get();
    if(b==0x55){ //нашли метку во входной информации, далее принимаем все 20 байтов
      receivedata();
      //основной процесс обработки и выполнения команд
      if(command==0x10){
      //case 0x10:
        // проверяем валидность ключевой комбинации
        valid=1;
        if(addr[0]!=0x12)valid=0;
    if(addr[1]!=0x34)valid=0;
        if(valid){
      put(0x55);
      put(0x41);
      put(0x02);
      put0(17);
      put(0x16);          
        }else{
      put(0x55);
      put(0x41);
      put(0x03);
      put0(17);
      put(0x17);          
        }  
      }
    }
  }
}  



// USCI A0/B0 Receive ISR
#pragma vector=USCIAB0RX_VECTOR
__interrupt void USCI0RX_ISR(void)
{
  if(!(UCA0STAT & UCRXERR))
     {
      rx_buffer[rx_wr_index]=UCA0RXBUF;
      if (++rx_wr_index == RX_BUFFER_SIZE) rx_wr_index=0;
      if (++rx_counter == RX_BUFFER_SIZE)
        {
          rx_counter=0;
          rx_buffer_overflow=1;
        }
     }
}

Кидаю по ком-порту последовательность 55.10.12.34.00.00.00.00.00.00.00.00.00.00.00.00.00.00.00.00.63, получаю через раз C5. Почему так? Что не правильно? В протеусе все частоты (MCLK, SMCLK, ACLK выставил равными кварцевой частоте).
Go to the top of the page
 
+Quote Post
rezident
сообщение Aug 11 2010, 20:24
Сообщение #2


Гуру
******

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



В функцию uart_init добавьте третьей строкой
Код
UCA0CTL1 |= UCSWRST;

Потому, что бит UCSWRST должен быть установлен на время инициализации регистров модуля USCI.
В обработчик прерывания USCI0RX_ISR добавьте вторую ветку ветвления для else потому, что биты ошибок сами не сбрасываются. Если возникла ошибка на приеме, то нужно либо прочитать регистр UCA0RXBUF, либо регистр UCA0STAT почистить "вручную" (программно).
Кроме того, настоятельно рекомендую инициализировать все регистры явными значениями, а не накладывать маски на дефолтные состояния, возникающие при подаче питания или после сброса.
Ну и насчет MCLK. Надежнее тактировать MCLK от DCO. Потому, что после сброса или включения питания MCLK тактируется от DCO. И даже если вы переключили его тактирование на кварцевый генератор, но в его работе произошел сбой, то MCLK автоматически переключается на DCO. После этого нужно обрабатывать прерывание по вектору NMI и восстанавливать работу модуля тактирования. У вас же такого обработчика прерывания нет. Так что все может случиться, особенно при неудачной трассировке платы. Я обычно рекомендую MCLK тактировать именно от DCO. Для этого нужно настроить регистры DCOCTL и BCSCTL1. Если вы еще не успели запортить сегмент INFO, то можно загружать калиброванные значения для этих регистров из TLV структуры, расположенной в INFO_A.
Еще один нюанс. Как именно вы проверяете работу UART? Если у вас в дебаггере открыто окно с регистрами USCI, то могут теряться прерывания от него. Чтение регистра UCA0RXBUF для отображения в этом окне, сбрасывает UCA0RXIFG. Следует иметь в виду этот факт.
Эскизы прикрепленных изображений
Прикрепленное изображение
 
Go to the top of the page
 
+Quote Post
Зураб
сообщение Aug 12 2010, 09:42
Сообщение #3





Группа: Участник
Сообщений: 10
Регистрация: 11-11-07
Пользователь №: 32 244



Спасибо за быстрый ответ!
Цитата
Как именно вы проверяете работу UART?

К сожалению, дебаггера пока нет. Пытаюсь сначала симулировать в Протеусе, затем с помощь BSL загружаю в железо. Сейчас убедился, что Протеус и железо ведут себя по разному. Видимо из-за Simulation is not running in real time... Думаю теперь тестировать только в железе.
Сейчас пытаюсь разобраться с DCO. Мозги кипят.
Цитата
Надежнее тактировать MCLK от DCO

То есть можно оставить MCLK всегда тактироваться от DCO? А как же стабильность частоты?
Цитата
после сброса или включения питания MCLK тактируется от DCO

Значит DCO по умолчанию настроен на какую-то частоту? На какую? Если источником синхросигнала для UART выбрать кварц, а MCLK оставить как есть от DCO будет ли моя программа работать (я насчёт синхронизации процессора и UART)? В железе не работает.
Go to the top of the page
 
+Quote Post
rezident
сообщение Aug 12 2010, 16:20
Сообщение #4


Гуру
******

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



Цитата(Зураб @ Aug 12 2010, 15:42) *
То есть можно оставить MCLK всегда тактироваться от DCO?
Да, можно. Я считаю, что не просто можно, а даже нужно! smile.gif
Цитата(Зураб @ Aug 12 2010, 15:42) *
А как же стабильность частоты?
А что там со стабильностью DCO? Вроде не хуже 1% во всем рабочем температурном диапазоне при условии стабильности питания. И почему вас волнует стабильность частоты тактирования ядра микроконтроллера? Где вы еще используете MCLK? Для USCI используется SMCLK или ACLK, которые как раз лучше от кварцевого генератора затактировать. Аналогично с таймерами, если вы хотите отсчитывать временные интервалы.
Цитата(Зураб @ Aug 12 2010, 15:42) *
Значит DCO по умолчанию настроен на какую-то частоту? На какую?
Около 1МГц. Это в даташите указано.
Цитата(Зураб @ Aug 12 2010, 15:42) *
Если источником синхросигнала для UART выбрать кварц, а MCLK оставить как есть от DCO будет ли моя программа работать (я насчёт синхронизации процессора и UART)? В железе не работает.
Источником тактового сигнала для UART может выбираться внешний сигнал, поступающий на пин UC0CLK, или внутренние тактовые сигналы SMCLK или ACLK, которые в свою очередь могут тактироваться от DCO или от кварцевого генератора (LFXT или XT2, второго нет в вашем кристалле) или от VLO. Программу выполняет ядро процессора, которое тактируется только от MCLK. UART работает сам по себе, вне зависимости от работы или неработы (спячки) ядра.
Вам видимо нужно более тщательно разобраться с устройством и функционированием Basic Clock Module в MSP430.
Go to the top of the page
 
+Quote Post
Зураб
сообщение Aug 12 2010, 17:28
Сообщение #5





Группа: Участник
Сообщений: 10
Регистрация: 11-11-07
Пользователь №: 32 244



Применил советы на практике, оставил MCLK от DCO, ввел прерывание на вектор NMI, залил прошивку в железо. Всё работает! Спасибо огромное! biggrin.gif Правда не разобрался с настройками DCO, но это потом, при необходимости.
Go to the top of the page
 
+Quote Post

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

 


RSS Текстовая версия Сейчас: 22nd July 2025 - 06:35
Рейтинг@Mail.ru


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