Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: MSP-EXP430F5529
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > MSP430
*rust*
Добрый день!

Есть борд MSP-EXP430F5529. Запускаю I2C. Среда IAR.
Загрузил пример от TI MSP430F55xx_uscib0_i2c_05, который делает борд ведомым передатчиком и отправляет число по I2C мастеру.
Заметил странность, мастер получает числа как будто деленные на 2. В теле программы создал константу и отправляю ее на передачу, мастером вижу, что число в два раза меньше, к примеру оправляю 0xAA получаю 0x55, отправляю 0хFF получаю 0x7F.
Такое ощущение что сдвиговый регистр отнимает единицу от количества требуемых сдвигов, из-за этого получается деление на два. Читал мануал, код вроде правильный, а непонимание есть.
Что это такое, как это понять и устранить?
rezident
А кто у вас мастер-то?
*rust*
Мастер FTDI-микросхема, данные смотрю на компьютере. К мастеру вопросов нет, с AVR и ARMом работает нормально.
rezident
Дайте ссылку, откуда берете ваш пример? Или приведите здесь этот исходник.
*rust*
Код
#include <msp430f5529.h>

unsigned char TXData;
unsigned char i=0;

void main(void)
{
  WDTCTL = WDTPW + WDTHOLD;                 // Stop WDT

  P3SEL |= 0x03;                            // Assign I2C pins to USCI_B0
  UCB0CTL1 |= UCSWRST;                      // Enable SW reset
  UCB0CTL0 = UCMODE_3 + UCSYNC;             // I2C Slave, synchronous mode
  UCB0I2COA = 0x48;                         // Own Address is 048h
  UCB0CTL1 &= ~UCSWRST;                     // Clear SW reset, resume operation
  UCB0IE |= UCTXIE + UCSTTIE + UCSTPIE;     // Enable TX interrupt
                                            // Enable Start condition interrupt
  TXData = 0xAA;                               // Used to hold TX data

  __bis_SR_register(LPM0_bits + GIE);       // Enter LPM0 w/ interrupts
  __no_operation();                         // For debugger
}

// USCI_B0 State ISR
#pragma vector = USCI_B0_VECTOR
__interrupt void USCI_B0_ISR(void)
{
  switch(__even_in_range(UCB0IV,12))
  {
  case  0: break;                           // Vector  0: No interrupts
  case  2: break;                           // Vector  2: ALIFG
  case  4: break;                           // Vector  4: NACKIFG
  case  6:                                  // Vector  6: STTIFG
     UCB0IFG &= ~UCSTTIFG;                  // Clear start condition int flag
     break;
  case  8:                                  // Vector  8: STPIFG
    //TXData++;                               // Increment TXData
    UCB0IFG &= ~UCSTPIFG;                   // Clear stop condition int flag
    break;
  case 10: break;                           // Vector 10: RXIFG  
  case 12:                                  // Vector 12: TXIFG
    UCB0TXBUF = TXData;                     // TX data
    break;
  default: break;
  }
}


Вот ссылка на архив со всеми примерами для данного кристалла
rezident
Вроде никакого криминала нет. А резисторы на шине I2C какого номинала?
*rust*
по 10кОм
KARLSON
Самая лучшая проверка - осциллографом.
*rust*
Передаю 0xFF
Смотрю на осциллографе прием адреса, аск далее передача байта. Мастер дает 9 клоков, на первый клок MSP молчит. Передача начинается со второго клока.
*rust*
Дополнение:

После приема адреса и ответа аска, линия SDA находиться в нуле до клоков для принятия байта мастером. Чисто случайно отключил питание, борд запитался через резисторы I2C, а линия SDA после принятия адреса и ответа аском стала устанавливаться в 1 и мастером я принимаю правильную дату.
*rust*
Что еще можно посмотреть, вообще не понимаю что происходит? Как только запитываю штатно - все, MSP передает на один бит меньше.

Попробовал переделать код на другой модуль I2C, в F5529 их два. Результат такой же. MSP не реагирует на первый клок от мастера, если он начинается с переднего фронта.
rezident
Уменьшите номиналы резисторов вдвое. На какой частоте идет обмен? Попробуйте увеличить частоту тактирования MCLK и SMCLK хотя бы до 8МГц. Для этого нужно проинициализировать модуль тактирования. В вашем примере модуль тактирования не инициализируется и поэтому ядро работает на частоте около 1МГц.
*rust*
Поставил уже резисторы 4.7кОм-результат тот же. Частоту менял, пробовал от 100кГц до 1МГц - все равно одинаковое поведение. Попробую про инициализировать модуль тактирования, хотя, на мой взгляд, пример от разработчика все же должен работать без изменений, на то он и пример.
rezident
1МГц на шине с резисторами 10 кОм??? blink.gif Вы никаких, извиняюсь, необычных грибов на обед не вкушали? Уменьшите частоту на шине до 10кГц хотя бы, раз частоту тактирования ядра MSP430 поднимать лениво. Кстати, а резисторы на шине к питанию MSP430 подтянуты или к другому напряжению? У FTDI на VССIO то же самое по величине напряжение, что и на MSP430 подается, надеюсь?
*rust*
Цитата
Вы никаких, извиняюсь, необычных грибов на обед не вкушали?

Что за истерика?

Своей фразой я хотел лишь подчеркнуть, что поведение модуля при частотах от 100кГц до 1МГц одинаковое. Это же не криминал, чисто из любопытства попробовать разные частоты, никто ж в конечном счете не умрет. Все проверки делал на частоте 100кГц.

Код
Кстати, а резисторы на шине к питанию MSP430 подтянуты или к другому напряжению? У FTDI на VССIO то же самое по величине напряжение, что и на MSP430 подается, надеюсь?


Все по спецификации I2C.


*rust*
Частоту тактирования поднял уже до 16МГц, MSP передает корректные данные по I2c только на скорости до 200 kbps, дальше опять сдвиг на один бит. На какой частоте тактирования MSP сможет нормально передавать данные по I2C на скорости 400 kbps, если вообще в частоте дело?
*rust*
Неужели с такой проблемой никто не сталкивался?
rezident
Дык все-таки, какие по величине резисторы pull-up на шине? И почему вы так боитесь показать всю схему подключения целиком? Ну не верю я что там есть что-то секретное sm.gif
*rust*
Резисторы по 4.7кОм. Проверяю на частоте от 400кГц и ниже. Абсолютно ничего секретного, питание FTDI и борда 3.3В резисторы есть со стороны FTDI и со стороны борда. Эти два устройства физически соединяются тремя проводами: (SDA, SCL, GND). Уже попробовал частоту тактирования MSP повышать до 25Мгц, макс. частота обмена при котором получаю нормальную, не сдвинутую дату примерно 320кГц. Могу картинку с осциллографа показать если нужно.

Вот код:
Код
#include <msp430f5529.h>

unsigned char TXData;
void SetVcoreUp (unsigned int level);

void main(void)
{
  volatile unsigned int i;

  WDTCTL = WDTPW+WDTHOLD;                   // Stop WDT
  
  P1DIR |= 0x01;                            // Set P1.0 to output direction
  P1OUT  = 0x01;

  P1DIR |= BIT1;                            // P1.1 output

  P1DIR |= BIT0;                            // ACLK set out to pins
  P1SEL |= BIT0;                            
  P2DIR |= BIT2;                            // SMCLK set out to pins
  P2SEL |= BIT2;                            
  P7DIR |= BIT7;                            // MCLK set out to pins
  P7SEL |= BIT7;          

    //*********************   I2C  ****************************
  P3SEL |= 0x03;                            // Assign I2C pins to USCI_B0
  UCB1CTL1 |= UCSSEL1;
  UCB0CTL1 |= UCSWRST;                      // Enable SW reset
  UCB0CTL0 = UCMODE_3 + UCSYNC;             // I2C Slave, synchronous mode
  UCB0I2COA = 0x48;                         // Own Address is 048h
  UCB0CTL1 &= ~UCSWRST;                     // Clear SW reset, resume operation
  UCB0IE |= UCTXIE + UCSTTIE + UCSTPIE;     // Enable TX interrupt
                                            // Enable Start condition interrupt
  TXData = 0x7F;                            // Used to hold TX data

  //*********************************************************
  
  
  // Increase Vcore setting to level3 to support fsystem=25MHz
  // NOTE: Change core voltage one level at a time..
  SetVcoreUp (0x01);
  SetVcoreUp (0x02);  
  SetVcoreUp (0x03);  
  
  UCSCTL3 = SELREF_2;                       // Set DCO FLL reference = REFO
  UCSCTL4 |= SELA_2;                        // Set ACLK = REFO

  __bis_SR_register(SCG0);                  // Disable the FLL control loop
  UCSCTL0 = 0x0000;                         // Set lowest possible DCOx, MODx
  UCSCTL1 = DCORSEL_7;                      // Select DCO range 50MHz operation
  UCSCTL2 = FLLD_1 + 762;                   // Set DCO Multiplier for 25MHz
                                            // (N + 1) * FLLRef = Fdco
                                            // (762 + 1) * 32768 = 25MHz
                                            // Set FLL Div = fDCOCLK/2
  __bic_SR_register(SCG0);                  // Enable the FLL control loop

  // Worst-case settling time for the DCO when the DCO range bits have been
  // changed is n x 32 x 32 x f_MCLK / f_FLL_reference. See UCS chapter in 5xx
  // UG for optimization.
  // 32 x 32 x 25 MHz / 32,768 Hz ~ 780k MCLK cycles for DCO to settle
  __delay_cycles(782000);

  // Loop until XT1,XT2 & DCO stabilizes - In this case only DCO has to stabilize
  do
  {
    UCSCTL7 &= ~(XT2OFFG + XT1LFOFFG + DCOFFG);
                                            // Clear XT2,XT1,DCO fault flags
    SFRIFG1 &= ~OFIFG;                      // Clear fault flags
  }while (SFRIFG1&OFIFG);                   // Test oscillator fault flag
  
  __bis_SR_register(GIE);       // Enter LPM0 w/ interrupts
  
  while(1)
  {}
}

void SetVcoreUp (unsigned int level)
{
  // Open PMM registers for write
  PMMCTL0_H = PMMPW_H;              
  // Set SVS/SVM high side new level
  SVSMHCTL = SVSHE + SVSHRVL0 * level + SVMHE + SVSMHRRL0 * level;
  // Set SVM low side to new level
  SVSMLCTL = SVSLE + SVMLE + SVSMLRRL0 * level;
  // Wait till SVM is settled
  while ((PMMIFG & SVSMLDLYIFG) == 0);
  // Clear already set flags
  PMMIFG &= ~(SVMLVLRIFG + SVMLIFG);
  // Set VCore to new level
  PMMCTL0_L = PMMCOREV0 * level;
  // Wait till new level reached
  if ((PMMIFG & SVMLIFG))
    while ((PMMIFG & SVMLVLRIFG) == 0);
  // Set SVS/SVM low side to new level
  SVSMLCTL = SVSLE + SVSLRVL0 * level + SVMLE + SVSMLRRL0 * level;
  // Lock PMM registers for write access
  PMMCTL0_H = 0x00;
}

// USCI_B0 State ISR
#pragma vector = USCI_B0_VECTOR
__interrupt void USCI_B0_ISR(void)
{
  switch(__even_in_range(UCB0IV,12))
  {
  case  0: break;                           // Vector  0: No interrupts
  case  2: break;                           // Vector  2: ALIFG
  case  4: break;                           // Vector  4: NACKIFG
  case  6:                                  // Vector  6: STTIFG
     UCB0IFG &= ~UCSTTIFG;                  // Clear start condition int flag
     break;
  case  8:                                  // Vector  8: STPIFG
    //TXData++;                               // Increment TXData
    UCB0IFG &= ~UCSTPIFG;                   // Clear stop condition int flag
    break;
  case 10: break;                           // Vector 10: RXIFG  
  case 12:                                  // Vector 12: TXIFG
    UCB0TXBUF = TXData;                     // TX data
    break;
  default: break;
  }
}


Скорость 320kbps:
Адрес Нажмите для просмотра прикрепленного файла передача байта Нажмите для просмотра прикрепленного файла стоп Нажмите для просмотра прикрепленного файла

Скорость 400kbps:
Адрес Нажмите для просмотра прикрепленного файла передача байта Нажмите для просмотра прикрепленного файла стоп Нажмите для просмотра прикрепленного файла

Должен добавить, что FTDI не поддерживает растягивание клоков, но скорости 400kbps, он успешно работал с C51, PIC, AVR, ARM.
*rust*
Посмотрите на этот скрин (адрес). Поймал граничное состояние, мастер иногда получает нормальную дату, а иногда плохую. Так как FTDI не поддерживает растягивание клоков, то последний бит клока для ASK/NASK, придавлен MSP. MSP пытается снизить скорость для решения внутренних задач.
Нажмите для просмотра прикрепленного файла.
Растягивание приходиться только на половину клока, поэтому, иногда нормально, а иногда нет.
Остается вопрос: Зачем MSP потребовалось притормозить при частоте ядра и периферии в 25МГц?
rezident
Цитата(*rust* @ Oct 11 2011, 14:37) *
Остается вопрос: Зачем MSP потребовалось притормозить при частоте ядра и периферии в 25МГц?

А описание бага USCI30 в errata не в тему?
*rust*
Цитата
А описание бага USCI30 в errata не в тему?

В errata речь идет о том, когда модуль USCI работает как master receiver / slave receiver. Если прочитать за slave, то проблему можно обойти при контроле UCSCLLOW и при определенном чтении регистра приемника, учитываю проблемный бит клока. В моем случае slave transmitter. К тому же по описанию после бита R/W модуль обязан удерживать линию SCL в нуле и держать ее до тех пор, пока не загрузиться байт в регистр UCBxTXBUF, а затем давать ASK (стр 683 user guide, slau208i). Другое дело, почему MSP загружает байт так долго, при такой то частоте.
rezident
На вашей осциллограмме присутствует "ступенька", которой быть не должно. Она может свидетельствовать о том, что на шине возникает конфликт при котором помимо (взаимо)действия pull-up и open drain на шину выдается "жесткая" лог.1. Вопрос: откуда? Какой именно пин/выход/устройство создает этот конфликт "жесткой" лог1. и open drain?
*rust*
Цитата
конфликт при котором помимо (взаимо)действия pull-up и open drain на шину выдается "жесткая" лог.1. Вопрос: откуда?

FTDI не поддерживает clock stretching. После принятия адреса и бита R\W MSP обязан сделать след. действия: The USCI module is automatically configured as a transmitter and UCTR and UCTXIFG become set. The SCL line is held low until the first data to be sent is written into
the transmit buffer UCBxTXBUF. Then the address is acknowledged, the UCSTTIFG flag is cleared, and the data is transmitted.
Поэтому получается, что MSP держит ckock после бита R\W перед битом ASK, до тех пор, пока байт не загрузится в UCBxTXBUF, т.к FTDI имеет источники тока на выходах SDA и SCL, которые позволяют даже на низком сопротивлении open drain иметь такую ступеньку. На картинке ASK clock похож как бы на стул. Так вот спинка этого стула, это момент когда MSP отпустил линию SCL.
rezident
Цитата(*rust* @ Oct 12 2011, 11:10) *
Поэтому получается, что MSP держит ckock после бита R\W перед битом ASK, до тех пор, пока байт не загрузится в UCBxTXBUF,
Правильно. А как же иначе управлять асинхронным процессом? Тут нет никакого криминала, все в пределах спецификации I2C.
Цитата(*rust* @ Oct 12 2011, 11:10) *
т.к FTDI имеет источники тока на выходах SDA и SCL, которые позволяют даже на низком сопротивлении open drain иметь такую ступеньку. На картинке ASK clock похож как бы на стул. Так вот спинка этого стула, это момент когда MSP отпустил линию SCL.
Э-э-э, позвольте! Что за источники тока? Источники втекающего тока (внутренний pull-down)? wacko.gif Дык это явное нарушение спецификации I2C! В соответствии со спецификацией входной ток должен быть не выше ±10мкА, т.е входное сопротивление не менее 500кОм. И причем тут спрашивается MSP430? Выходной каскад пина MSP430 вполне способен принять входной втекающий ток 15мА, создав при этом уровень напряжения VOL не выше 0,6В. В даташите это явно указано. По спецификации I2C для Standard- и Fast-mode требования для VOL гораздо скромнее: не менее 3мА@0,4В и не менее 6мА@0,6В. По вашей картинке в момент конфликта на шине уровень примерно в полпитания. Если MSP430 в это время тянет шину к нулю, то выходит, что FTDI выдает лог.1 с током не меньше 30-40мА. То бишь проблема-то в FTDI заключена. С какого фига она выходной ток лог.1 создает в тот момент, когда его быть не должно?
Сделайте эксперимент, уменьшив pull-up резисторы на шине до 560 Ом. Что при этом будет? Увеличится ли высота "сидения стула"?
Ну и смотрите внимательно настройки FTDI, возможно вы ее неправильно конфигурируете для работы с I2C.
*rust*
Цитата
Дык это явное нарушение спецификации I2C!

А никто не говорит что FTDI работает по спецификации I2C. Я связывался с изготовителем и прояснял у них этот вопрос. Непонятно другое, что MSP делает так долго??? Тактовая 25МГц, один такт 40нС, скорость I2C - 400кГц, задержка SCL - 3мкС. Что можно делать за 75 тактов????? AVR, С51 с тактовой 8МГц справлялись c I2C(400кГц) легко, работая с той же самой FTDI.
rezident
Цитата(*rust* @ Oct 12 2011, 22:53) *
А никто не говорит что FTDI работает по спецификации I2C. Я связывался с изготовителем и прояснял у них этот вопрос.
Тогда непонятно, чего вы тут на MSP430 бочку катите? laughing.gif
Цитата(*rust* @ Oct 12 2011, 22:53) *
Что можно делать за 75 тактов?????

Вход в прерывание - 6 тактов, выход - 5 тактов. В симуляторе IAR есть счетчик циклов. Хотя с симуляцией периферии в IAR полный швах, но можно попробовать посимулировать "вручную", управляя прерываниями и их флагами. Я попробовал для вашего примера. Если источник прерывания в функции не обрабатывается, то прерывание выполняется 20 тактов (вход в прерывание, переход по таблице и выход). Если обрабатывается (например, запись в регистр UCB0TXBUF), то - 25 тактов. Три источника прерывания - вызывают прерывание три раза. 25*3=75 тактов. Похоже на правду? wink.gif
P.S. поправка. Ошибся при подсчете, не там брейкпоинт ставил. Обработка прерывания 23 и 28 тактов Причем это при выборе модели памяти Small, когда не используется расширенный набор команд. При выборе модели памяти Large получается уже 26 и 32 такта соответственно, за счет того, что для сохранения/восстановления контекста (регистра R15) используются команды PUSHM.A и POPM.A.
*rust*
rezident, спасибо за подробный ответ и Ваши хлопоты!
Еще раз внимательно прочитав мануал в части I2C, я немного переделал оригинальный пример от TI. Стал загружать байт в TXBUF по входу в прерывание по UCSTTIFG (на самом деле этот бит выставляется когда распознан свой адрес и известно направление чтение\запись) - это помогло. Скорость 400kpbs стала доступна при частоте ядра 16MHz.
В конечном счете макс. частота ядра, в конкретно этом случае, может быть только 8MHz (иначе выхожу за рамки в потреблении), но скорость передачи нормальных данных падает до 200kbps.

Как Вы думаете можно ли при такой частоте 8MHz организовать обмен на 400kbps, и что для этого нужно сделать?
rezident
Цитата(*rust* @ Oct 13 2011, 02:10) *
Как Вы думаете можно ли при такой частоте 8MHz организовать обмен на 400kbps, и что для этого нужно сделать?
Нет, не получится. Посчитайте сами. Даже если МК будет обрабатывать только прерывание USCI, то 8МГц/32такта=250кГц. А ведь кроме записи по прерыванию в UCB0TXBUF нужно еще в основной программе данные готовить/подтаскивать/относить к этому конвейеру. Так, что при 8МГц выше 100кГц я бы не рассчитывал.
*rust*
Убрал FTDI. В качестве мастера выступил PIC, работающий по спецификации I2C. Скорость HS 1Mbps, менять не могу т.к девайс не мой.
см. картинку. Пульсы на втором канале - это пребывание MSP в обработчике прерывания I2C. Прерывания разрешены для пустого буфера передатчика и стоп условия. Нажмите для просмотра прикрепленного файла

Частота MSP 8Mhz
rezident
3,5мкс это как раз 28 тактов на 8МГц. Модель памяти Small используется?
*rust*
Цитата
3,5мкс это как раз 28 тактов на 8МГц. Модель памяти Small используется?

да
rezident
100кГц я имел в виду, это если требуется совсем без задержек передавать. На 400 кГц тоже будет, но только если мастер полностью в соответствии со спецификацией I2C работает и позволяет тормозить обмен на время подготовки данных слейвом (MSP430) за счет "растягивания" SCL.
*rust*
Цитата
100кГц я имел в виду

Я так и понял. Спасибо за содействие! Теперь все более менее уложилось.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.