|
|
  |
ADuC 841 подогнать под 10 КГц |
|
|
|
Jun 16 2009, 20:43
|
Группа: Новичок
Сообщений: 4
Регистрация: 16-06-09
Пользователь №: 50 350

|
Задача подогнать программу под 10 Кгц. Все проблемы начинаются с тог, что в программе используются коэффициенты с дробной частью (4,8; 5,21...). Я в таких случаях использую тип float для переменных. Но так как процессор 8-битный, то тут и начинаются тормоза.
Вопрос такой: как уложиться в 10 КГц и не лишиться точности вычислений?
|
|
|
|
|
Jun 17 2009, 08:56
|
Местный
  
Группа: Участник
Сообщений: 315
Регистрация: 5-05-08
Из: Kursk
Пользователь №: 37 282

|
Цитата(B1sh0p @ Jun 17 2009, 00:43)  Задача подогнать программу под 10 Кгц. Все проблемы начинаются с тог, что в программе используются коэффициенты с дробной частью (4,8; 5,21...). Я в таких случаях использую тип float для переменных. Но так как процессор 8-битный, то тут и начинаются тормоза. Вопрос такой: как уложиться в 10 КГц и не лишиться точности вычислений? Перевести КОООФИЦИЕНТЫ В ЦЕЛЫЕ (48 )сделать чего надо в целочисленном виде,а результат разделить на 10,хотя я на ADUC 845 переделывал библиотеку под плавучку на асме для максимальношо ускорения,результатом остался весьма доволен.А вообще поподробнее чего в прграмме с 10 Кгц делается?
--------------------
"Если я в чем-то сомневаюсь, я возвращаюсь к началу"
|
|
|
|
|
Jun 17 2009, 14:41
|
Знающий
   
Группа: Свой
Сообщений: 540
Регистрация: 16-08-07
Из: Владивосток
Пользователь №: 29 831

|
Цитата(Verifi @ Jun 17 2009, 19:56)  Перевести КОООФИЦИЕНТЫ В ЦЕЛЫЕ (48 )сделать чего надо в целочисленном виде,а результат разделить на 10 Согласен. Но иногда лучше переводить коэффициенты умножением на числа 2^х . Тогда деление можно сделать быстрее. Выбирайте.
|
|
|
|
|
Jun 17 2009, 18:47
|
Группа: Новичок
Сообщений: 4
Регистрация: 16-06-09
Пользователь №: 50 350

|
Цитата(Verifi @ Jun 17 2009, 12:56)  Перевести КОООФИЦИЕНТЫ В ЦЕЛЫЕ (48 )сделать чего надо в целочисленном виде,а результат разделить на 10,хотя я на ADUC 845 переделывал библиотеку под плавучку на асме для максимальношо ускорения,результатом остался весьма доволен.А вообще поподробнее чего в прграмме с 10 Кгц делается? Вот тут ----------------------------- CODE #include <ADuC841.h>
#define TRUE 1 #define FALSE 0
#define ADC_0 0x10 #define ADC_1 0x11
#define ADCCON1_CFG 0xF2; #define T2CON_CFG 0x4; #define PLLCON CFG 0x50:
sbit P00 = P0^0: sbit P01 = P0^1; sbit P02 = Р0^2; sbit Р03 = Р0^3; sbit Р34 = РЗ^4; sbit Р35 = РЗ^5; sbit Р36 = РЗ^6; sbit Р37 = РЗ^7;
unsigned char chanel = 0;
float fUoc = 0, fUf = 0, fUf1 = 0, fU2 = 0, fUnkz = 0, fUЗ = 0, fU4 = 0, fU3_1 = 0, fU4_1 = 0. fU5 = 0, fU6 = 0, fU8 = 0, fU7_1 = 0, fU6_1 = 0, fUosh = 0, fUosh_1 = 0, fUin1 = 0, fUin2 = 0, fUin = 0, fUtp = 0, fU7 = 0;
char sign (float value ) { return ( value > 0 ) ? 1 : -1; } short get_ADC ( char ADCCONFIGDATA) { ADCCON2 = ADCCONFIGDATA; while ( SCONV ) { } return ((ADCDATAH & 0xF ) * 0x100 + ADCDATAL; } void InitializeCPU ( ) { ADCCON1 = ADCC0N1_CFG; T2CON = T2CON_CFG; PLLCON = PLLCON_CFG;
RCAP2H = 0xFF; RCAP2L = 0x9C;
PT2 = 1; // Timer 2 interupt priority Т2ЕX = 0; T2 = 0; TF2 = 1; // Interupt flag enable } void main( void ) { Initialize_CPU( ); while (TRUE) { if ( TF2 = TRUE ) { TF2 = FALSE; for( chanel = 0; chanel <= 1; chanel++ ) { switch( chanel ) case 0: fUin1 = ( P00 = FALSE ) ? FALSE : 4096; fUin2 = ( P01 = FALSE ) ? FALSE : 4096; fUoc = getADC ( ADC_0 ): break; case 1: fUin1 = ( P02 = FALSE ) ? FALSE : 4096; fUin2 = ( P03 = FALSE ) ? FALSE : 4096; fUoc = get_ADC ( ADC_1 ): break; default: break; } fU7 = 4.8 * (fUoc - 2048 ); fU6 = 10 * fU7 + 10 * fU7_1 + fU6_1; fU7_1 = fU7; fU6_1 = fU6: fUosh = 5.21 * fUin - 5.84 * fU7;
fUf = 0.25 * fUosh + (-0.25 * fUosh_1 - 0.25 * fUf ); fUosh_1 = fUosh; fUf_1 = fUf; fU2 = (fUf >= 2457.6) ? 2457.6 : (fUf <= -2457.6) ? -2457.6 : fUf; fUnkz - 10 * fUin + fU2 - 0.1 * fU7 - 15 * fU8 + 2.33 * fU5; fUЗ = (fUnkz >= 3522.56) ? 3522.56 : (fUnkz <= 3522.56) ? 3522.56 : fUnkz; } } }
Сообщение отредактировал B1sh0p - Jun 17 2009, 18:54
|
|
|
|
|
Jun 18 2009, 14:25
|
Группа: Новичок
Сообщений: 4
Регистрация: 16-06-09
Пользователь №: 50 350

|
Цитата(Verifi @ Jun 18 2009, 08:55)  Вполне хорошо получится перевести все числа в целые,а потом делите результат на 10 или 100 и даже возможно уложились в 16 разрядую математику,например типа вот так: fU7 = 48 * (fUoc - 2048 ) fU6 = fU7 + fU7_1 + fU6_1; Не выйдет. Там дальше используются умножения и сложения.... Я уже пробовал подобное. Резултат теряется за 16-ю битами. Может есть у кого идеи? Ну оооочень нужно. Я бьюсь уже почти месяц. Задача сама по себе плевая, а вот оптимизация хромает.....
|
|
|
|
|
Jun 19 2009, 01:26
|
Знающий
   
Группа: Свой
Сообщений: 540
Регистрация: 16-08-07
Из: Владивосток
Пользователь №: 29 831

|
вопервых, Цитата(B1sh0p @ Jun 18 2009, 05:47)  Код fUin1 = ( P00 = FALSE ) ? FALSE : 4096; почему Вас компилятор не предупреждает о возможной ошибке, ведь в скобках подразумевается "==", а не "=" ? Далее у Вас несколько раз встречаются конструкции вида Код fU6 = 10 * fU7 + 10 * fU7_1 + fU6_1; Ведь можно общий множитель вынести за скобку. У silabs есть такой документ "CIP-51 Performance for Standard Library Math Routines". Так вот, там написано, что среднее время выполнения умножения float больше чем сложение. Непонятны строки Код fUosh = 5.21 * fUin - 5.84 * fU7; <-откуда берется fUin ? fUnkz - 10 * fUin + fU2 - 0.1 * fU7 - 15 * fU8 + 2.33 * fU5; <-чему это все присваивается? Так как не все величины в Вашем коде понятны, откуда они берутся, то полностью оптимизированный код дать не получится. Мой совет - переводите все в long. В этом случае на умножении Вы не сильно выиграете, а на сложениях-вычитаниях ускорение почти в 10 раз. Например: Код fU7 = 1229 * (fUoc - 2048 ); //1228,8=4,8*256 //....... fUf=64*(fUosh- fUosh_1-fUf)/256; //например так всесто fUf = 0.25 * fUosh + (-0.25 * fUosh_1 - 0.25 * fUf ); //а можно в этом месте на 256 не делить Вы что-то типа фильтров описываете, но я в Вашем описании не разобрался  , поэтому придется Вам самому дальше разбираться. Например, в последней моей строке если не делить на 256 может начаться переполнение.
|
|
|
|
|
Jun 19 2009, 04:13
|
Местный
  
Группа: Участник
Сообщений: 315
Регистрация: 5-05-08
Из: Kursk
Пользователь №: 37 282

|
Цитата(B1sh0p @ Jun 18 2009, 18:25)  Не выйдет. Там дальше используются умножения и сложения.... Я уже пробовал подобное. Резултат теряется за 16-ю битами. Может есть у кого идеи? Ну оооочень нужно. Я бьюсь уже почти месяц. Задача сама по себе плевая, а вот оптимизация хромает..... Обьясните как то попроще что эта за плёвая задача,а код вам помогут нарисовать,а то у вас не совсем понятен алгоритм.
--------------------
"Если я в чем-то сомневаюсь, я возвращаюсь к началу"
|
|
|
|
|
Jun 19 2009, 17:11
|
Группа: Новичок
Сообщений: 4
Регистрация: 16-06-09
Пользователь №: 50 350

|
Цитата(Verifi @ Jun 19 2009, 08:13)  Обьясните как то попроще что эта за плёвая задача,а код вам помогут нарисовать,а то у вас не совсем понятен алгоритм. Ребят, я бы с удовольствием выложил бы схему, но меня за нее убьют. Дело в том, что надо получить данные с двух АЦП 0 и 1 и по формулам расчитать выходное цифровое значение. Формулы я приложил, правда с опечатками. Ну НЕ МОГУ Я выложить всю задачу. Основную часть, в которой проблемы я показал. CODE #include <ADuC841.h>
#define TRUE 1 #define FALSE 0
#define ADC_0 0x10 #define ADC_1 0x11
#define ADCCON1_CFG 0xF2; #define T2CON_CFG 0x4; #define PLLCON CFG 0x50:
sbit P00 = P0^0: sbit P01 = P0^1; sbit P02 = Р0^2; sbit Р03 = Р0^3; sbit Р34 = РЗ^4; sbit Р35 = РЗ^5; sbit Р36 = РЗ^6; sbit Р37 = РЗ^7;
unsigned char chanel = 0;
float fUoc = 0, fUf = 0, fUf1 = 0, fU2 = 0, fUnkz = 0, fUЗ = 0, fU4 = 0, fU3_1 = 0, fU4_1 = 0. fU5 = 0, fU6 = 0, fU8 = 0, fU7_1 = 0, fU6_1 = 0, fUosh = 0, fUosh_1 = 0, fUin1 = 0, fUin2 = 0, fUin = 0, fUtp = 0, fU7 = 0;
char sign (float value ) { return ( value > 0 ) ? 1 : -1; } short get_ADC ( char ADCCONFIGDATA) { ADCCON2 = ADCCONFIGDATA; while ( SCONV ) { } return ((ADCDATAH & 0xF ) * 0x100 + ADCDATAL; } void InitializeCPU ( ) { ADCCON1 = ADCC0N1_CFG; T2CON = T2CON_CFG; PLLCON = PLLCON_CFG;
RCAP2H = 0xFF; RCAP2L = 0x9C;
PT2 = 1; // Timer 2 interupt priority Т2ЕX = 0; T2 = 0; TF2 = 1; // Interupt flag enable } void main( void ) { Initialize_CPU( ); while (TRUE) { if ( TF2 = TRUE ) { TF2 = FALSE; for( chanel = 0; chanel <= 1; chanel++ ) { switch( chanel ) case 0: fUin1 = P00; fUin1 << 12; fUin2 = P01; fUin2 << 12; fUoc = getADC ( ADC_0 ): break; case 1: fUin1 = P02; fUin1 << 12; fUin2 = P03; fUin2 << 12; fUoc = get_ADC ( ADC_1 ): break; default: break; } fU7 = 4.8 * (fUoc - 2048 ); fU6 = 10 * fU7 + 10 * fU7_1 + fU6_1; fU7_1 = fU7; fU6_1 = fU6: fUosh = 5.21 * fUin - 5.84 * fU7;
fUf = 0.25 * fUosh + (-0.25 * fUosh_1 - 0.25 * fUf ); fUosh_1 = fUosh; fUf_1 = fUf; fU2 = (fUf >= 2457.6) ? 2457.6 : (fUf <= -2457.6) ? -2457.6 : fUf; fUnkz = 10 * fUin + fU2 - 0.1 * fU7 - 15 * fU8 + 2.33 * fU5; fUЗ = (fUnkz >= 3522.56) ? 3522.56 : (fUnkz <= 3522.56) ? 3522.56 : fUnkz; } } }
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|