Страница 1 из 1

Программный I2C в Atmega8.

Добавлено: Пн май 13, 2013 20:37:12
kushman
Приветствую!
Решил сделать программный I2C на Atmega8, несмотря на то, что имеется аппаратный. Но вот проблема, ведомый не хочет принимать ни один байт, все прозвонил на плате, питание есть, шина подтянута к питанию через 4.7 кОм. Вот код:

Код: Выделить всё

#define SDA PORTC.4
#define SCL PORTC.5

void I2C_Start(void) {
	
	SDA=1;
	SCL=1; 
    delay();
	if(SDA==0) {er=1;};
	if(SCL==0) {er=1;};
	if(er==1) {send_lcd_symbol(set_first_line+14, 'X');};
	SDA=0; 
    delay();
	SCL=0;
}


void I2C_Send_byte(char byte) {
    
	unsigned int bits;
		for(bits=0; bits<8;bits++) {
			if((byte&0x80)==0x80) {
				SDA=1;
				delay();
				SCL=1;
				delay();
				SCL=0;
				send_lcd_symbol(set_first_line+bits, '1');
				}
				else {
				SDA=0;
				delay();
				SCL=1;
				delay();
				SCL=0;
				send_lcd_symbol(set_first_line+bits, '0');
				};
			 byte=byte<<1;
			 }
		 SDA=1;
		 delay();
		 SCL=1;
		 delay();  
         if(SDA==0) {
		 send_lcd_symbol(set_second_line+15, 'A');
		 sprintf(lcd_buffer, "TRANSFERRED!"); 
		 send_lcd(set_second_line, lcd_buffer);
		 } else {
		 send_lcd_symbol(set_first_line+15, 'E');
		 }
		 SCL=0; 
}

Re: Программный I2C в Atmega8.

Добавлено: Пн май 13, 2013 21:03:01
ChipKiller
шина подтянута к питанию через 4.7 кОм. Вот код:

Код: Выделить всё

#define SDA PORTC.4
#define SCL PORTC.5
......
... если шина подтянута, то почему PORT а не DDR?

PS.

Код: Выделить всё

if(SDA==0) {er=1;};
что надеетесь получить читая из PORT ???

Re: Программный I2C в Atmega8.

Добавлено: Пн май 13, 2013 21:34:47
kushman
ChipKiller писал(а):
шина подтянута к питанию через 4.7 кОм. Вот код:

Код: Выделить всё

#define SDA PORTC.4
#define SCL PORTC.5
......
... если шина подтянута, то почему PORT а не DDR?

PS.

Код: Выделить всё

if(SDA==0) {er=1;};
что надеетесь получить читая из PORT ???
Так ведь DDR отвечает только за настройку порта на ввод или на вывод, или я чего-то не понимаю? Только начал осваивать АВР, а этот код писал для ADUCа.

А там где er=1, я надеюсь узнать не занята ли шина, это можно сказать рудимент)

Re: Программный I2C в Atmega8.

Добавлено: Пн май 13, 2013 21:39:48
ChipKiller
Так ведь DDR отвечает только за настройку порта на ввод или на вывод, или я чего-то не понимаю?
... похоже "чего-то не понимаю". Повторяться лень - почитайте http://radiokot.ru/forum/viewtopic.php?f=20&t=89532 .... справедливо и для I2C

Re: Программный I2C в Atmega8.

Добавлено: Пн май 13, 2013 21:46:52
shads
Я себе такой I2C замутил.....

Код: Выделить всё

//#######################################################################################################################
//#
//# ФУНКЦИИ ОБСЛУЖИВАНИЯ ИНТЕРФЕЙСА I2C (софтовый вариант)
//#
//#######################################################################################################################

    //настройка порта IIC
    #define IICDDR                DDRC                /*порт управления I2C*/
    #define IICPORT                PORTC                /*порт вывода данных на линию I2C*/
    #define IICPIN                PINC                /*порт ввода данных с линий I2C*/
    #define IICData                (1<<4)                /*линия DATA*/
    #define IICClc                (1<<5)                /*линия CLC*/

//ФУНКЦИЯ ФОРМИРОВАНИЯ СОСТОЯНИЯ START ПО ИНТЕРФЕЙСУ IIC
void IICStart (void)
{
    IICDDR &= ~(IICData | IICClc);
    _delay_us (2);
    IICDDR |= IICData;                            //подтяжка data к нулю
    _delay_us (2);
    IICDDR |= IICClc;                            //подтяжка clc к нулю
    _delay_us (2);
}


//ФУНКЦИЯ ФОРМИРОВАНИЯ СОСТОЯНИЯ STOP ПО ИНТЕРФЕЙСУ IIC
void IICStop (void)
{
    IICDDR |= (IICData | IICClc);
    _delay_us (2);
    IICDDR &= ~IICClc;                            //подтяжка data к нулю
    _delay_us (2);
    IICDDR &= ~IICData;                            //подтяжка clc к нулю
    _delay_us (2);
}

//ФУНКЦИЯ ЗАПИСИ БАЙТА ПО ИНТЕРФЕЙСУ IIC
//АРГУМЕНТ - байт данных для вывода по IIC
//ЗНАЧЕНИЕ - флаг подтверждения 0 (есть подтверждение) или 1 (нет подтверждения) 
char IICByteWrite (char byte)
{
    for (char i = 0; i<8; i++)
        byte = IICBit (byte);
    byte = 0x80;                                
    return IICBit (byte);                        //возвращаем бит подтверждения (0-есть бит подтверждения, 1-нет)
}

//ФУНКЦИЯ ЧТЕНИЯ БАЙТА ПО ИНТЕРФЕЙСУ IIC
//АРГУМЕНТ - значение бита подтверждения (0 - есть подтверждение, 1 - нет подтверждения)
//ЗНАЧЕНИЕ - принятый байт
char IICByteRead (char bit)
{
    char byte = 0xFF;
    for (char i = 0; i<8; i++)
        byte = IICBit (byte);
    bit <<= 7;
    IICBit (bit);                                //передать значение бита подтверждения
    return byte;                                //возвращаем принятый байт
}

//ФУНКЦИЯ ЗАПИСИ\ЧТЕНИЯ БИТА ПО ИНТЕРФЕЙСУ IIC
//выводится значение старшего бита аргумента
//принятый бит возвращается в младшем бите предварительно сдвинутого влево аргумента
char IICBit (char byte)                        
{
    if (byte & 0x80)                        //выводимый бит
        IICDDR &= ~IICData;                 //вывод 1 на линию данных
    else 
        IICDDR |= IICData;                    //вывод 0 на линию данных
    _delay_us (2);
    IICDDR &= ~IICClc;                        //старт строб импульса
    while (! (IICPIN & IICClc)){}            //ожидание формирования строба
    _delay_us (2);
    char temp;    
    if (IICPIN & IICData)                    //принимаем бит
        temp = 1;
    else
        temp = 0;
    IICDDR |= IICClc;                        //завершить строб
    byte <<= 1;
    byte |= temp;
    return byte;
} 

Re: Программный I2C в Atmega8.

Добавлено: Пн май 13, 2013 21:54:13
ChipKiller
shads писал(а):Я себе такой I2C замутил.....
...поступил проще - переписал пример от Atmel для 89с2051 под AVR.

Re: Программный I2C в Atmega8.

Добавлено: Пн май 13, 2013 22:05:48
vAv
ChipKiller прав: из PORT не читают - читают из PIN.
Поэтому попробуй в начале:
#define SDA PINC.4
#define SCL PORTC.5

Re: Программный I2C в Atmega8.

Добавлено: Пн май 13, 2013 22:08:42
ChipKiller
Поэтому попробуй в начале:

Код: Выделить всё

#define SDA PINC.4
#define SCL PORTC.5
... немного не так

Код: Выделить всё

#define SDA DDRC.4
#define SCL DDRC.5
, а состояние проверяют через PIN

Re: Программный I2C в Atmega8.

Добавлено: Вт май 14, 2013 11:45:55
vAv
ну да.
b можно целиком макрос определить типа read_sda и write_sda

Re: Программный I2C в Atmega8.

Добавлено: Вт май 14, 2013 13:33:17
kushman
А, то есть если я хочу вывести на линию SDA что-либо, то надо DDRX.Y=1, после этого выводим, если же надо считать с линии SDA, то DDRX.Y=0 и считываем из регистра PINX.Y?

Re: Программный I2C в Atmega8.

Добавлено: Вт май 14, 2013 13:47:11
ibiza11
если вы хотите вывести лог.0 :
PORTx.y = 0
DDRx.y = 1

если вы хотите вывести лог.1:
PORTx.y = 0
DDRx.y = 0

если вы хотите считать лог уровень:
PORTx.y = 0
DDRx.y = 0
читаем из PINx.y

Re: Программный I2C в Atmega8.

Добавлено: Вт май 14, 2013 14:50:00
ChipKiller
kushman писал(а):А, то есть если я хочу вывести на линию SDA что-либо, то надо DDRX.Y=1
.. вывести на линию можно только "0", "1" обеспечивается pull-up - поэтому и дергают DDR. Если изпользовать PORT - можно убить вывод МК ( например PORTx=1, а в это время слейв ответил "0")

Re: Программный I2C в Atmega8.

Добавлено: Вт май 14, 2013 14:59:14
s_black
kushman писал(а):Приветствую!
Решил сделать программный I2C на Atmega8, несмотря на то, что имеется аппаратный. Но вот проблема, ведомый не хочет принимать ни один байт, все прозвонил на плате, питание есть, шина подтянута к питанию через 4.7 кОм
Вот для примера работающий код.

Re: Программный I2C в Atmega8.

Добавлено: Ср май 15, 2013 19:16:59
kushman
Всем большое спасибо за помощь, все заработало. Только условие стоп не хочет работать, но запись в память и чтение из нее работает.