Полная версия этой страницы:
I2C в MSP430F169
Slonic
Mar 16 2006, 09:08
Господа, разбираюсь с чудом из Техаса в связке с IAR EW 3.2 Проблема с моим непониманием, как должен работать модуль I2C. С UARTом все получилось довольно просто, а здесь что-то застопорилось.
Итак, задача. Есть контроллер с резонатором 6Мгц на месте XCLK1. Конфигурируем источник тактовой частоты и затем модуль I2C:
BCSCTL1 = 0xC0; // select clock source
BCSCTL2 = 0xC8;
P3SEL |= 0x0a; // Assign I2C pins to module
U0CTL |= I2C + SYNC; // Switch USART0 to I2C mode
U0CTL &= ~I2CEN; // Recommended I2C init procedure
I2CTCTL = 0x30; // SMCLK
I2CSCLH = 0x1D; // High period of SCL
I2CSCLL = 0x1D; // Low period of SCL
I2CNDAT = 0x01; // Transmit one byte
I2CSA = 0x4F; // Slave address = 0 1001 111
I2CIE = RXRDYIE; // Enable RXRDYIFG interrupt
U0CTL |= I2CEN; // Enable I2C, 7 bit addr,
_EINT(); // Enable interrupts
По идее, на входе модуля должна быть исходная тактовая частота 6мгц. Частота SCL соответственно должна быть 6000кГц / ((29 + 1) * 2) = 100кГц. При контроле этого пина осциллографом вижу там частоту в районе 2кГц. Откуда она берется - непонятно. При этом UART1 прекрасно работает на нужной скорости.
Заранее спасибо.
rezident
Mar 16 2006, 10:16
Я с модулем I2C тесно не работал, но есть два замечания.
1. у вас модуль I2C в режиме slave (бит MST в U0CTL не установлен), откуда там вообще частота на SCL должна быть?
2. по поводу делителя I2CSCLH/I2CSCLH цитата
Цитата
I2C shift clock high. These bits define the high period of SCL when the I2C
controller is in master mode. The SCL high period is (I2CSCLH+2) x (I2CPSC
+ 1).
А где у вас I2CPSC инициализируется?
Slonic
Mar 16 2006, 11:23
rezident, спасибо за замечания.
1. Бит MST устанавливается непосредственно перед передачей, поэтому в предыдущем листинге его не было. А именно:
I2CNDAT = 0x01;
I2CDRB = 0xEE;
U0CTL |= MST;
I2CTCTL |= I2CTRX + I2CSTT + I2CSTP;
2. Не инициализировал специально, т.к. подразумевалось, что там должны быть нули. Добавил специально. строку:
I2CPSC = 0x00; // I2C prescaler
Ничего не поменялось. Период SCL по-прежнему порядка 500мкс.
Slonic
Mar 16 2006, 13:11
Вообще какие-то непонятки.
Экспериментально подобрал работающий вариант. А именно: модуль I2C тактируется от ACLK, который представляет собой 6мгц деленные на 4. Удалось-таки получить примерно 100кГц на SCL.
BCSCTL1 = XT2OFF + XTS + DIVA_2; // ACLK = SCLK / 4
I2CTCTL = I2CSSEL_1; // ACLK
I2CPSC = 0x00; // I2C prescaler
I2CSCLH = 0x06; // High period of SCL
I2CSCLL = 0x06; // Low period of SCL
Может быть, для него 6Мгц - слишком быстро... не знаю. Но самое интересное началось дальше. Когда на шине I2C ничего, кроме мастера-контроллера нет, все нормально. Выдается байт адреса, вызывается прерывание NACK и все вроде хорошо. Когда подключаю свой термодатчик и выставляю правильный SLAVE адрес, датчик отвечает, но байт данных не передается. Но это еще не самое интересное. При попытке повторить передачу без сброса контроллера (сделал передачу I2C по команде от RS232) клок снова становится длинным - 6кГц вместо 100!
Ничего подобного не встречал ни в Микрочипе ни в Атмеле, там как-то сразу все работало ((
Slonic
Mar 21 2006, 15:51
С частотой вроде разобрался.
Нужно было включить знаменитую задержку (см. FAQ) при включении, до переключения на тактирование от кварца. Раньше мне это в голову не приходило, т.к. UART работал нормально и все проблемы были связаны только с I2C. Но оказалось, что все частоты встали на свое место после введения этой задержки.
Но обмен по-прежнему так и не работает. Кто-нибудь может мне сказать, правильно ли я понимаю, что по команде
I2CTCTL |= I2CTRX + I2CSTT + I2CSTP;
должно передаваться два байта: адрес и данные? у меня передается один адрес, после чего вызывается прерывание Transmit Ready. И вот если после этого записать что-то в регистр данных I2С, тогда только происходит реальная передача байта данных. Судя по мануалу, что-то не так. Или...?
rezident
Mar 22 2006, 08:33
Вы забыли еще установить бит, который определяет работу модуля I2C в режиме слова (двухбайтовый)
I2CTCTL|=I2CWORD+I2CTRX+I2CSTT+I2CSTP;
Slonic
Mar 24 2006, 05:51
Нет, не забыл.
Этот бит (I2CWORD) отвечает за разрядность передаваемых ДАННЫХ. Т.е. когда он установлен, регистр I2CDRB рассматривается как 16-разрядный и передается два байта данных вместо одного.
В любом случае попробовал и с этим битом и без, отправляется только адрес и больше ничего. ACK приходит. И тишина...
Slonic
Apr 10 2006, 11:19
Рассказываю, как все было на самом деле.
Оказывается, записывать данные в регистр I2C нужно после того, как инициирована передача. Иначе, контроллер думает, что их там нет.
Иными словами, чтобы послать один байт, нужно сделать следующее:
I2CNDAT = 0x01;
U0CTL |= MST;
I2CTCTL |= I2CTRX + I2CSTT + I2CSTP;
I2CDRB = 0xEE;
Если последние две строки поменять местами, работать НЕ БУДЕТ! Надеюсь, кому-нибудь пригодится.
Для просмотра полной версии этой страницы, пожалуйста,
пройдите по ссылке.