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

 
 
> Проблема с I2C в MSP430F2617, Протокол не функционирует как положено.
Lemist
сообщение Oct 6 2010, 13:02
Сообщение #1


Участник
*

Группа: Участник
Сообщений: 27
Регистрация: 28-04-10
Из: город Харьков
Пользователь №: 56 948



Пришлось по необходимости заняться МК MSP430F2617. К счастью, для чайников в среде IAR есть примеры. Все примеры удалось запустить и отработать, кроме примера по I2C, хотя он там нужен. Привожу код в примере
#include "msp430x26x.h"

unsigned char TXData;
unsigned char TXByteCtr;

void main(void)
{
WDTCTL = WDTPW + WDTHOLD; // Stop WDT
P3SEL |= 0x06; // Assign I2C pins to USCI_B0
UCB0CTL1 |= UCSWRST; // Enable SW reset
UCB0CTL0 = UCMST + UCMODE_3 + UCSYNC; // I2C Master, synchronous mode
UCB0CTL1 = UCSSEL_2 + UCSWRST; // Use SMCLK, keep SW reset
UCB0BR0 = 12; // fSCL = SMCLK/12 = ~100kHz
UCB0BR1 = 0;
UCB0I2CSA = 0x48; // Slave Address is 048h
UCB0CTL1 &= ~UCSWRST; // Clear SW reset, resume operation
IE2 |= UCB0TXIE; // Enable TX interrupt

TXData = 0x01; // Holds TX data

while (1)
{
TXByteCtr = 1; // Load TX byte counter
while (UCB0CTL1 & UCTXSTP); // Ensure stop condition got sent
UCB0CTL1 |= UCTR + UCTXSTT; // I2C TX, start condition
__bis_SR_register(CPUOFF + GIE); // Enter LPM0 w/ interrupts
// Remain in LPM0 until all data
// is TX'd
TXData++; // Increment data byte
}
}

//------------------------------------------------------------------------------
// The USCIAB0TX_ISR is structured such that it can be used to transmit any
// number of bytes by pre-loading TXByteCtr with the byte count.
//------------------------------------------------------------------------------
#pragma vector = USCIAB0TX_VECTOR
__interrupt void USCIAB0TX_ISR(void)
{
if (TXByteCtr) // Check TX byte counter
{
UCB0TXBUF = TXData; // Load TX buffer
TXByteCtr--; // Decrement TX byte counter
}
else
{
UCB0CTL1 |= UCTXSTP; // I2C stop condition
IFG2 &= ~UCB0TXIFG; // Clear USCI_B0 TX int flag
__bic_SR_register_on_exit(CPUOFF); // Exit LPM0
}
}

В комментарии указано: "Этот демо связывает два MSP430 по шине I2C. Мaster передает slave. Это код для master. Он постоянно передает 00h, 01h, ..., 0ffh и демонстрирует, как подключить I2C master transmitter для передачи одного байта using прерывание USCI_B0 TX." Так вот, я запустил этот пример, и он НЕ работает так, как написано в комментарии. В чем может быть дело?
Go to the top of the page
 
+Quote Post
 
Start new topic
Ответов
Lemist
сообщение Oct 8 2010, 11:57
Сообщение #2


Участник
*

Группа: Участник
Сообщений: 27
Регистрация: 28-04-10
Из: город Харьков
Пользователь №: 56 948



Извините, что столь неугомонен, но с обменом по протоколу I2C все-таки не все ладно. У меня возникло подозрение, что slave (а в качестве такового в обмене участвует акселерометр LIS331DLH) не отвечает, не дает подтверждение, необходимое по протоколу. Судя по примерам, вся последовательность обмена:
Start - Slave Address - R/W - ACK - Data - ACK - S Slave Address - R/W - ACK - Data - ACK - Stop
недоступна для программы - значит, существует "нижний" уровень типа микропрограммного, реализцющий собственно обмен. Об этом, кстати, свидетельствует и то, что в упомянутой Вами книге есть раздел "Universal Serial Interface", и регистры этого раздела (например, USICTLx или USICNT etc), однако из программы ни один из этих регистров недоступен, хотя в самой книге есть Ассемблерные примеры управления через эти регистры.
Как все-таки убедиться, что подтверждение со стороны приемника slave действительно приходит (или НЕ приходит)? Ведь в последнем случае обмена как раз и не будет.
Go to the top of the page
 
+Quote Post
rezident
сообщение Oct 8 2010, 12:06
Сообщение #3


Гуру
******

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



Цитата(Lemist @ Oct 8 2010, 17:57) *
Об этом, кстати, свидетельствует и то, что в упомянутой Вами книге есть раздел "Universal Serial Interface", и регистры этого раздела (например, USICTLx или USICNT etc), однако из программы ни один из этих регистров недоступен, хотя в самой книге есть Ассемблерные примеры управления через эти регистры.

Уважаемый, если предположить, что у вас плохое зрение, то вы видимо забыли надеть очки? cranky.gif Ну причем тут модуль USI (Universal Serial Interface) и соответствующий ему раздел в User's manual (Chapter 14), если в вашем кристалле модуль USCI (Universal Serial Communication Interface) и читать вам следует раздел Chapter 17. Universal Serial Communication Interface, I2C Mode? laughing.gif
Go to the top of the page
 
+Quote Post
Lemist
сообщение Oct 8 2010, 12:23
Сообщение #4


Участник
*

Группа: Участник
Сообщений: 27
Регистрация: 28-04-10
Из: город Харьков
Пользователь №: 56 948



Цитата(rezident @ Oct 8 2010, 15:06) *
Уважаемый, если предположить, что у вас плохое зрение, то вы видимо забыли надеть очки? cranky.gif Ну причем тут модуль USI (Universal Serial Interface) и соответствующий ему раздел в User's manual (Chapter 14), если в вашем кристалле модуль USCI (Universal Serial Communication Interface) и читать вам следует раздел Chapter 17. Universal Serial Communication Interface, I2C Mode? laughing.gif


Может, я и не о том говорил, но вопрос все равно остается. Как из программы отловить наличие подтверждения от приемника? Опять же никаких упоминаний (битов в регистрах) нет.
Go to the top of the page
 
+Quote Post
=DS=
сообщение Oct 9 2010, 02:07
Сообщение #5


Участник
*

Группа: Участник
Сообщений: 54
Регистрация: 25-09-07
Пользователь №: 30 836



Разработчики USART MSP430 2xx заложили в него 2 идеи, в общем-то спорные, но имеющие право на жизнь, без понимания которых вы не сможете понять все остальное:
(речь о режиме Master Transmitter/Receiver)

1 адрес Slave не является частью пакета данных, а задается отдельно. Это сильно упрощает программирование, если у Вас на шине одно устройство (частая ситуация). Вы один раз задаете адрес и можете забыть о нем, USCI сам вставляет его в начале каждого приема/передачи. Бит R/W при этом определяется битом UCTR.

2 Штатным ответом Slave является ACK, NACK - признак нештатной ситуации. По ACKу не выставляется никаких специальных флагов, просто контроллер дает знать о готовности к приему/передаче следующего байта через UCxxRXIFG/UCxxTXIFG, в случае получения NACK контроллер выставит UCNACKIFG ( вызовет прерывание), сотрет данные из передающего буфера, если они там есть, и будет ждать вашей реакции.

В общем, проще прислать код, наверное...
Вот кусок кода, только он для UCB1, надо будет подправить. Прерывания для приема,передачи не используются, NACK обрабатывается в ISR
Реализует как раз ваше:
Start - Slave Address - R/W - ACK - Data - ACK - S Slave Address - R/W - ACK - Data - ACK - Stop

Код
void I2C_SetSlave(unsigned char slave_address, unsigned char baudrate)
{
  UCB1CTL1 |= UCSWRST;                       // Clear SW reset, resume operation
   UCB1CTL1 = UCSSEL_2 + UCSWRST;    // Use SMCLK, SW reset
  UCB1BR0 = baudrate;                          // set prescaler
  UCB1BR1 = 0;
  UCB1I2CSA = slave_address;                  // Set slave address
  UC1IFG &= ~(UCB1TXIFG+UCB1RXIFG);

  UCB1CTL1 &= ~UCSWRST;                       // Clear SW reset, resume operation
  if(UCB1STAT & UCBBUSY) I2C_BusReset();
}

unsigned char  I2C_ReadByteRs(unsigned char reg)
{
  UCB1CTL1 |= (UCTR + UCTXSTT);    // Master TX, start condition

  while (!(UC1IFG & UCB1TXIFG));      // Wait for address transmit
  UC1IFG &= ~UCB1TXIFG;
  UCB1TXBUF = reg;
  while (!(UC1IFG & UCB1TXIFG));      // Wait for register tx
  UC1IFG &= ~UCB1TXIFG;
  UCB1CTL1 &= ~UCTR;                    // Set master receiver mode
  UCB1CTL1 |= UCTXSTT;                  // Set start condition, Master rx
  while (UCB1CTL1 & UCTXSTT);         // Start condition sent?
  UCB1CTL1 |= UCTXSTP;                  // Set stop immediately
  while (!(UC1IFG & UCB1RXIFG));      // Wait for receive
   UC1IFG &= ~UCB1RXIFG;

  return UCB1RXBUF;
}


#pragma vector = USCIAB1RX_VECTOR
void USCIAB1RX_ISR(void)
{
   if (UCB1STAT & UCNACKIFG){                  // if slave sends NACK
    UCB1CTL1 |= UCTXSTP;                          // set STOP condition
    UCB1STAT &= ~UCNACKIFG;
    UC1IFG &= ~(UCB1TXIFG+UCB1RXIFG);
    // Здесь сообщить об ошибке
  }
}

И еще. Частая ошибка при работе с акселерометрами - забывают их инициализировать и сразу кидаются читать регистры осей. А многие акселерометры при включении уходят в сон и при чтении большинства регистров выдают нули.

2 rezident
Согласитесть, "TFM", который надо читать, в части I2C довольно мутный, точнее, слишком много впихнуто в крайне сжатом виде, рисунки - это вообще песня, учитывая, что легенда к ним приводится один раз и за 3 страницы до первого рисунка. Кстати, давно хотел спросить у Вас: учитывая Ваш опыт работы с MSP430, не кажется ли Вам, что I2C в 2хх намного глючнее, чем в 1хх?

Сообщение отредактировал =DS= - Oct 9 2010, 02:39
Go to the top of the page
 
+Quote Post

Сообщений в этой теме
- Lemist   Проблема с I2C в MSP430F2617   Oct 6 2010, 13:02
- - rezident   Во-первых, нужно напомнить, что шина I2C обязатель...   Oct 6 2010, 13:22
|- - Lemist   Цитата(rezident @ Oct 6 2010, 16:22) Во-п...   Oct 6 2010, 14:19
|- - rezident   Цитата(Lemist @ Oct 6 2010, 19:53) Может,...   Oct 6 2010, 14:29
- - Lemist   Гм, все оказалось донельзя тривиально. Как только ...   Oct 6 2010, 16:26
|- - Lemist   Цитата(Lemist @ Oct 6 2010, 19:26) Гм, вс...   Oct 7 2010, 10:12
- - rezident   А 100кГц не устроит? Код#define PIN_SCL (1U...   Oct 7 2010, 12:08
- - Lemist   Спасибо за код, должен сказать, что ничего военног...   Oct 7 2010, 13:36
|- - rezident   Цитата(Lemist @ Oct 7 2010, 19:36) Вот та...   Oct 7 2010, 16:29
|- - Lemist   Цитата(rezident @ Oct 7 2010, 19:29) Как ...   Oct 8 2010, 08:14
- - rezident   Цитата(Lemist @ Oct 8 2010, 18:23) Как из...   Oct 8 2010, 14:28
- - rezident   Цитата(=DS= @ Oct 9 2010, 08:07) Кстати, ...   Oct 9 2010, 18:49


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

 


RSS Текстовая версия Сейчас: 20th June 2025 - 17:58
Рейтинг@Mail.ru


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