2014 dxdy logo

Научный форум dxdy

Математика, Физика, Computer Science, Machine Learning, LaTeX, Механика и Техника, Химия,
Биология и Медицина, Экономика и Финансовая Математика, Гуманитарные науки




Начать новую тему Ответить на тему На страницу Пред.  1, 2
 
 Re: Странное поведение fuses в atmega8a
Сообщение25.04.2025, 22:24 
Заслуженный участник


20/08/14
12108
Россия, Москва
Missir в сообщении #1683748 писал(а):
не совсем так, данные идут непостоянно, прерывания приходят с частотой около 1 кгц. Там всего 14 байт, это 22,5*14=315мкс, т.е. 1/3 от периода. Остаётся 600мкс, в них нужно и поместиться.
Не совсем так:
Вы не посчитали 5 байтов заголовка перед данными (и где-то 5мкс на два старта);
пока один байт обрабатывается по i2c идёт следующий, если обработка менее 22мкс, то тормозов не будет и фактически обработка времени занимать не будет (кроме последних двух байтов);
за 1мс можно переслать по i2c 44 байта, а используется лишь 19, менее 40%;
в оставшееся время (1000-19*22.5=570мкс) надо успеть их обработать, или в данном случае отослать по uart, на скорости 115200 и 8N1 это 87мкс на байт, 570мкс хватает всего на 6 байтов, а у вас 8 байтов шлётся, по идее буквально на грани работает (первый и два следующих байта улетают в буфер uart без ожидания).
Поставьте в прерывании установку на входе и сброс на выходе любого свободного выходного пина и посмотрите осциллографом и частоту прерываний и сколько времени оно занимает. Я всегда так делаю если есть подозрения или интерес.
А вот если отсылку по uart вынести из прерывания, то будет время 1000/87=11.5 байтов отослать. А тем более это можно делать в 512 раз реже, т.е. раз в полсекунды, вообще море времени. Но код сложнее, да.

 Профиль  
                  
 
 Re: Странное поведение fuses в atmega8a
Сообщение26.04.2025, 01:10 


22/11/17
70
Missir в сообщении #1683741 писал(а):
start_i2c()
Меня, честно говоря, смущает наличие двойного вызова этой функции по коду.

(Оффтоп)

В каком именно виде она сделана у Вас не увидел.
Посмотрел по аналогии:
https://count-zero.ru/2017/msp430_usi_i2c/
и на гите
https://github.com/BeFra/I2C-Atmega32u4

 Профиль  
                  
 
 Re: Странное поведение fuses в atmega8a
Сообщение26.04.2025, 02:19 
Заслуженный участник


20/08/14
12108
Россия, Москва
DemISdx в сообщении #1683758 писал(а):
Меня, честно говоря, смущает наличие двойного вызова этой функции по коду.
Нет, это как раз обычное дело - повторный старт без освобождения шины (без стопа), первый с командой записи (обычно номера читаемого регистра), второй уже с командой чтения (в ней уже передать ничего нельзя, только прочитать). Формально можно и после первого дать стоп, но иногда, редко (сейчас даже не вспомню где видел), это запрещено и нужен именно повторный старт без освобождения шины (по стопу). Так что всё правильно, самая обычная процедура чтения из i2c, вот такой он примитивный протокол, не USB с его кучей служебных сообщений.

-- 26.04.2025, 02:26 --

Вспомнил, в каких-то многоканальных ЦАП-ах, обновление выходных сигналов было по стопу, а если хочется синхронно изменить не подряд каналы, то надо подавать два и более старта с командами записи разных каналов без промежуточных стопов, тогда обновление всех записанных будет по последнему стопу.

 Профиль  
                  
 
 Re: Странное поведение fuses в atmega8a
Сообщение26.04.2025, 03:58 


15/12/22
225
Уважаемый Dmitriy40, не могу разобраться в чём проблема. Решил вынести деление и отправку по uart в основной цикл, как Вы и советовали. Тогда в прерывании данные будут просто суммироваться в буфер, а в основном цикле - уже не спеша обрабатываться.

Вот обработчик:
код: [ скачать ] [ спрятать ]
Используется синтаксис C
ISR(INT0_vect)
{
   if (start_i2c())
   {  if (send_i2c(GY521<<1, 0x18))   // адрес GY-521 на запись
         if (send_i2c(0x3B, 0x28))     // адрес первой ячейки памяти accel_xout_high
           if (start_i2c())
             if (send_i2c((GY521<<1)|0x01, 0x40)) // адрес GY-521 для чтения
             {
                 for (int i=0; i<6; i++)
                 {num.byts[1]=rec_i2c(1); num.byts[0]=rec_i2c(1); sum[i]+=num.v;}
                 num.byts[1]=rec_i2c(1); num.byts[0]=rec_i2c(0); sum[6]+=num.v; st++;
                 
                 if (st==512)
                 { send_uart('A'); for (int i=0; i<7; i++) buf[i]=sum[i]; st=0; done=1; }                
             }
       TWCR=(1<<TWINT) | (1<<TWEN) | (1<<TWSTO);    // STOP i2c
   }
 }
 

А вот основной цикл:
код: [ скачать ] [ спрятать ]
Используется синтаксис C
while (1)
  {
    if (done==1)
    {  
       for (int i=0; i<7; i++)
       { x=buf[i]/512;
         if (x<0) {ch[0]='-'; x*=(-1);} else ch[0]='+';
         send_uart(' '); send_uart(' '); send_uart(' ');
         for (int j=6; j>0; j--) {ch[j]=(x%10)+48; x/=10;}
         for (int j=0; j<7; j++) send_uart(ch[j]);
         send_uart(' '); send_uart(' '); send_uart(' ');    
        }
        send_uart('\r'); done=0;
    }
  }  
 


буквы "A" приходят примерно 2 раза в секунду (как раз 1000 Гц / 512), но на этом всё. Из основного цикла данные по uart не отправляются совсем. Почему так происходит? Если вставить содержимое цикла в прерывание, то всё работает.
Я ставил cli(); после того как результат 512 усреднений копируется в буфер, а в цикле снова sei(); но бесполезно. Такое впечатление, что программа вообще не заходит в основной цикл

 Профиль  
                  
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 19 ]  На страницу Пред.  1, 2

Модераторы: Karan, Toucan, PAV, maxal, Супермодераторы



Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей


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

Найти:
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group