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

Участник

Группа: Участник
Сообщений: 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." Так вот, я запустил этот пример, и он НЕ работает так, как написано в комментарии. В чем может быть дело?
|
|
|
|
|
 |
Ответов
|
Oct 8 2010, 11:57
|

Участник

Группа: Участник
Сообщений: 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 действительно приходит (или НЕ приходит)? Ведь в последнем случае обмена как раз и не будет.
|
|
|
|
|
Oct 8 2010, 12:06
|
Гуру
     
Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882

|
Цитата(Lemist @ Oct 8 2010, 17:57)  Об этом, кстати, свидетельствует и то, что в упомянутой Вами книге есть раздел "Universal Serial Interface", и регистры этого раздела (например, USICTLx или USICNT etc), однако из программы ни один из этих регистров недоступен, хотя в самой книге есть Ассемблерные примеры управления через эти регистры. Уважаемый, если предположить, что у вас плохое зрение, то вы видимо забыли надеть очки?  Ну причем тут модуль USI (Universal Serial Interface) и соответствующий ему раздел в User's manual (Chapter 14), если в вашем кристалле модуль USCI (Universal Serial Communication Interface) и читать вам следует раздел Chapter 17. Universal Serial Communication Interface, I2C Mode?
|
|
|
|
|
Oct 8 2010, 12:23
|

Участник

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

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

Группа: Участник
Сообщений: 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
|
|
|
|
Сообщений в этой теме
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
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|