Задать вопрос
@Kopranych

TWI конечный автомат на прерываниях как избавится от зацикливания?

Здравствуйте уважаемые форумчане! Написал программу для мк мега16 обмена данными с модулем по шине TWI, сделал все на прерываниях. Но к сожалению когда " каруселька" автомата начинает крутится на одном из значений происходит crash, а именно сохраненные данные с модуля в массиве перезаписываются неизвестными, а индекс следующего шага автомата перезаписывается первым шагом и все начинается с начала и так по кругу бесконечное прерывание... Я не знаю где скрылась ошибка, в коде все кажется логично и правильно тем более в своем помогите советом компетентные люди
Show
#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;
}
  • Вопрос задан
  • 387 просмотров
Подписаться 1 Оценить Комментировать
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы