Перейти к содержанию

Акселерометр LIS302DL и atmega16a


Рекомендуемые сообщения

Всем доброго дня. Помогите пожалуйста с акселем LIS302DL. Пишу в AVR Studio. 

Нацарапал инициализацию и функции работы с I2C, регистр имени читает и возвращает 0x3b как положено. 

Пробую записывать регистры чипа, но результата не вижу. 

Задача заключается в том, чтобы по двойному клику (а в идеале, еще и по определенному перевороту акселя) выводить прерывания на ножки INT0 и\или INT1 акселя, с целью пробуждения МК. 

После запуска, МК полностью настраивается, настраивает аксель и засыпает. В настоящий момент, для упрощения отслеживания наличия изменений на ноге МК, я не завожу его в сон, а просто вывожу состояние на светодиод. 

Помогите пожалуйста с кодом. 

Мой фрагмент кода:

Инициализация I2C, настройка акселя и выключение I2C в Main() :

#define F_CPU 8000000UL
#define F_I2C 50000UL
#define TWBR_VALUE (((F_CPU)/(F_I2C)-16)/2)
#if ((TWBR_VALUE > 255) || (TWBR_VALUE == 0))
    #error "TWBR value is not correct"
#endif

#define I2C_device 0b0011101

 

I2C_Config(1);

ACEL_Config();
I2C_Config(0);

Функция инициализации I2C:

void I2C_Config(uint8_t Mode){
    if(Mode){
        TWBR = TWBR_VALUE;
        TWSR = 0;
    }else{
        TWCR = 0;
    }        
}

Функция настройки акселя:

void ACEL_Config(void){
    unsigned int i = 0;
     
    uint8_t CTRL_REG1 = 0b01000111;
    I2C_Work(0x20, CTRL_REG1, 0);
    
    uint8_t FF_WU_CFG_1 = 0b01110000;
    I2C_Work(0x30, FF_WU_CFG_1, 0);
    
    /* Настроить регистр управления прерываниями: включить Click interrupt1 */ 
    uint8_t CTRL_REG3 = 0b00111111;
    I2C_Work(0x22, CTRL_REG3, 0);
    
    /* Включить генерацию прерывания по двойному клику по оси Z */
    uint8_t CLICK_CFG = 0b01100000;
    I2C_Work(0x38, CLICK_CFG, 0);
        
    uint8_t CLICK_THSXY = 0xAA;
    I2C_Work(0x3B, CLICK_THSXY, 0);
    
    uint8_t CLICK_THSZ = 0x0A;
    I2C_Work(0x3C, CLICK_THSZ, 0);
    
    /* настройка лимита времени */ 
    uint8_t CLICK_TimeLimit = 127;
    I2C_Work(0x3D, CLICK_TimeLimit, 0);
    
    /* настройка задержки */ 
    uint8_t CLICK_Latency = 127;
    I2C_Work(0x3E, CLICK_Latency, 0);
    
    /* настройка окна выборки */
    uint8_t CLICK_Window = 255;
    I2C_Work(0x3F, CLICK_Window, 0);
    
    //uint8_t CLICK_SRC = 0b01101010;
    //I2C_Work(0x39, CLICK_SRC, 0);
    
}

Функции работы с I2C:

void I2C_Start(void){
    TWCR = (1<<TWINT)|(1<<TWSTA)|(1<<TWEN);
    while(!(TWCR & (1<<TWINT)));
}
void I2C_Stop(void){
    TWCR = (1<<TWINT)|(1<<TWSTO)|(1<<TWEN); 
}
uint8_t I2C_Work(uint8_t adr, uint8_t data, uint8_t setaddr){
    uint8_t getdata;
    I2C_Start();

    /*выдаемна шину пакет SLA-W*/
    TWDR = (I2C_device<<1)|0;
    TWCR = (1<<TWINT)|(1<<TWEN); 
    while(!(TWCR & (1<<TWINT)));
   
    /*передаем адрес регистра*/
    TWDR = adr;
    TWCR = (1<<TWINT)|(1<<TWEN); 
    while(!(TWCR & (1<<TWINT)));

    /*передаем данные или пропускаем*/
    if (!setaddr){ 
        /*это чтобы привести данные к BCD формату*/
        //data = ((data/10)<<4) + data%10; 
        TWDR = data;
        TWCR = (1<<TWINT)|(1<<TWEN); 
        while(!(TWCR & (1<<TWINT)));
    }else{
        /*выдаем на шину пакет SLA-R*/
        TWDR = (I2C_device<<1)|1;
        TWCR = (1<<TWINT)|(1<<TWEN); 
        while(!(TWCR & (1<<TWINT))); 
        
        /*считываем данные*/
        TWCR = (1<<TWINT)|(1<<TWEN);
        while(!(TWCR & (1<<TWINT)));
        getdata = TWDR;
    }

    /*формируем состояние СТОП*/ 
    I2C_Stop(); 
    return getdata;
}

uint8_t I2C_Read(void){
   uint8_t data;
 
   I2C_Start(); 
 
   /*выдаем на шину пакет SLA-R*/
   TWDR = (I2C_device<<1)|1;
   TWCR = (1<<TWINT)|(1<<TWEN); 
   while(!(TWCR & (1<<TWINT))); 
 
   /*считываем данные*/
   TWCR = (1<<TWINT)|(1<<TWEN);
   while(!(TWCR & (1<<TWINT)));
   data = TWDR;
 
   /*формируем состояние СТОП*/
   I2C_Stop(); 
 
 return data; 
}

Ссылка на комментарий
Поделиться на другие сайты

Реклама: ООО ТД Промэлектроника, ИНН: 6659197470, Тел: 8 (800) 1000-321

А в чём сложность? Тут надо вдумчиво читать даташит на акселерометр - на первой странице написано, что он может генерить прерывания.

Цитата

Programmable multiple interrupt generator

Значит, где-то дальше написано, как именно он это делает.

Изменено пользователем Огонёк
Ссылка на комментарий
Поделиться на другие сайты

20% скидка на весь каталог электронных компонентов в ТМ Электроникс!

Акция "Лето ближе - цены ниже", успей сделать выгодные покупки!

Плюс весь апрель действует скидка 10% по промокоду APREL24 + 15% кэшбэк и бесплатная доставка!

Перейти на страницу акции

Реклама: ООО ТМ ЭЛЕКТРОНИКС, ИНН: 7806548420, info@tmelectronics.ru, +7(812)4094849

Сложность в том, что по сути сошлись несколько неизвестных: четкость пайки чипа, правильность работы с I2C и правильность настройки акселя. В условиях ультракомпактности устройства, проверить работоспособность я могу либо выводя некие флаги на светодиоды, либо смотря, просыпается ли устройство и работает штатно. Собственно поэтому и прошу помощи в заведомо рабочем коде.

Ссылка на комментарий
Поделиться на другие сайты

Выбираем схему BMS для корректной работы литий-железофосфатных (LiFePO4) аккумуляторов

 Обязательным условием долгой и стабильной работы Li-FePO4-аккумуляторов, в том числе и производства EVE Energy, является применение специализированных BMS-микросхем. Литий-железофосфатные АКБ отличаются такими характеристиками, как высокая многократность циклов заряда-разряда, безопасность, возможность быстрой зарядки, устойчивость к буферному режиму работы и приемлемая стоимость. Но для этих АКБ, также как и для других, очень важен контроль процесса заряда и разряда, а специализированных микросхем для этого вида аккумуляторов не так много. Инженеры КОМПЭЛ подготовили список имеющихся микросхем и возможных решений от разных производителей. Подробнее>>

Реклама: АО КОМПЭЛ, ИНН: 7713005406, ОГРН: 1027700032161

Давай отделим мух от котлет. Если ты сумел настроить общение МК с акселерометром и тот тебе всякое светодиодиком отмигивает, значит в тайминги ты попал и с остальным не ошибся. Следующий шаг - настроить пробуждение МК от акселерометра. Для этого у акселерометра есть два вывода - 8 и 9. Как с ними работать, подробно описано в даташите с 28 страницы и дальше. Там много всего - читай, выбирай нужное.

Ссылка на комментарий
Поделиться на другие сайты

Шью устройство в ожидании что по двойному клику аксель начнет будить МК)

Учитывая что прерывания точно в МК работают корректно (проверено), выложил именно фрагменты в которых сомневаюсь.

Изменено пользователем Ostroukhovio
Ссылка на комментарий
Поделиться на другие сайты

2 часа назад, Огонёк сказал:

Если ты сумел настроить общение МК с акселерометром и тот тебе всякое светодиодиком отмигивает...

Да вот и не понятно. Читать та он читает. А вот правильно ли вообще написан код на WRITE в чип - не факт. Так как уже перекрутил кучу конфигов (в том числе и из аппликейшена даташита), аксель не выдает ничего.

Самый последний код настройки акселя, я уже без понятия что ему нужно.

uint8_t CTRL_REG1 = 0xC7;
	ACEL_Write(0x20, CTRL_REG1);
	
	uint8_t CTRL_REG2 = 0x04;
	ACEL_Write(0x21, CTRL_REG2);
	
	uint8_t CTRL_REG3 = 0x01;
	ACEL_Write(0x22, CTRL_REG3);
	
	uint8_t FF_WU_THS_1 = 0x01;
	ACEL_Write(0x32, FF_WU_THS_1);
	
	uint8_t FF_WU_DURATION_1 = 0x00;
	ACEL_Write(0x33, FF_WU_DURATION_1);
	
	//read HP_FILTER_RESET register
	ACEL_Read(0x23);
	
	uint8_t FF_WU_CFG_1 = 0x6A;
	ACEL_Write(0x30, FF_WU_CFG_1);

 

Изменено пользователем Ostroukhovio
Ссылка на комментарий
Поделиться на другие сайты

3 часа назад, Ostroukhovio сказал:

Читать та он читает  ... аксель не выдает ничего.

Ну почитайте регистр 31h. Может действительно настроен ничего не выдавать.

________________________________

3 часа назад, Ostroukhovio сказал:

А вот правильно ли вообще написан код на WRITE в чип - не факт.

В даташите явно указано, если регистр ReadOnly (в описании того же 31-го), управляющие же не помечены как WriteOnly, т.е. по идее должны читаться. Тогда можно проверить чтением, пишется ли в них то, что вы туда пишете.

Изменено пользователем Lexter
Ссылка на комментарий
Поделиться на другие сайты

Кстати забыл уточнить. Линии i2c подтянуты через 51к, так как у устройства очень низкое энергопотребление должно быть и из-за этого частота сейчас 50кГц.

Сделал очень урезанную инициализацию акселя:

	uint8_t CTRL_REG1 = 0x47;
	ACEL_Write(0x20, CTRL_REG1);

И прямую проверку на светодиодах читая регистр OUT_Z:

	if(ACEL_Read(0x2d)>127){ 
		fLED_Driver(1,3,1);
	}else{
		fLED_Driver(1,1,1);
	}

По логике, вращая плату, в какой-то момент должно происходите переключение светодиодов в одну сторону и соответственно обратно при обратном повороте. Но у меня судя по коду регистр всегда возвращает значение меньше 127.

 

Можно сделать вывод, если я не ошибаюсь, что даже запись регистра запуска CTRL_REG1 не происходит, раз аксель молчит.

Сейчас I2C реализовано вот так:

uint8_t ACEL_Write(uint8_t addr, uint8_t data){
	I2C_Start(I2C_device_w);
	I2C_Write(addr);
	I2C_Write(data);
	I2C_Stop();
}

uint8_t ACEL_Read(uint8_t addr){
	uint8_t InData;
	I2C_Start(I2C_device_w);
	I2C_Write(addr);
	I2C_Repeated_Start(I2C_device_r);
	InData = I2C_Read_Ack();
	//I2C_Read_Nack();
	I2C_Stop();
	return InData;
}

uint8_t I2C_Start(char write_address)/* I2C start function */
{
    uint8_t status;		/* Declare variable */
    TWCR=(1<<TWSTA)|(1<<TWEN)|(1<<TWINT); /* Enable TWI, generate START */
    while(!(TWCR&(1<<TWINT)));	/* Wait until TWI finish its current job */
    
    TWDR=write_address;		/* Write SLA+W in TWI data register */
    TWCR=(1<<TWEN)|(1<<TWINT);	/* Enable TWI & clear interrupt flag */
    while(!(TWCR&(1<<TWINT)));	/* Wait until TWI finish its current job */
}
uint8_t I2C_Repeated_Start(char read_address) /* I2C repeated start function */
{
    uint8_t status;		/* Declare variable */
    //TWCR=(1<<TWSTA)|(1<<TWEN)|(1<<TWINT);/* Enable TWI, generate start */
    //while(!(TWCR&(1<<TWINT)));	/* Wait until TWI finish its current job */
    			/* Return 0 for repeated start condition fail */
    TWDR=read_address;		/* Write SLA+R in TWI data register */
    TWCR=(1<<TWEN)|(1<<TWINT);	/* Enable TWI and clear interrupt flag */
    while(!(TWCR&(1<<TWINT)));	/* Wait until TWI finish its current job */
}
uint8_t I2C_Write(char data)	/* I2C write function */
{
    uint8_t status;		/* Declare variable */
    TWDR=data;			/* Copy data in TWI data register */
    TWCR=(1<<TWEN)|(1<<TWINT);	/* Enable TWI and clear interrupt flag */
    while(!(TWCR&(1<<TWINT)));	/* Wait until TWI finish its current job */
}
char I2C_Read_Ack(void)		/* I2C read ack function */
{
    TWCR=(1<<TWEN)|(1<<TWINT)|(1<<TWEA); /* Enable TWI, generation of ack */
    while(!(TWCR&(1<<TWINT)));	/* Wait until TWI finish its current job */
    return TWDR;			/* Return received data */
}
char I2C_Read_Nack(void)		/* I2C read nack function */
{
    TWCR=(1<<TWEN)|(1<<TWINT);	/* Enable TWI and clear interrupt flag */
    while(!(TWCR&(1<<TWINT)));	/* Wait until TWI finish its current job */
    return TWDR;		/* Return received data */
}
void I2C_Stop(void)			/* I2C stop function */
{
    TWCR=(1<<TWSTO)|(1<<TWINT)|(1<<TWEN);/* Enable TWI, generate stop */
    while(TWCR&(1<<TWSTO));	/* Wait until stop condition execution */
}

 

Изменено пользователем Ostroukhovio
Ссылка на комментарий
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы публикуете как гость. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.
Примечание: Ваш пост будет проверен модератором, прежде чем станет видимым.

Гость
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Ответить в этой теме...

×   Вставлено с форматированием.   Восстановить форматирование

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

Загрузка...
  • Последние посетители   0 пользователей онлайн

    • Ни одного зарегистрированного пользователя не просматривает данную страницу
×
×
  • Создать...