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

Обсуждаем контроллеры компании Atmel.
Ответить
Нашел транзистор. Понюхал.
Сообщения: 194
Зарегистрирован: Сб ноя 07, 2009 15:27:59

Сообщение 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; 
}
Реклама
Сверлит текстолит когтями
Аватара пользователя
Сообщения: 1163
Зарегистрирован: Ср янв 05, 2011 16:25:15

Сообщение ChipKiller »

шина подтянута к питанию через 4.7 кОм. Вот код:

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

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

PS.

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

if(SDA==0) {er=1;};
что надеетесь получить читая из PORT ???
Реклама
Нашел транзистор. Понюхал.
Сообщения: 194
Зарегистрирован: Сб ноя 07, 2009 15:27:59

Сообщение 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, я надеюсь узнать не занята ли шина, это можно сказать рудимент)
Сверлит текстолит когтями
Аватара пользователя
Сообщения: 1163
Зарегистрирован: Ср янв 05, 2011 16:25:15

Сообщение ChipKiller »

Так ведь DDR отвечает только за настройку порта на ввод или на вывод, или я чего-то не понимаю?
... похоже "чего-то не понимаю". Повторяться лень - почитайте http://radiokot.ru/forum/viewtopic.php?f=20&t=89532 .... справедливо и для I2C
Реклама
Эиком - электронные компоненты и радиодетали
Опытный кот
Аватара пользователя
Сообщения: 882
Зарегистрирован: Ср фев 22, 2012 01:25:21

Сообщение 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;
} 
Реклама
Сверлит текстолит когтями
Аватара пользователя
Сообщения: 1163
Зарегистрирован: Ср янв 05, 2011 16:25:15

Сообщение ChipKiller »

shads писал(а):Я себе такой I2C замутил.....
...поступил проще - переписал пример от Atmel для 89с2051 под AVR.
Реклама
vAv
Прорезались зубы
Сообщения: 221
Зарегистрирован: Пн июн 13, 2011 20:04:59
Откуда: Новочебоксарск

Сообщение vAv »

ChipKiller прав: из PORT не читают - читают из PIN.
Поэтому попробуй в начале:
#define SDA PINC.4
#define SCL PORTC.5
Контактная информация:
Сверлит текстолит когтями
Аватара пользователя
Сообщения: 1163
Зарегистрирован: Ср янв 05, 2011 16:25:15

Сообщение ChipKiller »

Поэтому попробуй в начале:

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

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

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

#define SDA DDRC.4
#define SCL DDRC.5
, а состояние проверяют через PIN
vAv
Прорезались зубы
Сообщения: 221
Зарегистрирован: Пн июн 13, 2011 20:04:59
Откуда: Новочебоксарск

Сообщение vAv »

ну да.
b можно целиком макрос определить типа read_sda и write_sda
Контактная информация:
Нашел транзистор. Понюхал.
Сообщения: 194
Зарегистрирован: Сб ноя 07, 2009 15:27:59

Сообщение kushman »

А, то есть если я хочу вывести на линию SDA что-либо, то надо DDRX.Y=1, после этого выводим, если же надо считать с линии SDA, то DDRX.Y=0 и считываем из регистра PINX.Y?
Поставщик валерьянки для Кота
Аватара пользователя
Сообщения: 1900
Зарегистрирован: Сб фев 21, 2009 13:11:40
Откуда: Москва

Сообщение ibiza11 »

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

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

если вы хотите считать лог уровень:
PORTx.y = 0
DDRx.y = 0
читаем из PINx.y
Ставим плюсы: )
Сверлит текстолит когтями
Аватара пользователя
Сообщения: 1163
Зарегистрирован: Ср янв 05, 2011 16:25:15

Сообщение ChipKiller »

kushman писал(а):А, то есть если я хочу вывести на линию SDA что-либо, то надо DDRX.Y=1
.. вывести на линию можно только "0", "1" обеспечивается pull-up - поэтому и дергают DDR. Если изпользовать PORT - можно убить вывод МК ( например PORTx=1, а в это время слейв ответил "0")
Мучитель микросхем
Аватара пользователя
Сообщения: 411
Зарегистрирован: Вс авг 10, 2008 19:35:49
Откуда: Евпатория

Сообщение s_black »

kushman писал(а):Приветствую!
Решил сделать программный I2C на Atmega8, несмотря на то, что имеется аппаратный. Но вот проблема, ведомый не хочет принимать ни один байт, все прозвонил на плате, питание есть, шина подтянута к питанию через 4.7 кОм
Вот для примера работающий код.
Контактная информация:
Нашел транзистор. Понюхал.
Сообщения: 194
Зарегистрирован: Сб ноя 07, 2009 15:27:59

Сообщение kushman »

Всем большое спасибо за помощь, все заработало. Только условие стоп не хочет работать, но запись в память и чтение из нее работает.
Ответить

Вернуться в «AVR»