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

 
 
> Tактирование I2C
pashevich
сообщение May 26 2006, 10:32
Сообщение #1





Группа: Новичок
Сообщений: 6
Регистрация: 26-05-06
Пользователь №: 17 471



Не могу подключить индикатор через I2C. Скорее всего, проблемы с тактированием CLK. Для шины нужно 100 или 400 кГц. МК по умолчанию должен работать от SMCLK на 1 МГц. Но реально осциллограф показывает 715 кГц, а CLK на шине без использования прескалера 12.5 кГц.
Почему так получается, ведь I2C тоже тактируется от SMCLK?
Читал где-то, что необходима задержка для установления частоты тактирования.. может из-за ее отсутствия?
Go to the top of the page
 
+Quote Post
 
Start new topic
Ответов
pashevich
сообщение May 27 2006, 12:34
Сообщение #2





Группа: Новичок
Сообщений: 6
Регистрация: 26-05-06
Пользователь №: 17 471



Подобрал частоту:

BCSCTL1 |= XT2OFF + RSEL2 + RSEL1 ;
DCOCTL |= DCO0 + DCO1; // частота тактирования ... МГц
BCSCTL2 = 0x00;
P5SEL = 0x20; //SMCLK на вывод P5.0 - наблюдаем ~1 MГц

Инициализация I2C:

U0CTL |= I2C + SYNC; // режим I2C
U0CTL &= ~I2CEN; // начало инициализации порта
I2CSA = 0x78; // адрес LCD
U0CTL |= MST; // режим ведущего
I2CTCTL = I2CSSEL_2; // тактирование I2C от SMCLK
I2CPSC = 0x01; // по теории деление MSCLK на 2 - получается около 100 кГц
I2CTCTL |= I2CTRX + I2CRM; // ПО устанавливает "старт" и "стоп"
U0CTL |= I2CEN; // разрешение работы порта в режиме I2C

Далее посылаем старт-адрес ведомого-стоп и не получаем ASK (выставляется флаг NASK)...
т.е. всё-равно ведущий молчит, может он вообще не рабочий? smile.gif
Go to the top of the page
 
+Quote Post
Slonic
сообщение May 30 2006, 11:22
Сообщение #3


Частый гость
**

Группа: Участник
Сообщений: 84
Регистрация: 3-10-05
Из: Москва-Троицк
Пользователь №: 9 174



Говоря о задержке тактирования, я имел в виду, конечно, работу от внешнего кварца. При работе от DCO никаких задержек не нужно, он начинает работать сразу.

Что касается отправки данных по I2C. Наличие ACK желательно контролировать осциллографом непосредственно на шине. Записывать данные в регистр I2CDRB нужно после того, как инициирована передача, для меня это оказалось нетривиальным моментом.

Привожу код, который в итоге заработал:

signed char i2c_n, i2c_tx_n;
unsigned char i2c_buf[10];

void init_i2c(void)
{
P3SEL |= 0x0a; // Assign I2C pins to module
U0CTL |= I2C + SYNC; // Switch USART0 to I2C mode
U0CTL &= ~I2CEN; // Recommended I2C init procedure
I2CTCTL = I2CSSEL_1; // ACLK
I2CPSC = 0x00; // I2C prescaler
I2CSCLH = 0x07; // High period of SCL
I2CSCLL = 0x07; // Low period of SCL // 6000 / 16 = 375khz
I2CIE = RXRDYIE + NACKIE;
U0CTL |= I2CEN; // Enable I2C, 7 bit addr,
_EINT(); // Enable interrupts
}

void i2c_sendbyte(unsigned char SlaveAddress, unsigned char Value, unsigned char Stop)
{
I2CSA = THERM0_SA;
I2CNDAT = 0x01;
i2c_tx_n = 0;
U0CTL |= MST;

i2c_buf[0] = Value;

I2CIFG &= ~TXRDYIFG;
I2CIFG &= ~ARDYIFG;
I2CIE = TXRDYIE;
if(Stop)
I2CTCTL |= I2CTRX + I2CSTT + I2CSTP;
else
I2CTCTL |= I2CTRX + I2CSTT;
while ((~I2CIFG) & ARDYIFG);
}

#pragma vector=USART0TX_VECTOR
__interrupt void I2C_ISR(void)
{
switch(I2CIV)
{
case 0: break; // No interrupt
case 2: break; // Arbitration lost
case 4: // No Acknowledge
uart1_putchar('X');
break;
case 6: break; // Own Address
case 8: break; // Register Access Ready
case 10: // Receive Ready
if(i2c_n < 10)
i2c_buf[i2c_n] = I2CDRB;
i2c_n++;
break;
case 12:
I2CDRB = i2c_buf[i2c_tx_n];
i2c_tx_n = i2c_tx_n-1;
if(i2c_tx_n < 0)
I2CIE &= ~TXRDYIE; // disable interrupts
break; // Transmit Ready
case 14: break; // General Call
case 16: break; // Start Condition
}
}
Go to the top of the page
 
+Quote Post



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

 


RSS Текстовая версия Сейчас: 28th July 2025 - 10:19
Рейтинг@Mail.ru


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