Портал для радиолюбителей и разработчиков электроники · с 2003 годаРеклама на сайте
Найти компонент, схему или даташит

Даташиты, справочник отечественных приборов, схемы с разбором и живой форум

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

 
Опции темы

TWI конечный автомат на прерываниях

Непрочитано 09.07.2016, 00:18  
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  
NewWriter
Почётный гражданин KAZUS.RUN
 
Аватар для NewWriter
 
Регистрация: 07.09.2014
Адрес: В Кремле!
Сообщений: 4,481
Сказал спасибо: 396
Сказали Спасибо 2,222 раз(а) в 1,317 сообщении(ях)
NewWriter на пути к лучшему
По умолчанию Re: TWI конечный автомат на прерываниях

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

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

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

Последний раз редактировалось ForcePoint; 09.07.2016 в 11:20. Причина: Дополнение про сброс флага.
ForcePoint вне форума  
Непрочитано 09.07.2016, 12:50  
_Артём_
Гражданин KAZUS.RUN
 
Регистрация: 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  
ForcePoint
Почётный гражданин KAZUS.RUN
 
Регистрация: 20.03.2007
Адрес: "Братское кольцо враждебности", т.е. ближайшее заМКАДье.
Сообщений: 7,459
Сказал спасибо: 3,227
Сказали Спасибо 3,513 раз(а) в 2,394 сообщении(ях)
ForcePoint на пути к лучшему
По умолчанию Re: TWI конечный автомат на прерываниях

Сообщение от _Артём_ Посмотреть сообщение
sei и cli в прерывании не нужны - при входе в прерывание бит I устанавливается в 0. При выходе из прерывания устанавливается в 1 командой reti.
Да.
cli() это не смертельно. А вот sei() без сброса TWINT помимо постоянного "шлёпанья" этого прерывания вызовет и переполнение стека, т.к. текущее прерывание не будет доходить reti когда оно-же вызовется снова.
ForcePoint вне форума  
Сказали "Спасибо" ForcePoint
Kopranych (09.07.2016)
Непрочитано 09.07.2016, 16:46  
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, время: 17:55.


Powered by vBulletin® Version 3.8.4
Copyright ©2000 - 2026, Jelsoft Enterprises Ltd.