Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: ADuC 841 подогнать под 10 КГц
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > Все остальные микроконтроллеры > MCS51
B1sh0p
Задача подогнать программу под 10 Кгц. Все проблемы начинаются с тог, что в программе используются коэффициенты с дробной частью (4,8; 5,21...). Я в таких случаях использую тип float для переменных. Но так как процессор 8-битный, то тут и начинаются тормоза.

Вопрос такой: как уложиться в 10 КГц и не лишиться точности вычислений?
Verifi
Цитата(B1sh0p @ Jun 17 2009, 00:43) *
Задача подогнать программу под 10 Кгц. Все проблемы начинаются с тог, что в программе используются коэффициенты с дробной частью (4,8; 5,21...). Я в таких случаях использую тип float для переменных. Но так как процессор 8-битный, то тут и начинаются тормоза.
Вопрос такой: как уложиться в 10 КГц и не лишиться точности вычислений?

Перевести КОООФИЦИЕНТЫ В ЦЕЛЫЕ (48 )сделать чего надо в целочисленном виде,а результат разделить на 10,хотя я на ADUC 845 переделывал библиотеку под плавучку на асме для максимальношо ускорения,результатом остался весьма доволен.А вообще поподробнее чего в прграмме с 10 Кгц делается?
barabek
Цитата(Verifi @ Jun 17 2009, 19:56) *
Перевести КОООФИЦИЕНТЫ В ЦЕЛЫЕ (48 )сделать чего надо в целочисленном виде,а результат разделить на 10

Согласен. Но иногда лучше переводить коэффициенты умножением на числа 2^х . Тогда деление можно сделать быстрее.
Выбирайте.
B1sh0p
Цитата(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;
}
}
}
Verifi
Вполне хорошо получится перевести все числа в целые,а потом делите результат на 10 или 100 и даже возможно уложились в 16 разрядую математику,например типа вот так:
fU7 = 48 * (fUoc - 2048 )
fU6 = fU7 + fU7_1 + fU6_1;
B1sh0p
Цитата(Verifi @ Jun 18 2009, 08:55) *
Вполне хорошо получится перевести все числа в целые,а потом делите результат на 10 или 100 и даже возможно уложились в 16 разрядую математику,например типа вот так:
fU7 = 48 * (fUoc - 2048 )
fU6 = fU7 + fU7_1 + fU6_1;


Не выйдет. Там дальше используются умножения и сложения.... Я уже пробовал подобное. Резултат теряется за 16-ю битами. Может есть у кого идеи? Ну оооочень нужно. Я бьюсь уже почти месяц. Задача сама по себе плевая, а вот оптимизация хромает.....
barabek
вопервых,
Цитата(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 не делить

Вы что-то типа фильтров описываете, но я в Вашем описании не разобрался smile.gif, поэтому придется Вам самому дальше разбираться. Например, в последней моей строке если не делить на 256 может начаться переполнение.
Verifi
Цитата(B1sh0p @ Jun 18 2009, 18:25) *
Не выйдет. Там дальше используются умножения и сложения.... Я уже пробовал подобное. Резултат теряется за 16-ю битами. Может есть у кого идеи? Ну оооочень нужно. Я бьюсь уже почти месяц. Задача сама по себе плевая, а вот оптимизация хромает.....

Обьясните как то попроще что эта за плёвая задача,а код вам помогут нарисовать,а то у вас не совсем понятен алгоритм.
B1sh0p
Цитата(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;
}
}
}
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.