реклама на сайте
подробности

 
 
> Скорость выполнения кода на atmega640
Leonmezon
сообщение Jul 24 2009, 11:12
Сообщение #1


Частый гость
**

Группа: Участник
Сообщений: 191
Регистрация: 11-02-09
Из: Краснодар
Пользователь №: 44 686



Просьба помочь с функцией отправки байт по RS232 от atmega640 (сама функция полностью работает, но необходимо ускорить ее выполнения (на ассемблер перейти не могу - его не знаю).
// Функция передачи данных на ЭВМ по RS232 (масивы B1, B2 - создаю в ОЗУ, передаю по переменно взависимости от флагов. перед массив идут 5 0хF0 - заголовок.
Код
void RS232(void)
{
unsigned int i, j;
unsigned char data[4];
signed long *p;
p=(signed long*)data;
flag_BUF=0;
if (flag_B2==1)
{
  UDR0 = 0xF0;
  while ( !( UCSR0A & (1<<UDRE0)) ) { };
  UDR0 = 0xF0;
  while ( !( UCSR0A & (1<<UDRE0)) ) { };
  UDR0 = 0xF0;
  while ( !( UCSR0A & (1<<UDRE0)) ) { };
  UDR0 = 0xF0;
  while ( !( UCSR0A & (1<<UDRE0)) ) { };
  UDR0 = 0xF0;
  while ( !( UCSR0A & (1<<UDRE0)) ) { };
  // Преобразуем signed long B1 и в ЭВМ
     for(i=0; i<600; i++)
     {
        *p=B1[i];
         for (j=0; j<4; j++)
           {
              UDR0 = data[j];
              while ( !( UCSR0A & (1<<UDRE0)) ) { };
           }
     }
}
else
{
  UDR0 = 0xF0;
  while ( !( UCSR0A & (1<<UDRE0)) ) { };
  UDR0 = 0xF0;
  while ( !( UCSR0A & (1<<UDRE0)) ) { };
  UDR0 = 0xF0;
  while ( !( UCSR0A & (1<<UDRE0)) ) { };
  UDR0 = 0xF0;
  while ( !( UCSR0A & (1<<UDRE0)) ) { };
  UDR0 = 0xF0;
  while ( !( UCSR0A & (1<<UDRE0)) ) { };
// Преобразуем signed long B2 и в ЭВМ
    for(i=0; i<600; i++)
     {
        *p=B2[i];
         for (j=0; j<4; j++)
           {
              UDR0 = data[j];
              while ( !( UCSR0A & (1<<UDRE0)) ) { };
           }
     }      
}
}
Причина редактирования: Оформление цитаты исходника.
Go to the top of the page
 
+Quote Post
5 страниц V  « < 2 3 4 5 >  
Start new topic
Ответов (45 - 59)
x736C
сообщение Jul 25 2009, 20:45
Сообщение #46


Профессионал
*****

Группа: Участник
Сообщений: 1 273
Регистрация: 3-03-06
Пользователь №: 14 942



Понятно. Это как раз то, чего я не мог понять в диалоге между вами и aaarrr.
Ну удачи вам.
Go to the top of the page
 
+Quote Post
Leonmezon
сообщение Jul 27 2009, 10:45
Сообщение #47


Частый гость
**

Группа: Участник
Сообщений: 191
Регистрация: 11-02-09
Из: Краснодар
Пользователь №: 44 686



Цитата(x736C @ Jul 26 2009, 00:45) *
Понятно. Это как раз то, чего я не мог понять в диалоге между вами и aaarrr.
Ну удачи вам.


Время исполнения кода (в симуляторе) снизилось на 31%. (Много времени занимает деление - попробую и его убрать, на сдвиг).
Go to the top of the page
 
+Quote Post
aaarrr
сообщение Jul 27 2009, 13:07
Сообщение #48


Гуру
******

Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448



Цитата(Leonmezon @ Jul 27 2009, 14:45) *
Время исполнения кода (в симуляторе) снизилось на 31%. (Много времени занимает деление - попробую и его убрать, на сдвиг).

А зачем Вы его (деление) вообще оставили?
Go to the top of the page
 
+Quote Post
Leonmezon
сообщение Jul 27 2009, 16:18
Сообщение #49


Частый гость
**

Группа: Участник
Сообщений: 191
Регистрация: 11-02-09
Из: Краснодар
Пользователь №: 44 686



Цитата(aaarrr @ Jul 27 2009, 17:07) *
А зачем Вы его (деление) вообще оставили?

Согласен, деление увеличивает время исполнения в 2 раза:
Начальный вариант: - 2976 циклов;
Мой вариант - 2021 циклов;
Ваш вариант (без деления но в double) - 1000 циклов, впорос в константе KK сколько знаков после запятой оставлять? И второй Kd - может быть тип long - это как то влияет на размер кода (теоретически)?
Вот тестовый файл:
Код
//ICC-AVR application builder : 27.07.2009 20:16:20
// Target : M640
// Crystal: 14.7456Mhz

#include <iom640v.h>
#include <macros.h>

void main(void)
{
   unsigned long A, B, C;
   signed long rez;
   double U, KU, Kd, KK;
   A=128;
   B=25;
   C=55;

// Начальный вариант
   rez=(C+(B<<8)+(A<<16));
   KU=1.077;
   U=(((double)(rez))*20)/0xFFFFFF; // Получаем напряжение от 0 до 20 В
   // Отнимаем 10 В - для сдига в биполярный сигнал - получаем изменение напряжения от -10 до 10В
   U=U-10;
   U=U*KU;
   // Преобразуем в микровольты и возращаем результат
   rez=(signed long)(U*1000000);
    
// Мой вариант
   KU=10770000;
   Kd=8388608;  
    U=(C+(B<<8)+(A<<16));
   // Далее преобразуем с типу double и Преобразуем к напряжению
   U=U/Kd;
   U=U-1;    // Отнимаем 1  - для сдига в биполярный сигнал
   rez=(signed long)(U*KU);  // Изменяем масштаб и преобразуем в микровольты и возращаем результат
  
  
   // Предложенный вариант
  KU=10770000;
  Kd=8388608;
  KK=1.2838840484619140625; // KK=KU/Kd
   U=(C+(B<<8)+(A<<16));
   U -= Kd; // Отнимаем 0x800000  - для сдига в биполярный сигнал
   rez = (signed long)(U*KK); // Изменяем масштаб и преобразуем в микровольты и возращаем результат
  
  while(1)
{;}
  }
Go to the top of the page
 
+Quote Post
rezident
сообщение Jul 27 2009, 17:11
Сообщение #50


Гуру
******

Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882



Цитата(Leonmezon @ Jul 27 2009, 22:18) *
Вот тестовый файл:
А вы только кол-во циклов сравнивали или результат тоже? В смысле, что программа правильно (или хотя бы одинаково smile.gif ) считает всеми способами? А то могу подсказать где кроется потенциальная ошибка. Константы отличные (отличающиеся) от типа int (от диапазона переменной типа int на данной архитектуре, в данном компиляторе) следует обозначать явным образом.
типа unsigned int - 32769U
типа long int - 12345678L
типа unsigned long int - 12345678UL
типа long long int - 1234567890LL
типа unsigned long long int - 1234567890ULL
типа float - 1.234567f В противном случае вот здесь константа в формате double может подставляться и вас спасаетвыручает только то, что float и double в вашем компиляторе одинаковой размерности (32 бита).
Go to the top of the page
 
+Quote Post
Leonmezon
сообщение Jul 27 2009, 17:39
Сообщение #51


Частый гость
**

Группа: Участник
Сообщений: 191
Регистрация: 11-02-09
Из: Краснодар
Пользователь №: 44 686



Цитата(rezident @ Jul 27 2009, 21:11) *
А вы только кол-во циклов сравнивали или результат тоже? В смысле, что программа правильно (или хотя бы одинаково smile.gif ) считает всеми способами? А то могу подсказать где кроется потенциальная ошибка. Константы отличные (отличающиеся) от типа int (от диапазона переменной типа int на данной архитектуре, в данном компиляторе) следует обозначать явным образом.
типа unsigned int - 32769U
типа long int - 12345678L
типа unsigned long int - 12345678UL
типа long long int - 1234567890LL
типа unsigned long long int - 1234567890ULL
типа float - 1.234567f В противном случае вот здесь константа в формате double может подставляться и вас спасаетвыручает только то, что float и double в вашем компиляторе одинаковой размерности (32 бита).

1. Результат проверил - одинаковый, с точностью до 1 еденицы числа (т.е. если в первом случае 12345678 то во втором и третьем (одинаково) 12345678 или 12345677 - иногда меняеться на 1 еденицу конечный результат - а это +-1 мкВ - меньше чем мзр. АЦП)
2. ImageCraft не требует указания явного обозначения констант, достаточно указать тип переменной и ее значение. (Да и не понимает он таких указаний - я попробывал, препроцессор дает ошибку).
3. Да только в тестовом я так записал константы: реально они пишуться как глобальные константы перед main() - пока ошибок небыло.
Код
const double Kd=8388608;


Сообщение отредактировал Leonmezon - Jul 27 2009, 17:46
Go to the top of the page
 
+Quote Post
aaarrr
сообщение Jul 27 2009, 18:01
Сообщение #52


Гуру
******

Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448



Цитата(Leonmezon @ Jul 27 2009, 20:18) *
впорос в константе KK сколько знаков после запятой оставлять?

Вам должно быть виднее. На сколько, например, 1.077 отражает реальность? Я бы не стал писать больше пяти.

Цитата(Leonmezon @ Jul 27 2009, 20:18) *
И второй Kd - может быть тип long - это как то влияет на размер кода (теоретически)?

Логично сначала вычесть в целых числах, затем умножить с плавающей запятой.

Код
  Kd=8388608;
  KK=1.2838840484619140625; // KK=KU/Kd
  rez=(C+(B<<8)+(A<<16));
  U = rez - Kd; // Отнимаем 0x800000  - для сдига в биполярный сигнал
  rez = (signed long)(U*KK); // Изменяем масштаб и преобразуем в микровольты и возращаем результат
Go to the top of the page
 
+Quote Post
Leonmezon
сообщение Jul 27 2009, 20:12
Сообщение #53


Частый гость
**

Группа: Участник
Сообщений: 191
Регистрация: 11-02-09
Из: Краснодар
Пользователь №: 44 686



Цитата(aaarrr @ Jul 27 2009, 22:01) *
Вам должно быть виднее. На сколько, например, 1.077 отражает реальность? Я бы не стал писать больше пяти.


Логично сначала вычесть в целых числах, затем умножить с плавающей запятой.

Код
  Kd=8388608;
  KK=1.2838840484619140625; // KK=KU/Kd
  rez=(C+(B<<8)+(A<<16));
  U = rez - Kd; // Отнимаем 0x800000  - для сдвига в биполярный сигнал
  rez = (signed long)(U*KK); // Изменяем масштаб и преобразуем в микровольты и возвращаем результат

1. 1,077 отражает разброс С2-29 резисторов в входный аналоговых цепях - расчетное естественно, думаю есть смысл ограничиться 7 знаками (на время не все равно не влияет)
2. Логичнее, да и время выполнения уменьшаться на 21%.
Спасибо.

И все таки хотелось вернуться к первоначальному вопросу:
можно ли уменьшить время выполнения (естественно без учета ожидания флага от UART) кода преобразования и отправки байт по порту в функции void RS232(void) ? (Фактически можно ли как по другому long разбить на 4 байта с большей скоростью и тем же результатам (чтоб не переписывать программу на ЭВМ).

Сообщение отредактировал Leonmezon - Jul 27 2009, 20:16
Go to the top of the page
 
+Quote Post
aaarrr
сообщение Jul 27 2009, 20:15
Сообщение #54


Гуру
******

Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448



Цитата(Leonmezon @ Jul 28 2009, 00:12) *
И все таки хотелось вернуться к первоначальному вопросу:
можно ли уменьшить время выполнения (естественно без учета ожидания флага от UART) кода преобразования и отправки байт по порту в функции void RS232(void) ? (Фактически можно ли как по другому long разбить на 4 байта с большей скоростью и тем же результатам (чтоб не переписывать программу на ЭВМ).

По сравнению со временем ожидания флага все остальные расходы пренебрежимо малы. Фактически более 95% процессорного времени в этой процедуре пускается на ветер.
Go to the top of the page
 
+Quote Post
Leonmezon
сообщение Jul 27 2009, 20:19
Сообщение #55


Частый гость
**

Группа: Участник
Сообщений: 191
Регистрация: 11-02-09
Из: Краснодар
Пользователь №: 44 686



Цитата(aaarrr @ Jul 28 2009, 00:15) *
По сравнению со временем ожидания флага все остальные расходы пренебрежимо малы.

Да, но пока я жду флаг - работают другие функции (в первую очередь прием новых данных): т.е. я имею ввиду что, написать функциию так, чтобы время ее выполнения равнялось фактически время ожидание флага умноженое на количество переданных байт (близко конечно).
Go to the top of the page
 
+Quote Post
aaarrr
сообщение Jul 27 2009, 20:26
Сообщение #56


Гуру
******

Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448



Цитата(Leonmezon @ Jul 28 2009, 00:19) *
т.е. я имею ввиду что, написать функциию так, чтобы время ее выполнения равнялось фактически время ожидание флага умноженое на количество переданных байт (близко конечно).

По сравнению с тем временем, что Вы уже отыграли на сокращении вычислений, это 0.

Ну, модифицируйте цикл в передаче, полкопейки может быть выйграете:
Код
     for(i=0; i<600; i++)
     {
        long d = B1[i];

        UDR0 = (unsigned char)d;
        while (!(UCSR0A & (1<<UDRE0)));
        UDR0 = (unsigned char)(d >> 8);
        while (!(UCSR0A & (1<<UDRE0)));
        UDR0 = (unsigned char)(d >> 16);
        while (!(UCSR0A & (1<<UDRE0)));
        UDR0 = (unsigned char)(d >> 24);
        while (!(UCSR0A & (1<<UDRE0)));
     }
Go to the top of the page
 
+Quote Post
Leonmezon
сообщение Jul 27 2009, 20:54
Сообщение #57


Частый гость
**

Группа: Участник
Сообщений: 191
Регистрация: 11-02-09
Из: Краснодар
Пользователь №: 44 686



Цитата(aaarrr @ Jul 28 2009, 00:26) *
По сравнению с тем временем, что Вы уже отыграли на сокращении вычислений, это 0.

Ну, модифицируйте цикл в передаче, полкопейки может быть выйграете:

Нет, выиграша нет (сдвиг на 24 требует почти 200 циклов).
А если немного переиначить вопрос: весь проект планируеться перевести на Xmega -в нем за счет DMA возможно будет получить выигреш ? Не сильно меняя при этом логику работы программы.
Причина редактирования: Излишнее цитирование.
Go to the top of the page
 
+Quote Post
aaarrr
сообщение Jul 27 2009, 20:58
Сообщение #58


Гуру
******

Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448



Цитата(Leonmezon @ Jul 28 2009, 00:54) *
Нет, выиграша нет (сдвиг на 24 требует почти 200 циклов).

Что-то слабо верится, что компилятор настолько туп. Сдвиг на 24 - это просто взять нужный байт. Или оптимизация выключена?

Цитата(Leonmezon @ Jul 28 2009, 00:54) *
А если немного переиначить вопрос: весь проект планируеться перевести на Xmega -в нем за счет DMA возможно будет получить выигреш ? Не сильно меняя при этом логику работы программы.

Ровным счетом то же самое Вы можете получить и сейчас, если перенесете работу с UART на прерывания.
Go to the top of the page
 
+Quote Post
rezident
сообщение Jul 28 2009, 16:01
Сообщение #59


Гуру
******

Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882



Цитата(Leonmezon @ Jul 27 2009, 23:39) *
3. Да только в тестовом я так записал константы: реально они пишуться как глобальные константы перед main() - пока ошибок небыло.
Код
const double Kd=8388608;
Если вы объявляете их как инициализированные константы, то да, указывать не нужно. Т.к. тип этих констант вы уже определили. А вот если бы вы вдруг воспользовались командами препроцессора
Код
#define Kd 8388608
то грабли бы сработали в полный рост. laughing.gif
Go to the top of the page
 
+Quote Post
Leonmezon
сообщение Jul 28 2009, 16:24
Сообщение #60


Частый гость
**

Группа: Участник
Сообщений: 191
Регистрация: 11-02-09
Из: Краснодар
Пользователь №: 44 686



Цитата(rezident @ Jul 28 2009, 20:01) *
Если вы объявляете их как инициализированные константы, то да, указывать не нужно. Т.к. тип этих констант вы уже определили. А вот если бы вы вдруг воспользовались командами препроцессора
Код
#define Kd 8388608
то грабли бы сработали в полный рост. laughing.gif

Не сработали biggrin.gif , я не люблю #define - через полгода сам не поймешь что писал. (А выдел я таких писателей - переименовывают названия порта чтоб легче - а потом куча вопросов че да как).
Лучше ответить на вопросов - DMA в Xmega может реально ускорить выполнения функции отправки байт (хотя массив с данными и так в ОЗУ находиться) - т.е. делать пересылку автоматом (я запустил и все пока не закончатся).


Цитата(aaarrr @ Jul 28 2009, 00:58) *
Что-то слабо верится, что компилятор настолько туп. Сдвиг на 24 - это просто взять нужный байт. Или оптимизация выключена?


Ровным счетом то же самое Вы можете получить и сейчас, если перенесете работу с UART на прерывания.

Оптимизация выключена (не могу обновить свою версию компилятора на расширенную) - так что нечего удивительного.

Сообщение отредактировал Leonmezon - Jul 28 2009, 16:25
Go to the top of the page
 
+Quote Post

5 страниц V  « < 2 3 4 5 >
Reply to this topicStart new topic
2 чел. читают эту тему (гостей: 2, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 19th July 2025 - 04:40
Рейтинг@Mail.ru


Страница сгенерированна за 0.01513 секунд с 7
ELECTRONIX ©2004-2016