Реклама на сайте English version  DatasheetsDatasheets

KAZUS.RU - Электронный портал. Принципиальные схемы, Datasheets, Форум по электронике

Новости электроники Новости Литература, электронные книги Литература Документация, даташиты Документация Поиск даташитов (datasheets)Поиск PDF
  От производителей
Новости поставщиков
В мире электроники

  Сборник статей
Электронные книги
FAQ по электронике

  Datasheets
Поиск SMD
Он-лайн справочник

Принципиальные схемы Схемы Каталоги программ, сайтов Каталоги Общение, форум Общение Ваш аккаунтАккаунт
  Каталог схем
Избранные схемы
FAQ по электронике
  Программы
Каталог сайтов
Производители электроники
  Форумы по электронике
Помощь проекту

AVR Раздел по микроконтроллерам компании Atmel - AVR / ATtiny / ATmega / ATMega128 / ATxmega, вопросы по программированию в AVR studio и все, относящееся к AVR...

Закрытая тема
Опции темы
Непрочитано 09.07.2016, 00:18   #1
Kopranych
Частый гость
 
Регистрация: 16.05.2016
Адрес: Москва
Сообщений: 35
Сказал спасибо: 6
Сказали Спасибо 1 раз в 1 сообщении
Kopranych на пути к лучшему
По умолчанию TWI конечный автомат на прерываниях

Здравствуйте уважаемые форумчане! Написал программу для мк мега16 обмена данными с модулем по шине TWI, сделал все на прерываниях. Но к сожалению когда " каруселька" автомата начинает крутится на одном из значений происходит crash, а именно сохраненные данные с модуля в массиве перезаписываются неизвестными, а индекс следующего шага автомата перезаписывается первым шагом и все начинается с начала и так по кругу бесконечное прерывание... Я не знаю где скрылась ошибка, в коде все кажется логично и правильно тем более в своем помогите советом компетентные люди
Нажмите, чтобы открыть спойлер
Код:
#include "LCD_HD44780.h"
#include "TWI.h"
#include "UART.h"
#include ‹util/delay.h›
#include ‹stdio.h›
#include ‹stdint.h›
#include ‹stdbool.h›

	enum measure_mode
	{
		accel_xh,
		accel_xl,
		accel_yh,
		accel_yl,
		accel_zh,
		accel_zl,
		hyro_xh,
		hyro_xl,
		hyro_yh,
		hyro_yl,
		hyro_zh,
		hyro_zl,
		temperature_h,
		temperatyre_l
	};
	int array_adress[] =
	{ ACCEL_XOUT_H, ACCEL_XOUT_L, ACCEL_YOUT_H, ACCEL_YOUT_L, ACCEL_ZOUT_H, ACCEL_ZOUT_L, 
	GYRO_XOUT_H, GYRO_XOUT_L, GYRO_YOUT_H, GYRO_YOUT_L, GYRO_ZOUT_H, GYRO_ZOUT_L,
			TEMP_OUT_H, TEMP_OUT_L };
	enum measure_mode current = accel_xh;
	char data[15];
	uint8_t Flag = 1;
	uint8_t reg_adress;

ISR(TWI_vect)
{
	cli();
	switch(get_status())
	{
		case TW_BUS_FAIL://аппаратная ошибка шины

		break;
		
		case TW_START://отправлено условие старт(1)

			

			I2C_tranciv_byte(MPU_6050_ADDRESS_W);//вот после этого шага на индексе	hyro_xl все рушится и следующий шаг записывается индекс accel_xh и так по кругу(((
			

			break;

		case ReStart://отправлен повторный старт(4)

			I2C_tranciv_byte(MPU_6050_ADDRESS_R);
			break;

		case TW_MT_AD_ACK://ведущий послал адрес ведомого с битом для записи ведомый отозвался(2)
			
			PORTD ^= 1‹‹PD7;

			reg_adress = array_adress[(int)current];
			
			I2C_tranciv_byte(reg_adress);

			break;

		case TW_MT_AD_NACK://ведущий послал адрес ведомого с битом для записи ведомый не отозвался
			
			kursor_adress(FIRST);
			LCD_write_str("ERROR SLAVE_NACK");
			break;
		
		case TW_MT_DATA_ACK://ведущий послал данные и принял подтверждение (3)

			I2C_start();

			break;

		case TW_MT_DATA_NACK://ведущий послал данные и не принял подтверждение 
			
			break;

		case TW_MR_AD_ACK://ведущий послал адрес ведомого с битом для чтения ведомый отозвался(5)

			data[(int)current] = I2C_receiver_last_byte();			
		
			break;

		case TW_MR_AD_NACK://ведущий послал адрес ведомого с битом для чтения ведомый не отозвался
			
			break;

		case TW_MR_DATA_ACK://ведущий принял данные и передал подтверждение
			
			break;

		case TW_MR_DATA_NACK://ведущий принял последний байт и передал NACK(6)
	
			I2C_stop();
			
			if(current == temperatyre_l)
			{	
				
				PORTB ^= 1‹‹PB3;
				current = accel_xh;
				Flag = 1;
			}
			else
			{ 
				current++;
				I2C_start();	
			
			}
			break;

	}
	sei();
}


int main()
{

	I2C_init();// инициализация шины TWI
	LCD_init();

	DDRD = 1‹‹PD5|1‹‹PD4|1‹‹PD7;
	DDRB = 1‹‹PB3;
	PORTD = 0‹‹PD5|0‹‹PD4|0‹‹PD7;
	sei();	
	I2C_start();

	for(;;)
	{
		while(Flag)
		{
				
				cli();
				char buffer[4];
				int16_t ACCEL_X = data[(int)accel_xh]‹‹8|(data[(int)accel_xl]&0xF0);
				int16_t ACCEL_Y = data[(int)accel_yh]‹‹8|(data[(int)accel_yl]&0xF0);
				int16_t ACCEL_Z = data[(int)accel_zh]‹‹8|(data[(int)accel_zl]&0xF0);
				int16_t GYRO_X = data[(int)hyro_xh]‹‹8|(data[(int)hyro_xl]&0xF0);
				int16_t GYRO_Y = data[(int)hyro_yh]‹‹8|(data[(int)hyro_yl]&0xF0);
				int16_t GYRO_Z = data[(int)hyro_zh]‹‹8|(data[(int)hyro_zl]&0xF0);
				int16_t TEMPERATURE = data[(int)temperature_h]‹‹8|data[(int)temperatyre_l];
				TEMPERATURE = TEMPERATURE/340+36;
				
				static _Bool is_init;

			if(!is_init)
			{
				kursor_adress(FIRST);
				LCD_write_str("A:000 000 000 t=");	
				
				kursor_adress(SEC_LINE);
				LCD_write_str("H:000 000 000 000");	
				is_init = true;		
			}


				itoa(ACCEL_X, buffer, 10);
				kursor_adress(THIRD);
				LCD_write_str(buffer);
				itoa(ACCEL_Y, buffer, 10);
				kursor_adress(SEVENTH);
				LCD_write_str(buffer);
				itoa(ACCEL_Z, buffer, 10);
				kursor_adress(ELEVENTH);
				LCD_write_str(buffer);


				itoa(GYRO_X, buffer, 10);
				kursor_adress(THIRD_S);
				LCD_write_str(buffer);
				itoa(GYRO_Y, buffer, 10);
				kursor_adress(SEVENTH_S);
				LCD_write_str(buffer);
				itoa(GYRO_Z, buffer, 10);
				kursor_adress(ELEVENTH_S);
				LCD_write_str(buffer);
				itoa(TEMPERATURE, buffer, 10);
				kursor_adress(FIFTEENTH_S);
				LCD_write_str(buffer);
				_delay_ms(40);
				Flag = 0;
				I2C_start();
				sei();
		}

	}
	return 0;
}
Реклама:
Kopranych вне форума  
Непрочитано 09.07.2016, 10:43   #2
NewWriter
Заблокирован
 
Регистрация: 07.09.2014
Адрес: В Кремле!
Сообщений: 4,486
Сказал спасибо: 396
Сказали Спасибо 2,220 раз(а) в 1,319 сообщении(ях)
NewWriter на пути к лучшему
По умолчанию Re: TWI конечный автомат на прерываниях

Ну значит, где-то было сделано не логично...
Бесконечное прерывание? Значит, не сбрасывается флаг прерывания.
NewWriter вне форума  
Непрочитано 09.07.2016, 11:17   #3
ForcePoint
Почётный гражданин KAZUS.RU
 
Регистрация: 20.03.2007
Адрес: "Братское кольцо враждебности", т.е. ближайшее заМКАДье.
Сообщений: 6,904
Сказал спасибо: 2,969
Сказали Спасибо 3,156 раз(а) в 2,142 сообщении(ях)
ForcePoint на пути к лучшему
По умолчанию Re: TWI конечный автомат на прерываниях

Да и исходников мало. Нет функций I2C_***, верно-ли определены константы (TW_BUS_FAIL и т.д.) для разбора состояний TWSR.

Сообщение от NewWriter Посмотреть сообщение
Бесконечное прерывание? Значит, не сбрасывается флаг прерывания.
Кстати - да. TWINT нужно сбрасывать программно перед "sei()", сам он не сбрасывается.

Последний раз редактировалось ForcePoint; 09.07.2016 в 11:20. Причина: Дополнение про сброс флага.
ForcePoint вне форума  
Непрочитано 09.07.2016, 12:50   #4
_Артём_
Гражданин KAZUS.RU
 
Регистрация: 16.03.2011
Сообщений: 486
Сказал спасибо: 8
Сказали Спасибо 131 раз(а) в 116 сообщении(ях)
_Артём_ на пути к лучшему
По умолчанию Re: TWI конечный автомат на прерываниях

Сообщение от ForcePoint Посмотреть сообщение
нужно сбрасывать программно перед "sei()", сам он не сбрасывается.
sei и cli в прерывании не нужны - при входе в прерывание бит I устанавливается в 0. При выходе из прерывания устанавливается в 1 командой reti.
_Артём_ вне форума  
Сказали "Спасибо" _Артём_
Kopranych (09.07.2016)
Непрочитано 09.07.2016, 13:13   #5
ForcePoint
Почётный гражданин KAZUS.RU
 
Регистрация: 20.03.2007
Адрес: "Братское кольцо враждебности", т.е. ближайшее заМКАДье.
Сообщений: 6,904
Сказал спасибо: 2,969
Сказали Спасибо 3,156 раз(а) в 2,142 сообщении(ях)
ForcePoint на пути к лучшему
По умолчанию Re: TWI конечный автомат на прерываниях

Сообщение от _Артём_ Посмотреть сообщение
sei и cli в прерывании не нужны - при входе в прерывание бит I устанавливается в 0. При выходе из прерывания устанавливается в 1 командой reti.
Да.
cli() это не смертельно. А вот sei() без сброса TWINT помимо постоянного "шлёпанья" этого прерывания вызовет и переполнение стека, т.к. текущее прерывание не будет доходить reti когда оно-же вызовется снова.
ForcePoint вне форума  
Сказали "Спасибо" ForcePoint
Kopranych (09.07.2016)
Непрочитано 09.07.2016, 16:46   #6
Kopranych
Частый гость
 
Регистрация: 16.05.2016
Адрес: Москва
Сообщений: 35
Сказал спасибо: 6
Сказали Спасибо 1 раз в 1 сообщении
Kopranych на пути к лучшему
По умолчанию Re: TWI конечный автомат на прерываниях

Всем спасибо убрал cli и sei в прерываниях, сделал сброс флага TWINT перед sei и все заработало!)))
Kopranych вне форума  
Закрытая тема

Закладки


Ваши права в разделе
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.

Быстрый переход

Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
AVR (ATmega16) - TWI (аппаратный) - DS1302 igor-k Микроконтроллеры, АЦП, память и т.д 9 06.07.2010 15:26
TWI as master и USI as slave duritskiy Микроконтроллеры, АЦП, память и т.д 20 06.09.2007 19:18


Часовой пояс GMT +4, время: 15:06.


Powered by vBulletin® Version 3.8.4
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd. Перевод: zCarot