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

 
 
> Скорость выполнения кода на 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  < 1 2 3 4 5 >  
Start new topic
Ответов (30 - 44)
x736C
сообщение Jul 25 2009, 16:54
Сообщение #31


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

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



Я написал просто деление. Дальше в скобках уточнил, что процедура деления в вашем случае достаточно быстрая.
Не надо рассматривать это, как ухищрение.
Не приводите перед делением rez к типу double. У вас абсолютно целочисленное деление на (2^23 - 1).
Все в signed long.

Напишите, пожалуйста, позже в теме, насколько уменьшилось время выполнения процедуры. Интересно.
На какой частоте работает контроллер?

Цитата(Leonmezon @ Jul 25 2009, 20:24) *
И можно что то сделать с отниманием 1 (или она мало занимает кода).

Думаю, что это не тот случай, чтоб оптимизировать вычитание единицы. Оставьте так smile.gif

Сообщение отредактировал x736C - Jul 25 2009, 16:57
Go to the top of the page
 
+Quote Post
Leonmezon
сообщение Jul 25 2009, 17:01
Сообщение #32


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

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



Цитата(x736C @ Jul 25 2009, 20:48) *
Я написал просто деление. Дальше в скобках уточнил, что процедура деления в вашем случае достаточно быстрая.
Не надо рассматривать это, как ухищрение.
Не переводите перед делением rez к типу double. У вас абсолютно целочисленное деление на (2^23 - 1).
Все в signed long.

Напишите, пожалуйста, позже в теме, насколько уменьшилось время выполнения процедуры. Интересно.
На какой частоте работает контроллер?

1. По времени - попробую на работ- напишу. (Хотя тяжело точно отследить - примерно будет только).
2. В целочисленных нельзя (правда я не уверен - как на самом деле будет происходить преобразования типов: сначала результат, потом преобразование или нет): U=rez/Kd - если rez и Kd целочисленные - то результат будет 0 при rez<Kd?
3. Частота 14,... МГц - хотя сейчас думаю перевести на Xmega - с частотой 14,...х2 = 28,.. МГц (в теме Xmega писал уже)
4. В принципе и сейчас все работает (и очень хорошо),но появился датчик (с собственным шумом 300 нВ) и для работы с ним планирую сделать запас времени, чтобы сняв 200 выборок за 1 сек прогнать через простой режекторный цифровой фильтр в микроконтроллере (повысить точность измерений) - для этого и еще как бы выиграть еще время, т.е. перед отправкой буфера (2400 байт) по RS232 успеть 200-300 мс прогнать через фильтр. (Фильтр пишу не я - человек на них собаку съел - но просит запас по времени на работу фильтра)
Go to the top of the page
 
+Quote Post
x736C
сообщение Jul 25 2009, 17:28
Сообщение #33


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

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



1. Как оцениваете время выполнения функции? Симулятор не может посчитать?
2. Результат будет правильным. Типы менять туда-сюда не надо в вашем случае.
3. 28 — огромная частота smile.gif
4.1. Если вы поверите в прерывания, то сможете многое выполнять параллельно. Например, работать с данными и отсылать их одновременно, выполняя что-то третье.
4.2. 200-300 мс — огромное время smile.gif
4.3. 1 сек — cranky.gif

«..200 выборок за 1 сек прогнать через...»
«...успеть 200-300 мс прогнать через...»
Сколько в итоге?

Если не секрет, какого рода данные с датчика? Что-то периодичное? Почему такие точности?


P. S. Неужели ассемблер окончательно отмирает unsure.gif

Сообщение отредактировал x736C - Jul 25 2009, 17:29
Go to the top of the page
 
+Quote Post
Leonmezon
сообщение Jul 25 2009, 18:19
Сообщение #34


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

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



Цитата(x736C @ Jul 25 2009, 21:28) *
1. Как оцениваете время выполнения функции? Симулятор не может посчитать?
2. Результат будет правильным. Типы менять туда-сюда не надо в вашем случае.
3. 28 — огромная частота smile.gif
4.1. Если вы поверите в прерывания, то сможете многое выполнять параллельно. Например, работать с данными и отсылать их одновременно, выполняя что-то третье.
4.2. 200-300 мс — огромное время smile.gif
4.3. 1 сек — cranky.gif

«..200 выборок за 1 сек прогнать через...»
«...успеть 200-300 мс прогнать через...»
Сколько в итоге?

Если не секрет, какого рода данные с датчика? Что-то периодичное? Почему такие точности?


P. S. Неужели ассемблер окончательно отмирает unsure.gif

1. Я и на симулятор не могу дома (компилятор не компилирует код - только до 4 кБ - а у меня больше - на работе - лицензия - тогда и проверю).
2. Насчет типов - проверю.
3. 28 - это не много.
4.1. На прерывания - нельзя, ввиду того что на прерываниях сидят 3 АЦП, плюс прерывание синхронизации от GPS.
4.2. Не очень верно написал: по внешнему такту, а запускаю 3 АЦП на оцифровку данных - с частотой 200 Гц - получаю за 1 сек - 600 значений (три канала) и останавливаюсь на 10 мкс, приходит новый такт и процесс повторяться по АЦП, при этом данные принятые за предыдущею секунду передаются по RS232 (надо успеть до нового такта). Т.е. получаем трехканальную систему синхронной оцифровки которая работает с задержкой во времени на 1 сек. (Заказчика устраивает).
4.3. Датчик - сейсмодатчик, последний с динамическим диапазоном 145 дБ (но самый верх можно не мерять - но выше 9 балов по шкале Рихтера можно не мерять...)
5. На ассемблере - это тяжка написать, если только не критические функции...
Go to the top of the page
 
+Quote Post
aaarrr
сообщение Jul 25 2009, 18:23
Сообщение #35


Гуру
******

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



Цитата(x736C @ Jul 25 2009, 21:28) *
2. Результат будет правильным. Типы менять туда-сюда не надо в вашем случае.

Не будет.

Цитата(x736C @ Jul 25 2009, 21:28) *
P. S. Неужели ассемблер окончательно отмирает unsure.gif

Ну и причем тут ассемблер?

2 Leonmezon:

Во-первых, 24-х значащих бит у Вас не будет никогда, просто примите это как данность. Во-вторых сдвиг является не "ухищрением",
а нормальным методом деления и умножения на степень двойки. И освойте тип long long.

Получите что-то типа:
Код
const signed int K11=-831; // программный учет смещения в 1 канале 1 АЦП
const signed int K12=-999; // программный учет смещения в 2 канале 1 АЦП
const long KU=10770000; // коэффициент передачи сигнала в аналоговой части 1.077 умноженный на 1000000х10
const double Kd=8388608; // половина всего диапазона для +-10В - 0xFFFFFF/2
.
.
// Функция получения данных от 1-го АЦП
signed long uzmerenie1(void)
{
   long long U;
.
.
.
   U=(C+(B<<8)+(A<<16));
   U -= Kd; // Отнимаем 1  - для сдига в биполярный сигнал
   rez = (U * KU) >> 23; // Изменяем масштаб и преобразуем в микровольты и возращаем результат
   rez=rez-K; //Учитываем смещение в каждом из каналов АЦП: 1К -  К11; 2К- К12
   return (rez);

Хотя и это дикий маразм, т.к. я уверен, что и 1.077 и (10000000 / 8388608) можно упихать в один восьмибитный коэффициент,
оставшись при этом в пределах 32-х битной арифметики, безо всякого ущерба для конечного результата.
Go to the top of the page
 
+Quote Post
x736C
сообщение Jul 25 2009, 18:43
Сообщение #36


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

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



Цитата(aaarrr @ Jul 25 2009, 22:23) *
Не будет.

Ну и причем тут ассемблер?


То есть поделить signed long на signed long нельзя? Каким будет результат при отрицательном значении делимого?
Не знал этого, спасибо за замечание.

По поводу ассемблера имел в виду не то, что надо все и вся на нем писать,
а то что иногда надо понимать то, что выполняет Си-комплилятор, понимая процесс чуть глубже.
Опыт использования ассемблера в этом смысле только плюс.
Go to the top of the page
 
+Quote Post
Leonmezon
сообщение Jul 25 2009, 18:43
Сообщение #37


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

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



long long - длиное целое 8 байтовое?
( Если да, то у меня только до 4 байт).
Go to the top of the page
 
+Quote Post
aaarrr
сообщение Jul 25 2009, 18:48
Сообщение #38


Гуру
******

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



Цитата(x736C @ Jul 25 2009, 22:43) *
То есть поделить signed long на signed long нельзя? Каким будет результат при отрицательном значении делимого?
Не знал этого, спасибо за замечание.

Можно, конечно. Просто нет смысла делить, условно говоря, 12345 на 123456.

Цитата(Leonmezon @ Jul 25 2009, 22:43) *
long long - длиное целое 8 байтовое?
( Если да, то у меня только до 4 байт).

Уверены? И double тоже 32-х битный?
Go to the top of the page
 
+Quote Post
x736C
сообщение Jul 25 2009, 19:02
Сообщение #39


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

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



Вы сначала написали, что результат не будет корректным.
«Нет смысла делить» и «результат не будет правильным» — это разное.

Смысле ваших слов («12345 на 123456») не понял. Лучше бы вы сказали не условно, а по существу.
Go to the top of the page
 
+Quote Post
Leonmezon
сообщение Jul 25 2009, 19:11
Сообщение #40


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

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



Цитата(aaarrr @ Jul 25 2009, 22:48) *
Можно, конечно. Просто нет смысла делить, условно говоря, 12345 на 123456.


Уверены? И double тоже 32-х битный?

Да; long, float, double - 4 байтовые. Компилятор ICC AVR 7.22 STD. Я често не знаю, но только вроде в IAR есть long long 8 байт.

По делению как раз понятно (я еще вчера об этом говорил) 12345/123456= 0 в целочисленном вычеслении.

Сообщение отредактировал Leonmezon - Jul 25 2009, 19:13
Go to the top of the page
 
+Quote Post
x736C
сообщение Jul 25 2009, 19:24
Сообщение #41


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

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



Цитата(Leonmezon @ Jul 25 2009, 23:11) *
По делению как раз понятно (я еще вчера об этом говорил) 12345/123456= 0 в целочисленном вычеслении.

Понял, что имел в виду aaarrr.

В целочисленном исчислении нет знака?
-1234567/123456= 0 ?
Все зависит от компилятора, конечно.

Такая («12345/123456») ситуация, как привел aaarrr, когда делимое меньше делителя,
в приведенной мной последовательности вычислений не возникает никогда.

Сообщение отредактировал x736C - Jul 25 2009, 19:27
Go to the top of the page
 
+Quote Post
Leonmezon
сообщение Jul 25 2009, 19:41
Сообщение #42


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

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



Цитата(x736C @ Jul 25 2009, 23:24) *
Понял, что имел в виду aaarrr.

В целочисленном исчислении нет знака?
-1234567/123456= 0 ?
Все зависит от компилятора, конечно.

Такая («12345/123456») ситуация, как привел aaarrr, когда делимое меньше делителя,
в приведенной мной последовательности вычислений не возникает никогда.

Нет, может быть: рассуждения относяться к формуле U=((double)(rez))/Kd; - чтоб она правильно работала rez - надо перевести в double.
rez может быть от 0 до 0хFFFFFF, а Kd=0х800000
Go to the top of the page
 
+Quote Post
aaarrr
сообщение Jul 25 2009, 19:44
Сообщение #43


Гуру
******

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



Цитата(x736C @ Jul 25 2009, 23:24) *
Такая («12345/123456») ситуация, как привел aaarrr, когда делимое меньше делителя,
в приведенной мной последовательности вычислений не возникает никогда.

Дык мы же не про вашу последовательность говорили, а про это:

Цитата(x736C @ Jul 25 2009, 20:54) *
Не приводите перед делением rez к типу double. У вас абсолютно целочисленное деление на (2^23 - 1).
Все в signed long.

Ладно, не важно, если long long все равно нет.

2 Leonmezon:
Тогда оставьте в плавучке одно умножение, а еще лучше поручите все вычисления принимающей стороне.
Go to the top of the page
 
+Quote Post
x736C
сообщение Jul 25 2009, 20:02
Сообщение #44


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

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



Понятно. Запутался слегка.

Из Kd можно убрать лишнюю единичку, на точность не влияет.


Код
Kd = 0x7FFFFF
   U=U-Kd;    // Отнимаем Kd  - для сдвига в биполярный сигнал
   rez=(signed long)(U*KU);  // Изменяем масштаб и преобразуем в микровольты и возвращаем результат
   U=((signed long)(rez))/Kd;

   rez=rez-K; //Учитываем смещение в каждом из каналов АЦП: 1К -  К11; 2К- К12
   return (rez);

А так?

Сообщение отредактировал x736C - Jul 25 2009, 20:11
Go to the top of the page
 
+Quote Post
Leonmezon
сообщение Jul 25 2009, 20:21
Сообщение #45


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

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



Цитата(aaarrr @ Jul 25 2009, 23:44) *
Дык мы же не про вашу последовательность говорили, а про это:


Ладно, не важно, если long long все равно нет.

2 Leonmezon:
Тогда оставьте в плавучке одно умножение, а еще лучше поручите все вычисления принимающей стороне.

Принимающей стороне нельзя (там программа должна быть абсолютно одинаковая в 50 комплектах).
Оставлю одно операцию с double.
Возможно только в будущем (зимой) получиться перейти на целочисленную математику, я списывался с ImageCraft - они наняли програмистов под Xmega (пишут генератор кода,примеры..., какие утилиты - возможно и добавять новые типы данных, сейчас есть только double 8 байтный профессиональной версии, но он не решает задачи). (да обязательно требование от заказчика - лицензия, а на IAR перейти - не вариант, дорого).
Спасибо за подсказки.

Цитата(x736C @ Jul 26 2009, 00:02) *
Понятно. Запутался слегка.

Из Kd можно убрать лишнюю единичку, на точность не влияет.


Код
Kd = 0x7FFFFF
   U=U-Kd;    // Отнимаем Kd  - для сдвига в биполярный сигнал
   rez=(signed long)(U*KU);  // Изменяем масштаб и преобразуем в микровольты и возвращаем результат
   U=((signed long)(rez))/Kd;

   rez=rez-K; //Учитываем смещение в каждом из каналов АЦП: 1К -  К11; 2К- К12
   return (rez);

А так?

Не получиться, необходмо 6 байт в rez=(signed long)(U*KU); , а есть только 4! (При максимальном значении 10 и -10 В).
Ладно, как не крути - 1 с плавующей умножени все равно необходимо. (В любом случае лучше чем 4!).
Go to the top of the page
 
+Quote Post

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

 


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


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