roboforum.ru

Технический форум по робототехнике.

не отпрвляет адрес по i2c

Раздел создан специально для людей которым интересна робототехника, но в силу разных причин они не знают с чего начать.
Задавайте ваши вопросы, какими бы простыми они не казались, постоянные посетители форума постараются ответить на них по мере своих сил.
Робот своими руками. Самодельный робот.

не отпрвляет адрес по i2c

Сообщение Raf00084 » 22 авг 2012, 04:46

Помогите не могу понять вот код:
Код: Выделить всёРазвернуть
#include <mega16a.h>
#include <delay.h>
#include <i2c.h>


#define Start TWCR=((1<<TWINT)|(1<<TWSTA)|(1<<TWEN))
#define Stop TWCR=((1<<TWINT)|(1<<TWEN)|(1<<TWSTO))
#define Send TWCR=((1<<TWINT)|(1<<TWEN))
#define Recieve TWCR=((1<<TWINT)|(1<<TWEA)|(1<<TWEN))
#define Execute (!(TWCR &(1<<TWINT)))


while (1)
      {
m1:   if(!PINA.0){i2c_data=0x01;goto m2;} //если кнопка 1 нажата,то отправляем 1
      if(!PINA.1){i2c_data=0x02;goto m2;}
      if(!PINA.2){i2c_data=0x03;goto m2;}
      goto m1;
     
           
m2:   Start;
      while(Execute);
     
      TWDR=0X1D;//отсылаем пакет-адрес и передача
      Send;
      while(Execute);
     
      TWDR=i2c_data;
      Send;
      while(Execute);
     
      Stop;
      delay_us(20);
      }
}

Так вот вопрос, почему когда я посылаю адрес (TWDR=0X1D;) у которого бит 0==1 то передача виснет после установки 9го бита (те бита подтверждения что передано).
Я уже и просто 0Х01 отправлял таже хрень, все остальные числа у которых бит0!=1 все норм посыла идет адрес + данные (нажатой кнопки) :(

Добавлено спустя 19 минут 12 секунд:
Прав ли я?
попытаюсь ответить на свой вопрос
1 идет старт
2 идет 7ми битный адрес
3 пишем 1 это чтение 0 это запись
видимо по этому контроллер предает адрес в моем лучае 0X1D и ждет приема так как 0-й бит равен 1 (чтение)
а адрес хранится в битах 1-6 так ли это???
Аватара пользователя
Raf00084
 
Сообщения: 50
Зарегистрирован: 19 янв 2009, 16:18
Откуда: Хренсбург

Re: не отпрвляет адрес по i2c

Сообщение Romikgy » 22 авг 2012, 14:15

а что пдф почитать не судьба? (" 1 это чтение 0 это запись " по ходу да)
die Wahrheit ist irgendwo da draußen
Аватара пользователя
Romikgy
 
Сообщения: 750
Зарегистрирован: 15 ноя 2009, 13:37
Откуда: Porto Franco "Odessa"

Re: не отпрвляет адрес по i2c

Сообщение Raf00084 » 28 авг 2012, 05:05

как отправлять я понял слизал код на сайте, вот теперь проблема такая;
железо:
1 аклсель ММА7455
2 проц мега 32а
3 питание 3,3 в
прога:
Код: Выделить всёРазвернуть
Chip type               : ATmega32A
Program type            : Application
AVR Core Clock frequency: 1,000000 MHz
Memory model            : Small
External RAM size       : 0
Data Stack size         : 512
*****************************************************/
#include <stdio.h>
#include <mega32a.h>
#include <delay.h>
#include <I2C_user.h>
// TWI functions
#include <twi.h>
// Declare your global variables here  7
// ОПРЕДЕЛЕНИЯ ДЛЯ ПОКЛЮЧЕНИЯ LCD C55
#define lcd_sclk  PORTD.3   // nokia lcd sclk
#define lcd_sda   PORTD.4   // nokia lcd sda
#define lcd_dc    PORTD.6   // nokia lcd d/c 
#define lcd_cs    PORTB.0   // nokia lcd cs   
#define lcd_res   PORTB.1   // nokia lcd res
// ОПРЕДЕЛЕНИЯ ДЛЯ ПОДКЮЧЕНИЯ АКСЕЛЛЕРОМЕТРА
#define AdressConst 0b00011101 //Постоянная часть адреса ведомого устройства MMA7455
#define int_axe PIND.7 //вывод готовноси преобразования MMA7455
#define blink PORTA.0 //ИНДИКАЦИЯ ГОТОВНОСТИ ПРЕОБРАЗОВАНИЯ ДАНЫХ MMA7455
//0x06;  // переменная для регистра оси X
//0x07;  // переменная для значний оси Y
//0x08;  // переменная для значний оси Z
//ПЕРЕМЕННЫЕ ДЛЯ lcd
unsigned char byteforlcd;
unsigned int lcdc55=918;   //количество столбцов в экране нокиа c55
char c;

//------------------------------------------------------------------------------
//ПЕРЕМЕННЫЕ ДЛЯ АКСЕЛЛЕРОМЕТРА

unsigned char str [11];  //буфер хранения строки выводимой на дисплей
unsigned char data_x;  // переменная для значний оси X
unsigned char data_y;  // переменная для значний оси Y
unsigned char data_z;  // переменная для значний оси Z
unsigned char data_r;   // переменная для хранения прочитаных данных


//----------------------------------------------------------------------------
flash unsigned char Font_6x8_Data[][6] =
{
 
};
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
void init_lcd(void);    // инициализация LCD
void lcd_clear(void);   // очистка экрана                       
void lcd_write_command(void);  // отправка комманды на LCD             
void lcd_write_dorc(void);     //отправка 8 бит по программной шине LCD (SPI)
void lcd_write_data(void);     // передача данных в диплей
void lcd_gotoxy(unsigned char xlcd, unsigned char ylcd); //установка курсора на Х и У LCD
void lcd_putch (unsigned char c);  // отправка одно сомвола в LCD
void lcd_putstr (char *s);    // отправка строки из буфера (str) в LCD

//--Функции для LCD----------------------------
void init_lcd(void)
{
        lcd_dc=0;               
        lcd_cs=1;               
        lcd_res=0;               
        delay_us (500);
        lcd_res=1;
        delay_us (500);
       
       
       
        byteforlcd=0x21;        //включения питания, ExtCommandSet
        lcd_write_command();
               
        byteforlcd=0x09;        //Внутренний HV поколения x3
        lcd_write_command();
       
        byteforlcd=0xC3;        //Set Vop
        lcd_write_command();
       
        byteforlcd=0x16;         //Смещение п = 2 / / 15
        lcd_write_command();
       
        byteforlcd=0x06;         //Температурный коэфф 2
        lcd_write_command();
       
        byteforlcd=0x20;         //StandartCommandSet
        lcd_write_command();
       
        byteforlcd=0x0C;         //нормальном режиме, отображение неинвертированного
        lcd_write_command();       
       
}
//////////////////////////////////////////////////////////////
void lcd_clear(void)
{
  unsigned int buf=0;
 
  lcd_gotoxy (0x00,0x00);   
       for (buf=0;buf<lcdc55;buf++) {
        byteforlcd=0;       
        lcd_write_data();
        }
}
//////////////////////////////////////////////////////////////
void erase_line(unsigned char num_x,unsigned char num_y)
{
  unsigned int buf=0;
 
  lcd_gotoxy (num_x,num_y);   
       for (buf=num_x;buf<98;buf++)
        {
        byteforlcd=0;       
        lcd_write_data();
        }
}
//////////////////////////////////////////////////////////////
void lcd_write_command(void)
{
lcd_dc=0;    // передача команды в регистр
lcd_cs=0;    // включение контроллера
lcd_write_dorc();
lcd_cs=1;    // отключение контроллера
}
//////////////////////////////////////////////////////////////
void lcd_write_data(void)
{
lcd_dc=1;   // передача данных в диплей
lcd_cs=0;    // chip enabled
lcd_write_dorc();
lcd_cs=1;    // chip disabled
}
//////////////////////////////////////////////////////////////
void lcd_write_dorc(void)            // serial write data or command subroutine
{
         for (c=8;c>0;c--) {
         lcd_sclk=0;
       
         if ((byteforlcd&0x80)==0){
         lcd_sda=0;}
         
            else {
            lcd_sda=1;}
           
         lcd_sclk=1;
         byteforlcd=byteforlcd<<1;}
}

//////////////////////////////////////////////////////////////
void lcd_gotoxy (unsigned char xlcd, unsigned char ylcd)    // Nokia LCD Position cursor
{
       
        byteforlcd=(0x40|(ylcd&0x07));        // Y axe initialisation: 0100 0yyy   
        lcd_write_command();
       
        byteforlcd=(0x80|(xlcd&0x7f));        // X axe initialisation: 1xxx xxxx
        lcd_write_command();
}
//////////////////////////////////////////////////////////////
void lcd_putch (unsigned char c)  //вызывается в 198 строке
{                                 //вывод символа в текущую поз. курсора
    unsigned char i=0;

    for (i=0; i<6; i++)           //ширина буквы 6!!! пикс
    {
    byteforlcd=(Font_6x8_Data[c][i]);
    lcd_write_data();   //
    }
                      //пропускаем пиксел между буквами!!!!!!!
    byteforlcd=0x00;
    lcd_write_data();   // если убрать, цифры будут   расположены вплотную. При увеличении 1цифры тоже сливаются при увел. 0х00 мусор
}
//////////////////////////////////////////////////////////////                   
void lcd_putstr (char *s)  //void lcd_putstr (const char *s)
{
    while (*s)          //выполнять пока *s>0
    {
        lcd_putch(*s);
        s++;
    }
}

//функции для акселерометра------------------------------------

int WriteByte(unsigned char address,unsigned char data)         /*Запись по адресу (adress) байта (data)*/
{
/*****УСТАНАВЛИВАЕМ СВЯЗЬ С ВЕДОМЫМ********/
    do
    {
     //Инициализация Регистра управления шиной в Блоке управления
     /*Перед началом передачи данных необходимо сформировать т.н. условие начала. В состоянии покоя линии SCL и SDA находятся на высоком уровне. Ведущее устройство (Контроллер AVR в нашем примере), которое хочет начать передачу данных, изменяет состояние линии SDA к низкому уровню. Это и есть условие начала передачи данных.*/
/*
а)Сброс флага прерывания TWINT (Флаг TWINT сбрасывается программно путем записи в него логической 1) для разрешения начала новой передачи данных
б)Уст. бит условия СТАРТ
в)Уст. бит разрешения работы TWI
*/
        TWCR=(1<<TWINT)|(1<<TWSTA)|(1<<TWEN);

//Ждем, пока шина даст добро (возможно, линия пока еще занята, ждем)
//TWINT бит устанавливается аппаратно, если TWI завершает текущее задание и ожидает реакции программы

        while(!(TWCR & (1<<TWINT)));

        /*Проверяем регистр статуса, а точнее биты TWS3-7,
        которые доступны только для чтения. Эти пять битов
        отражают состояние шины. TWS2-0 «отсекаем» с помощью операции «И         0xF8». Если TWS7-3 = 0x08, то СТАРТ был успешным.*/
       
        if((TWSR & 0xF8) != TW_START)
            return false;

/*К шине I2C может быть подключено множество подчиненных устройств (к примеру, много микросхем внешней памяти EEPROM). Для того, чтобы все микросхемы и контроллер знали, от кого и кому передается информация, в протоколе реализована Адресация ведомых устройств. В каждой микросхеме, предназначенной для работы с I2C, на заводе "зашит" определенный адрес. Мы этот адрес передаем по всей шине, т.е. всем ведомым. Каждый ведомый получает этот адрес и смотрит, типа мой это или чужой. Если мой, то О КРУТО, со мной хочет работать контроллер AVR. Так вот и происходит "рукопожатие" между ведущим и ведомым.*/


/*Так вот, мы хотим работать с микросхемой памяти 24LC64, поэтому по шине нам надо передать ее адрес. Она узнает свой адрес, и будет знать, что данные на запись адресуются именно ей. А остальные микросхемы, если они есть, эти данные будут просто игнорировать.*/

/*Постоянная часть адреса 24LC64 – 1010 (см. даташит на 24XX64), 3 бита - переменные (если вдруг мы захотим подключить несколько одинаковых микросхем c одинаковыми заводскими адресами, они пригодятся; в ином(нашем) случае выставляем нули), далее бит 0 - если хотим записывать в память или 1 - если читаем данные из памяти I2C EEPROM*/

        //TWDR = 0b1010‘000‘0;   

        TWDR = (AdressConst<<1) + (WRITEFLAG);

/*Говорим регистру управления, что мы хотим передать данные, содержащиеся в регистре данных TWDR*/

        TWCR=(1<<TWINT)|(1<<TWEN);

        //Ждем окончания передачи данных

        while(!(TWCR & (1<<TWINT)));

/*Если нет подтверждения от ведомого, делаем все по-новой (либо неполадки с линией, либо ведомого с таким адресом нет).

Если же подтверждение поступило, то регистр статуса установит биты в 0x18=TW_MT_SLA_ACK (в случае записи) или 0x40=TW_MR_SLA_ACK (в случае чтения).

Грубо говоря, если TW_MT_SLA_ACK, то ведомый "говорит" нам, что его адрес как раз 1010’000 и он готов для записи (чтения, если TW_MR_SLA_ACK).*/

    }while((TWSR & 0xF8) != TW_MT_SLA_ACK);

/*Здесь можем уже уверенно говорить, что ведущий и ведомый друг друга видят и понимают. Вначале скажем нашей микросхеме памяти, по какому адресу мы хотим записать байт данных*/

/*****ПЕРЕДАЕМ АДРЕС ЗАПИСИ********/

/*Записываем в регистр данных  разряд адреса */

    TWDR=(address);

    //..и передаем его

    TWCR=(1<<TWINT)|(1<<TWEN);

    //ждем окончания передачи

    while(!(TWCR & (1<<TWINT)));

/*Проверяем регистр статуса, принял ли ведомый данные. Если ведомый данные принял, то он передает "Подтверждение", устанавливая SDA в низкий уровень. Блок управления, в свою очередь, принимает подтверждение, и записывает в регистр статуса 0x28= TW_MT_DATA_ACK. В противном случае 0x30= TW_MT_DATA_NACK */

    if((TWSR & 0xF8) != TW_MT_DATA_ACK)

        return false;


/*****ЗАПИСЫВАЕМ БАЙТ ДАННЫХ********/

    //Аналогично, как и передавали адрес, передаем байт данных

    TWDR=(data);

    TWCR=(1<<TWINT)|(1<<TWEN);

    while(!(TWCR & (1<<TWINT)));

    if((TWSR & 0xF8) != TW_MT_DATA_ACK)

        return false;

    /*Устанавливаем условие завершения передачи данных (СТОП)

    (Устанавливаем бит условия СТОП)*/

    TWCR=(1<<TWINT)|(1<<TWEN)|(1<<TWSTO);

    //Ждем установки условия СТОП

    while(TWCR & (1<<TWSTO));

    return true;

}
int ReadByte(unsigned char address)                   /*чтение по дресу (adress)*/       
{

//Точно такой же кусок кода, как и в eeWriteByte...

/*****УСТАНАВЛИВАЕМ СВЯЗЬ С ВЕДОМЫМ********/

    do

    {

        TWCR=(1<<TWINT)|(1<<TWSTA)|(1<<TWEN);

        while(!(TWCR & (1<<TWINT)));

        if((TWSR & 0xF8) != TW_START)

            return false;

        TWDR =(AdressConst<<1) + (WRITEFLAG);     

        TWCR=(1<<TWINT)|(1<<TWEN);

        while(!(TWCR & (1<<TWINT)));

    }while((TWSR & 0xF8) != TW_MT_SLA_ACK);

/*****ПЕРЕДАЕМ АДРЕС ЧТЕНИЯ********/

    TWDR=(address);

    TWCR=(1<<TWINT)|(1<<TWEN);

    while(!(TWCR & (1<<TWINT)));

    if((TWSR & 0xF8) != TW_MT_DATA_ACK)

        return false;

/*****ПЕРЕХОД В РЕЖИМ ЧТЕНИЯ********/

/*Необходимо опять «связаться» с ведомым, т.к. ранее мы отсылали адресный пакет (slaveAddressConst<<4) + (slaveAddressVar<<1) + WRITEFLAG, чтобы записать адрес чтения байта данных. А теперь нужно перейти в режим чтения (мы же хотим прочитать байт данных), для этого отсылаем новый пакет (slaveAddressConst<<4) + (slaveAddressVar<<1) + READFLAG.*/

    //Повтор условия начала передачи

    TWCR=(1<<TWINT)|(1<<TWSTA)|(1<<TWEN);

//ждем выполнения текущей операции

    while(!(TWCR & (1<<TWINT)));

/*Проверяем статус. Условие повтора начала передачи (0x10=TW_REP_START) должно подтвердиться*/

    if((TWSR & 0xF8) != TW_REP_START)

        return false;

    /*Записываем адрес ведомого (7 битов) и в конце бит чтения (1)*/

    //TWDR=0b1010’000’1;   

    TWDR =(AdressConst<<1) + (READFLAG);     

//Отправляем..

    TWCR=(1<<TWINT)|(1<<TWEN);

    while(!(TWCR & (1<<TWINT)));

/*Проверяем, нашелся ли ведомый с адресом 1010’000 и готов ли он работать на чтение*/

    if((TWSR & 0xF8) != TW_MR_SLA_ACK)

        return false;

/*****СЧИТЫВАЕМ БАЙТ ДАННЫХ********/

/*Начинаем прием данных с помощью очистки флага прерывания TWINT. Читаемый байт записывается в регистр TWDR.*/

    TWCR=(1<<TWINT)|(1<<TWEN);

    //Ждем окончания приема..

    while(!(TWCR & (1<<TWINT)));

/*Проверяем статус. По протоколу, прием данных должен оканчиваться без подтверждения со стороны ведущего (TW_MR_DATA_NACK = 0x58)*/

    if((TWSR & 0xF8) != TW_MR_DATA_NACK)

        return false;

    /*Присваиваем переменной data значение, считанное в регистр данных TWDR*/

    data_r=TWDR;

    /*Устанавливаем условие завершения передачи данных (СТОП)*/

    TWCR=(1<<TWINT)|(1<<TWEN)|(1<<TWSTO);

    //Ждем установки условия СТОП

    while(TWCR & (1<<TWSTO));

    //Возвращаем считанный байт

    return data_r;

}
void init_axe (void)
{
WriteByte (0x16,0x01);}
void reset_int (void)            // сброс регистра прерывания для начала нового прерывания
{
WriteByte (0x17,0x03);
WriteByte (0x17,0x00);}


void main(void)
{
// Declare your local variables here

// Input/Output Ports initialization
// Port A initialization
// Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=Out
// State7=T State6=T State5=T State4=T State3=T State2=T State1=T State0=0
PORTA=0x00;
DDRA=0x01;

// Port B initialization
// Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=Out Func0=Out
// State7=T State6=T State5=T State4=T State3=T State2=T State1=0 State0=0
PORTB=0x00;
DDRB=0x03;

// Port C initialization
// Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In
// State7=T State6=T State5=T State4=T State3=T State2=T State1=T State0=T
PORTC=0x00;
DDRC=0x00;

// Port D initialization
// Func7=In Func6=Out Func5=In Func4=Out Func3=Out Func2=In Func1=In Func0=In
// State7=T State6=0 State5=T State4=0 State3=0 State2=T State1=T State0=T
PORTD=0x00;
DDRD=0x58;

// Timer/Counter 0 initialization
// Clock source: System Clock
// Clock value: Timer 0 Stopped
// Mode: Normal top=0xFF
// OC0 output: Disconnected
TCCR0=0x00;
TCNT0=0x00;
OCR0=0x00;

// Timer/Counter 1 initialization
// Clock source: System Clock
// Clock value: Timer1 Stopped
// Mode: Normal top=0xFFFF
// OC1A output: Discon.
// OC1B output: Discon.
// Noise Canceler: Off
// Input Capture on Falling Edge
// Timer1 Overflow Interrupt: Off
// Input Capture Interrupt: Off
// Compare A Match Interrupt: Off
// Compare B Match Interrupt: Off
TCCR1A=0x00;
TCCR1B=0x00;
TCNT1H=0x00;
TCNT1L=0x00;
ICR1H=0x00;
ICR1L=0x00;
OCR1AH=0x00;
OCR1AL=0x00;
OCR1BH=0x00;
OCR1BL=0x00;

// Timer/Counter 2 initialization
// Clock source: System Clock
// Clock value: Timer2 Stopped
// Mode: Normal top=0xFF
// OC2 output: Disconnected
ASSR=0x00;
TCCR2=0x00;
TCNT2=0x00;
OCR2=0x00;

// External Interrupt(s) initialization
// INT0: Off
// INT1: Off
// INT2: Off
MCUCR=0x00;
MCUCSR=0x00;

// Timer(s)/Counter(s) Interrupt(s) initialization
TIMSK=0x00;

// USART initialization
// USART disabled
UCSRB=0x00;

// Analog Comparator initialization
// Analog Comparator: Off
// Analog Comparator Input Capture by Timer/Counter 1: Off
ACSR=0x80;
SFIOR=0x00;

// ADC initialization
// ADC disabled
ADCSRA=0x00;

// SPI initialization
// SPI disabled
SPCR=0x00;

// TWI initialization
// Mode: TWI Master
// Bit Rate: 62 kHz
twi_master_init(62);

// Global enable interrupts
#asm("sei")

init_lcd();
lcd_clear();
init_axe();
while (1)
      {
      PORTA.0=0;
      delay_ms(500);
     
        if (int_axe)
       {
        // отрисовка значений X
       ReadByte(0x06);
       data_x=data_r;
       sprintf(str, "ОСЬ X= %u",data_x);//вывод значени переменой хранящней код
       erase_line(36,0);
       lcd_gotoxy(0,0); 
       lcd_putstr(str);
        // отрисовка значений Y
        ReadByte(0x07);
       data_y=data_r;
       sprintf(str, "ОСЬ Y= %u",data_y);//вывод значени переменой хранящней код
       erase_line(36,1);
       lcd_gotoxy(0,1); 
       lcd_putstr(str); 
        // отрисовка значений Z
         ReadByte(0x08);
       data_z=data_r;
       sprintf(str, "ОСЬ Z= %u",data_z);//вывод значени переменой хранящней код
       erase_line(36,2);
       lcd_gotoxy(0,2); 
       lcd_putstr(str);
       PORTA.0=1;
       }
       
       reset_int();
     
      }
}


ситуация следующая, после сброса контроллер работает и зависает, причем всегда по разному (в разное время) контроллер менял, отладить нечем :(, подскажите плиз кому не лень где косяк, неделю ковыряюсь.

P.S
Причем пока не зависает все работает как надо значения меняются от 0 до 255 по всем осям
Аватара пользователя
Raf00084
 
Сообщения: 50
Зарегистрирован: 19 янв 2009, 16:18
Откуда: Хренсбург

Re: не отпрвляет адрес по i2c

Сообщение SkyZi » 03 сен 2012, 01:27

В протеусе погоняй... там есть пошаговое чтобы видеть где МК находиться в коде. (.cof)
Project "Hexxx" (in progress...)
Аватара пользователя
SkyZi
 
Сообщения: 133
Зарегистрирован: 27 окт 2011, 22:32
Откуда: Ростов-на-Дону
Skype: skyzi007
прог. языки: Python, Си (МК)
ФИО: Святослав Игоревич


Вернуться в Новичкам или основы основ роботостроения.

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 12

cron