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 так ли это???

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

Romikgy » 22 авг 2012, 14:15

а что пдф почитать не судьба? (" 1 это чтение 0 это запись " по ходу да)

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 по всем осям

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

SkyZi » 03 сен 2012, 01:27

В протеусе погоняй... там есть пошаговое чтобы видеть где МК находиться в коде. (.cof)


Rambler\'s Top100 Mail.ru counter