|
Скорость выполнения кода на atmega640 |
|
|
|
Jul 24 2009, 11:12
|
Частый гость
 
Группа: Участник
Сообщений: 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)) ) { }; } } } }
Причина редактирования: Оформление цитаты исходника.
|
|
|
|
|
 |
Ответов
(45 - 59)
|
Jul 27 2009, 10:45
|
Частый гость
 
Группа: Участник
Сообщений: 191
Регистрация: 11-02-09
Из: Краснодар
Пользователь №: 44 686

|
Цитата(x736C @ Jul 26 2009, 00:45)  Понятно. Это как раз то, чего я не мог понять в диалоге между вами и aaarrr. Ну удачи вам. Время исполнения кода (в симуляторе) снизилось на 31%. (Много времени занимает деление - попробую и его убрать, на сдвиг).
|
|
|
|
|
Jul 27 2009, 16:18
|
Частый гость
 
Группа: Участник
Сообщений: 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) {;} }
|
|
|
|
|
Jul 27 2009, 17:11
|
Гуру
     
Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882

|
Цитата(Leonmezon @ Jul 27 2009, 22:18)  Вот тестовый файл: А вы только кол-во циклов сравнивали или результат тоже? В смысле, что программа правильно (или хотя бы одинаково  ) считает всеми способами? А то могу подсказать где кроется потенциальная ошибка. Константы отличные (отличающиеся) от типа int (от диапазона переменной типа int на данной архитектуре, в данном компиляторе) следует обозначать явным образом. типа unsigned int - 32769 Uтипа long int - 12345678 Lтипа unsigned long int - 12345678 ULтипа long long int - 1234567890 LLтипа unsigned long long int - 1234567890 ULLтипа float - 1.234567 f В противном случае вот здесь константа в формате double может подставляться и вас спасаетвыручает только то, что float и double в вашем компиляторе одинаковой размерности (32 бита).
|
|
|
|
|
Jul 27 2009, 17:39
|
Частый гость
 
Группа: Участник
Сообщений: 191
Регистрация: 11-02-09
Из: Краснодар
Пользователь №: 44 686

|
Цитата(rezident @ Jul 27 2009, 21:11)  А вы только кол-во циклов сравнивали или результат тоже? В смысле, что программа правильно (или хотя бы одинаково  ) считает всеми способами? А то могу подсказать где кроется потенциальная ошибка. Константы отличные (отличающиеся) от типа int (от диапазона переменной типа int на данной архитектуре, в данном компиляторе) следует обозначать явным образом. типа unsigned int - 32769 Uтипа long int - 12345678 Lтипа unsigned long int - 12345678 ULтипа long long int - 1234567890 LLтипа unsigned long long int - 1234567890 ULLтипа float - 1.234567 f В противном случае вот здесь константа в формате 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
|
|
|
|
|
Jul 27 2009, 18:01
|
Гуру
     
Группа: Свой
Сообщений: 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); // Изменяем масштаб и преобразуем в микровольты и возращаем результат
|
|
|
|
|
Jul 27 2009, 20:12
|
Частый гость
 
Группа: Участник
Сообщений: 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
|
|
|
|
|
Jul 27 2009, 20:19
|
Частый гость
 
Группа: Участник
Сообщений: 191
Регистрация: 11-02-09
Из: Краснодар
Пользователь №: 44 686

|
Цитата(aaarrr @ Jul 28 2009, 00:15)  По сравнению со временем ожидания флага все остальные расходы пренебрежимо малы. Да, но пока я жду флаг - работают другие функции (в первую очередь прием новых данных): т.е. я имею ввиду что, написать функциию так, чтобы время ее выполнения равнялось фактически время ожидание флага умноженое на количество переданных байт (близко конечно).
|
|
|
|
|
Jul 27 2009, 20:26
|
Гуру
     
Группа: Свой
Сообщений: 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))); }
|
|
|
|
|
Jul 27 2009, 20:54
|
Частый гость
 
Группа: Участник
Сообщений: 191
Регистрация: 11-02-09
Из: Краснодар
Пользователь №: 44 686

|
Цитата(aaarrr @ Jul 28 2009, 00:26)  По сравнению с тем временем, что Вы уже отыграли на сокращении вычислений, это 0.
Ну, модифицируйте цикл в передаче, полкопейки может быть выйграете: Нет, выиграша нет (сдвиг на 24 требует почти 200 циклов). А если немного переиначить вопрос: весь проект планируеться перевести на Xmega -в нем за счет DMA возможно будет получить выигреш ? Не сильно меняя при этом логику работы программы.
Причина редактирования: Излишнее цитирование.
|
|
|
|
|
Jul 27 2009, 20: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 на прерывания.
|
|
|
|
|
Jul 28 2009, 16:01
|
Гуру
     
Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882

|
Цитата(Leonmezon @ Jul 27 2009, 23:39)  3. Да только в тестовом я так записал константы: реально они пишуться как глобальные константы перед main() - пока ошибок небыло. Код const double Kd=8388608; Если вы объявляете их как инициализированные константы, то да, указывать не нужно. Т.к. тип этих констант вы уже определили. А вот если бы вы вдруг воспользовались командами препроцессора Код #define Kd 8388608 то грабли бы сработали в полный рост.
|
|
|
|
|
Jul 28 2009, 16:24
|
Частый гость
 
Группа: Участник
Сообщений: 191
Регистрация: 11-02-09
Из: Краснодар
Пользователь №: 44 686

|
Цитата(rezident @ Jul 28 2009, 20:01)  Если вы объявляете их как инициализированные константы, то да, указывать не нужно. Т.к. тип этих констант вы уже определили. А вот если бы вы вдруг воспользовались командами препроцессора Код #define Kd 8388608 то грабли бы сработали в полный рост.  Не сработали  , я не люблю #define - через полгода сам не поймешь что писал. (А выдел я таких писателей - переименовывают названия порта чтоб легче - а потом куча вопросов че да как). Лучше ответить на вопросов - DMA в Xmega может реально ускорить выполнения функции отправки байт (хотя массив с данными и так в ОЗУ находиться) - т.е. делать пересылку автоматом (я запустил и все пока не закончатся). Цитата(aaarrr @ Jul 28 2009, 00:58)  Что-то слабо верится, что компилятор настолько туп. Сдвиг на 24 - это просто взять нужный байт. Или оптимизация выключена?
Ровным счетом то же самое Вы можете получить и сейчас, если перенесете работу с UART на прерывания. Оптимизация выключена (не могу обновить свою версию компилятора на расширенную) - так что нечего удивительного.
Сообщение отредактировал Leonmezon - Jul 28 2009, 16:25
|
|
|
|
|
  |
2 чел. читают эту тему (гостей: 2, скрытых пользователей: 0)
Пользователей: 0
|
|
|