Перейти к содержанию

crazz

Рекомендуемые сообщения

Не мудрено в такой программе запутаться. Я бы часть кода не имеющего отношения к решению проблемы вынести в отдельный инклуд, инициализацию например и обработчики прерываний.

Функцию интерполяции тоже в отдельный.

Будет меньше текста, меньше глазам теряться. И проверить функцию можно отдельно, в другом проекте например с более удобными средствами отладки. В протеусе есть компонент который называется terminal его можно подключить к RX/TX выводам контроллера и через UART выдавать туда отладочные данные.

И еще, взял бы карандаш, лист бумаги и нарисовал бы блок-схему нужного алгоритма. Она нужна будет чтобы не запутаться потом при реализации.

Учение - изучение правил. Опыт - изучение исключений.

Ссылка на комментарий
Поделиться на другие сайты

Реклама: ООО ТД Промэлектроника, ИНН: 6659197470, Тел: 8 (800) 1000-321

Например, если её возвращаемое значение будет >99, то 7 раз !

Спасибо за подробное объяснение моих косяков =)

Я так и чувствовал что где то я не прав =)))

Сейчас поправлю =)

Будет меньше текста, меньше глазам теряться.

я пока путаюсь не в самой программе а просто даже в одной функции =))

Кстати, у функции LinearAPPROX возвращаемое значение void, т.б. ничего не возвращает, а Вы пытаетесь с неё взять какое то значение.

Тогда я не понимаю а каким образом эти функции вообще другие работают если они ничего не возвращают? Вот вечно меня это путает "возвращает не возвращает"

Ссылка на комментарий
Поделиться на другие сайты

20% скидка на весь каталог электронных компонентов в ТМ Электроникс!

Акция "Лето ближе - цены ниже", успей сделать выгодные покупки!

Плюс весь апрель действует скидка 10% по промокоду APREL24 + 15% кэшбэк и бесплатная доставка!

Перейти на страницу акции

Реклама: ООО ТМ ЭЛЕКТРОНИКС, ИНН: 7806548420, info@tmelectronics.ru, +7(812)4094849

И чего то у меня не получается. Функция возвращает 0

в инете в уроках пишут писать return но у меня ошибку выдает компилятор.

Вообщем если в коде пишу tm=126 то выдает 126 на дисплей значит все работает.

Но если эту строку заменяю на LinearAPPROX( tm); то выдает 0

Вот функция:

int LinearAPPROX(int tm)
{


unsigned int adc;
adc=(ADRESH<<8)+ADRESL;


if(adc>174 && adc<674){
tm=((-130L*adc+125344)/1024); //уравнение от 36.6 до 100
}
if(adc>674&& adc<835){
tm=((-132L*adc+126644)/1024); //уравнение от 15.8 до 36.6
}
if(adc>835 && adc<907){
tm=((-227L*adc+215109)/1024); //уравнение от 15.8 до 36.6
}
if (adc>906) {
tm=999;
}

}

Причем ошибка дилетантская потому что даже если вот такая функция все ровно возвращает 0

int LinearAPPROX(int tm)
{
tm=134;
}

Все разобрался =)))

Нельзя просто пихать в код запись LinearAPPROX( tm); а нужно какой то переменной присвоить значение этой функции:

tm=LinearAPPROX( tm);

А я пытался присвоить вот так: LinearAPPROX( tm)=tm;

Изменено пользователем Zombie47
Ссылка на комментарий
Поделиться на другие сайты

Выбираем схему BMS для корректной работы литий-железофосфатных (LiFePO4) аккумуляторов

 Обязательным условием долгой и стабильной работы Li-FePO4-аккумуляторов, в том числе и производства EVE Energy, является применение специализированных BMS-микросхем. Литий-железофосфатные АКБ отличаются такими характеристиками, как высокая многократность циклов заряда-разряда, безопасность, возможность быстрой зарядки, устойчивость к буферному режиму работы и приемлемая стоимость. Но для этих АКБ, также как и для других, очень важен контроль процесса заряда и разряда, а специализированных микросхем для этого вида аккумуляторов не так много. Инженеры КОМПЭЛ подготовили список имеющихся микросхем и возможных решений от разных производителей. Подробнее>>

Реклама: АО КОМПЭЛ, ИНН: 7713005406, ОГРН: 1027700032161

Вообщем дописал прогу, все работает, но осталось пару моментов.

1. В коде есть функция morganie и я сделал её криво. Ко мне пришло понимание того что прерывания это как своего рода многозадачность, но ею не являются. В данном случае правильнее моргание светодиодом сделать по прерыванию второго таймера верно? Ну или как правильно сделать чтобы при температуре свыше 110 градусов моргал варнинг (отдельный светодиод)?

2. Чтобы не ошибиться я вначале не думая выбирал типы переменных которые могут содержать число побольше, но как я понимаю выбрав к примеру тип переменной unsigned long int я автоматически под нее резевирую 32 бита, ну или как то так. А если она у меня будет принимать во всей программе значения в пределах от 0 до 255 то я как бы не оптимально построил программу, я верно мыслю? Тоесть мне сейчас нужно пройтись по всему коду и посмотреть какие значения у меня принимают переменные и задать соответствующий тип переменной.

3. И как по феншую сделать правильно чтобы значения не мерцали? ну к примеру переходные значения температуры могут мерцать. Просто вбабахать цикл for(i=64000;i>0;i--); перед каждым выводом температуры? или это не по феншую?

4. Ну и вообще насколько грамотно у меня написана программа? а в частности меня интересуют наверно больше всего мои формулы. Ибо как я читал что МК не любит деление и тд. Ну и как в будущем мне оценивать оптимальность программы?

/*
* File: newmain.c
* Author: Vlad
*
* Created on 16 ???????? 2015 ?., 0:37
'11-a RB5
'13-b RB7
'7-c RB1
'9-d RB3
'6-e RB0
'10-f RB4
'12-g RB6
'8-dp RB2
' RA3 dig1
' RA2 dig2
' RA7 dig3
*
* $82 - E, $08 -R
*
*/
#pragma config FOSC = INTOSCIO // Oscillator Selection bits (INTRC oscillator; port I/O function on both RA6/OSC2/CLKO pin and RA7/OSC1/CLKI pin)
#pragma config WDTE = OFF	 // Watchdog Timer Enable bit (WDT enabled)
#pragma config PWRTE = ON	 // Power-up Timer Enable bit (PWRT enabled)
#pragma config MCLRE = OFF	 // RA5/MCLR/VPP Pin Function Select bit (RA5/MCLR/VPP pin function is digital I/O, MCLR internally tied to VDD)
#pragma config BOREN = ON	 // Brown-out Reset Enable bit (BOR enabled)
#pragma config LVP = OFF	 // Low-Voltage Programming Enable bit (RB3/PGM pin has digital I/O function, HV on MCLR must be used for programming)
#pragma config CPD = OFF	 // Data EE Memory Code Protection bit (Code protection off)
#pragma config WRT = OFF	 // Flash Program Memory Write Enable bits (Write protection off)
#pragma config CCPMX = RB2	 // CCP1 Pin Selection bit (CCP1 function on RB2)
#pragma config CP = OFF		 // Flash Program Memory Code Protection bit (Code protection off)
#include <xc.h>
#include <pic.h>
#include <pic16f819.h>

#define dig1 RA3 //индикатор 1
#define dig2 RA2 //индикатор 2
#define dig3 RA7 //индикатор 3
//#define tochka RB2
#define warning RA1

#define LED PORTB
const unsigned char digits [13] = {0x44,0x7D,0x16,0x15,0x2D,0x85,0x84,0x5D,0x04,0x05,0xFF,0x86,0x0C}; //0,1,2,3,4,5,6,7,8,9,пусто, E,R
		 unsigned int i			 ; //
volatile	 unsigned char a			 ;//
volatile	 unsigned char LEDS[3]		 ; //

//***********************************************************************
//* ИНИЦИАЛИЗАЦИЯ МК
//***********************************************************************
void init(void)
{
INTCON =0x00; // запрет всех прерываний
OSCCON = 0b01100100; //с 4 по 6 бит значение 110 означает 4mhz
// настройка портов
PORTA = 0; //обнуляем порты а
PORTB = 0;
TRISA = 0b01110001; //порты RA2, RA3, RA7, RA1 на выход а остальные на вход
TRISB = 0b00000000; // все порты RB на выход
PORTA = 0; //обнуляем порты а
PORTB = 0;
warning=1; //вырубаем варнинг
// настройка АЦП
ADCON0=0b01000001; //тактирование АЦП Fosc/8, выбран канал AN0, модуль АЦП включен
ADCON1=0b10001110; //правое выравнивание, включен аналоговый вход RA0/AN0, остальные входы цифровые
// настройка таймера TMR0
TMR0 = 0; //сбрасываем таймер в 0
OPTION_REG = 0b00000011; // настройки таймера 1:16 и установка Set timer TMR0 даташит page 54:
// разрешение прерываний
TMR0IE = 1; //разрешение прерывания по таймеру0
GIE = 1; // глобальное разрешение прерываний
};
void morganie (){ //кривая функция моргания варнингом
 warning=1;
 for(i=64000;i>0;i--);
 warning=0;
};

void interrupt Timer (void)
{ //прерывание по таймеру для динамической индикации
if(TMR0IF)
 {
	 TMR0IF=0;
	 dig1=0; NOP(); dig2=0;NOP(); dig3=0; LED=(digits [10]); // гасим все разряды
	 a++;
	 switch(a)
 {	 // Динамическая индикация.
		 case 1: dig1=0; NOP(); dig2=0; NOP(); dig3=1; LED=(LEDS[2]); break; // Первый разряд
		 case 2: dig1=0; NOP(); dig3=0; NOP(); dig2=1; LED=(LEDS[1]); break; // второй разряд
		 case 3: dig2=0; NOP(); dig3=0; NOP(); dig1=1; LED=(LEDS[0]); a=0; break; // третий
 }
}
}
int LinearAPPROX(int tm) //функция конвертирования АЦП в температуру нелинейной характеристики резистивного датчика
{


 int adc,test;
 ADCON0bits.GO = 1; //запускаем ацп
 while (ADCON0bits.GO){NOP();}; // если ацп работает то ниче не делаем
 adc = (ADRESH<<8)+ADRESL; //помещаем значение ацп в переменную adc чтобы могли с ним работать ниже

 //898 - 3
// t1=(-227L*x+215109L)/1024;		 // y = - 32 /155 x + 29169/ 155 от 3 до 15.8
 //835-15.8
 // t2=(-132L*x+126644L)/1024;		 // y = - 104/ 805 x + 99559 /805 от 15.8 до 36.6
 //674-36.6
 // t3=(-130L*x+125344L)/1024 ;	 // y = - 317/ 2490 x + 152396 /1245 от 36.6 до 100
 //176-100

 if(adc<175){
tm=adc; //если температура выше 100 градусов (меньше значения ацп 175 ) то выдает значение АЦП в переменную tm для дальнейшей калибровки
}
 if(adc>174 && adc<675){
tm=((-130L*adc+125344)/1024); //уравнение от 36.6 до 100
}
 if(adc>674&& adc<836){
tm=((-132L*adc+126644)/1024); //уравнение от 15.8 до 36.6
}
 if(adc>835 && adc<898){
tm=((-211L*adc+192704)/1024); //уравнение от 15.8 до 3
}
 if (adc>897) {
	 tm=adc; //если температура ниже 3 градусов (АЦП 897) то выдает значение АЦП для дальнейшей калибровки;
}

}
void convert (void)//функция конвертирования значения температуры в показания на 3 разрядном семисегментном индикаторе
{
unsigned int adc,value, d1_1; //
int tm;
unsigned char DS,j;
unsigned char tempLEDS[3]		 ; // масив числа температуры на семисегментном индикаторе
 ADCON0bits.GO = 1; //запускаем ацп
 while (ADCON0bits.GO){NOP();}; // если ацп работает то ниче не делаем
 adc= (ADRESH<<8)+ADRESL; //значение ацп в adc

 value = adc; //
if ( value==1023) //если значение ацп равно 1023 то выполняем тело (1023 это когда 5 вольт тоесть когда не подрублен датчик)
 {
 tempLEDS[0]= digits [12]; //тело, отправляется на иникатор "ERR"
 tempLEDS[1]= digits [11];
 tempLEDS[2]= digits [11];
 warning=0; //и врубается варнинг
}
else // если не 1023 то выполняется тело
 {

 NOP();
tm=LinearAPPROX(tm); //присваиваем значение аргумента tm функции LinearAPPROX переменной с таким же именем просто чтобы не запутаться
 if(tm<10){ //если tm меньше 10 то выполняем тело
	 tempLEDS[2]=digits [10]; //посылаем пустой знак в ячейку 1
	 NOP();
	 tempLEDS[1]=digits [10]; //посылаем пустой знак в ячейку 2
	 NOP();
	 tempLEDS[0]=digits [tm]; //посылаем знак равный tm в ячейку 3
	 }// если значение меньше 10 то подаем цифру пусто на 1 и 2 слева индикатор
 if (tm >= 10 && tm < 100){
	 tempLEDS[2]=digits [10]; // если значение меньше от 10 до 100 то на 1 индикатор подаем цифру пусто. Заметил что там почемуто еле светиться цифра.
	 NOP();
	 d1_1=tm%100;
	 tempLEDS[1]=digits [d1_1/10];				 // Получаем разряд
	 tempLEDS[0]=digits [d1_1%10];			 // Получаем разряд
		 if (tm < 40 ){warning=0;NOP();} // врубаю варнинг если температура ниже 40
		 if (tm > 39 ){warning=1;NOP();} // вырубаю варнинг если температура выше 39
 }
 if (tm > 99 ){
	 d1_1=tm%100;
	 tempLEDS[2]=digits [tm/100];// Получаем разряд
	 tempLEDS[1]=digits [d1_1/10]; // Получаем разряд
	 tempLEDS[0]=digits [d1_1%10]; // Получаем разряд
	 if (tm > 110 ){morganie();} // врубаю морганием варнингом если температура выше 110
	 if (tm < 111 ){warning=1;NOP();} // вырубаю варнинг если температура ниже 111
 }


 }
GIE = 0;// глобальный запрет прерываний чтобы три переменных записались и запись не прервалась.
 LEDS[0]= tempLEDS[2];
 LEDS[1]= tempLEDS[1];
 LEDS[2]= tempLEDS[0];
GIE = 1;// врубаем прерывания заново.	

}
//***********************************************************************
//* ОСНОВНАЯ ПРОГРАММА
//***********************************************************************
void main (void)
{
 init();
 for(i=255;i>0;i--);
 //******** ГЛАВНЫЙ ЦИКЛ *****************
 while (1)
	 {
	 convert ();
	 };
}

Изменено пользователем Zombie47
Ссылка на комментарий
Поделиться на другие сайты

Для того чтобы не мерцало, надо применять алгоритмы сглаживания коих имеется вагон и тележка. Самый простой и эффективный это метод подвижного окна, когда берется последние N значений и вычисляется арифметическое среднее.

Но это означает что надо не просто взять N значений, а каждую итерацию учитывать N предыдущих измерений а для этого нужно организовать кольцевой буфер куда будут заносится измерения. Лучше всего когда размер буфера кратен степени двойки(8-16-32-64), деление суммы тогда заменяется элементарным сдвигом. Но с другой стороны, чем больше размер тем больше будет отставание показаний от реального значения.

как-то вот так

Изменено пользователем Alexeyslav

Учение - изучение правил. Опыт - изучение исключений.

Ссылка на комментарий
Поделиться на другие сайты

IMHO многабукафф, а где следует, код пропущен. Я-бы сделал как-то так:

...

#include <xc.h>
#include <pic.h> // Лишнее
#include <pic16f819.h> // Лишнее
...

#define _XTAL_FREQ 4000000 // для __delay_us и __delay_ms

//***********************************************************************
//* ИНИЦИАЛИЗАЦИЯ МК
//***********************************************************************
void init(void)
{
// обнулить индекс динамической индикации:
а = 0 ;
...
void interrupt Timer (void)
{ //прерывание по таймеру для динамической индикации
if( TMR0IF && TMR0IE )
	 {
			 TMR0IF=0;

		 // гасим все разряды
			 dig1=0;
			 dig2=0;
			 dig3=0;

			 // Или все разом:
			 PORTA &= 0b01110011 ;

			 a++;
			 switch(a)
	 {	 // Динамическая индикация.
					 case 1:
						 // Сначала выставляем символ, потом зажигаем разряд
						 LED=(LEDS[2]);
						 dig3=1;
						 break; // Первый разряд

					 case 2:
						 LED=(LEDS[1]);					    
						 dig2=1;
						 break; // второй разряд

					 case 3:
						 LED=(LEDS[0]);					    
						 dig1=1;
						 a=0;
						 break; // третий
	 }
}
}
...
// В оригинале функция ничего не возвращала. И наоборот, аргументы ей не нужны

int LinearAPPROX( void ) //функция конвертирования АЦП в температуру нелинейной характеристики резистивного датчика
{
int adc;

ADCON0bits.GO = 1; //запускаем ацп
// Просто для удобочитаемости:
while (ADCON0bits.GO); // если ацп работает то ниче не делаем

...

	 adc = ( ADRESH << 8 ) | ADRESL;

// используется оператор "больше либо равно"/"меньше либо равно" Чтобы точно видеть в какой диапазон попадает перемнная adc

	 if( adc < 175 || adc > 897 )
		 return adc ;

	 if( adc >= 175 && adc <= 675 )
		 return (-130L*adc+125344)/1024 ; //уравнение от 36.6 до 100

	 if( adc >= 676 && adc <= 836 )
		 return (-132L*adc+126644)/1024; //уравнение от 15.8 до 36.6

	 if( adc >= 837 && adc <= 897 )
		 return (-211L*adc+192704)/1024 ; //уравнение от 15.8 до 3

}
...    

void convert (void)//функция конвертирования значения температуры в показания на 3 разрядном семисегментном индикаторе
{
unsigned int adc,value, d1_1; //
int tm;
unsigned char DS,j;
unsigned char tempLEDS[3]			    ; // масив числа температуры на семисегментном индикаторе


	 tm = LinearAPPROX();

	 // Сначала вызываем LinearAPPROX, потом делаем всё остальное
	 // Или АЦП запускаем здесь, а в LinearAPPROX обрабатываем, но не в двух местах

    if ( tm == 1023) //если значение ацп равно 1023 то
...

//***********************************************************************
//* ОСНОВНАЯ ПРОГРАММА
//***********************************************************************
void main (void)
{
...
	 for(i=255;i>0;i--); // для задержки есть макросы __delay_us и __delay_ms

	 //******** ГЛАВНЫЙ ЦИКЛ *****************
	 while (1)
...
}

Как-то так. Ну и куча ненужных NOP(); Я знаю про RMW, но в данном случае проявление этого эффекта маловероятно, т.к. после установки битов идёт обращение к элементам массива, математика разная и др. Для измерения производительности функций в MPLAB, нужно в симуляторе использовать инструмент Stopwatch.

Изменено пользователем shindbad
Ссылка на комментарий
Поделиться на другие сайты

Самый простой и эффективный это метод подвижного окна, когда берется последние N значений и вычисляется арифметическое среднее.

А N значений лучше брать АЦП или температуру?

Ссылка на комментарий
Поделиться на другие сайты

Потому что иначе тебе надо будет N-1 лишних раз делать преобразование код-температура, лучше его 1 раз сделать после сглаживания.

Учение - изучение правил. Опыт - изучение исключений.

Ссылка на комментарий
Поделиться на другие сайты

Попытался придумать алгоритм сглаживания но чето пошло не так не работает вообщем. Вот такой код вставил в функцию convert

void convert (void)//функция конвертирования значения температуры в показания на 3 разрядном семисегментном индикаторе
{ 
   unsigned int  adc,value, d1_1; //
   int tm, sglaz;
   int tmp,tmp1,tmp2,tmp3,tmp4,tmp5,tmp6,tmp7,tmp8;
   unsigned char DS,j;
   unsigned char    tempLEDS[3]          ; // масив числа температуры на семисегментном индикаторе
   tm=LinearAPPROX(tm); //присваиваем значение аргумента tm функции LinearAPPROX переменной с таким же именем просто чтобы не запутаться    

       while (ADCON0bits.GO){NOP();}; // если ацп работает то ниче не делаем
   for (sglaz=0;sglaz<8;sglaz++){
       ADCON0bits.GO = 1; //запускаем ацп
       tmp = (ADRESH<<8)+ADRESL; //значение ацп в adc
       if (sglaz==0){tmp1=tmp;}
       if (sglaz==1){tmp2=tmp;}
       if (sglaz==2){tmp3=tmp;}
       if (sglaz==3){tmp4=tmp;}
       if (sglaz==4){tmp5=tmp;}
       if (sglaz==5){tmp6=tmp;}
       if (sglaz==6){tmp7=tmp;}
       if (sglaz==7){tmp8=tmp;}
       ADCON0bits.GO = 0; //вырубаем ацп
   }
   adc=(tmp1+tmp2+tmp3+tmp4+tmp5+tmp6+tmp7+tmp8)/8;
       value = adc; //

Ну и я вообще не понимаю как 8 штуками можно усреднить показания, вплане он же эти 8 ацп настолько быстро делает что один хрен мерцать будет. Я конечно могу вбахать код до 1024 но я чую это извращение ) Нужно как понимаю функцию писать. а вообще я правильно мыслю?

Ссылка на комментарий
Поделиться на другие сайты

чёт трава какая-то несусветная. Массивами вас никто пользоваться не научил?

Сглаживание должно быть вне этой процедуры.

Алгоритм очень простой - все значения измеренные АЦП постоянно складываешь в кольцевой буфер, просто тупо пишешь и все. Каждое измерение в следующую ячейку, дошли до конца буфера - переходим на начало. Алгоритм простой как пробка.

Потом, когда тебе надо вывести на дисплей, суммируешь каждую ячейку массива и делишь на количество ячеек. Удобно получается когда массив имеет размер кратный двойке - 16-32-64 измерения, тогда деление заменяется на сдвиг. И всё. В результате у тебя имеется значение которое можно преобразовывать и выводить как раньше до сглаживания.

Учение - изучение правил. Опыт - изучение исключений.

Ссылка на комментарий
Поделиться на другие сайты

Алгоритм простой как пробка.

для вас простой а я сижу голову ломаю =)))

adc = (old_adc<<4 - old_adc + tmp)>>4;

old_adc = adc;

какой то замкнутый круг получается.

tmp=255 к примеру.

adc=(old-adc ...а old_adc равно adc

итого получается adc=(adc/4-adc+255)*4 итого получаем уравнение с неизвестными =) нихрена не понимаю =(

Ссылка на комментарий
Поделиться на другие сайты

Ломка это хорошо. Возьми листочек бумаги и разрисуй алгоритм. А потом его просто пошагово воплоти. Когда есть листочек с бумагой это делать куда проще, у тебя сейчас просто переполнение стека, ты выбрал не тот уровень абстракции и на нём оказалось слишком много элементов поэтому мозг не может справится.

Есть такая отличная методика - метод черного ящика. И процесс разработки который постепенно превращает черный ящик в белый ящик.

Вот смотри. У тебя сейчас есть готовый алгоритм который работает и выводит значения на индикатор. Тебе в него надо вставить алгоритм сглаживания.

Так вот твой алгоритм сглаживания будет черным ящиком, который стоит между выходом с АЦП и выводом на индикатор.

На вход будут поступать значения с АЦП, на выходе будут браться значения выводимые на индикатор в том же формате как поступили с АЦП.

И так, раскрываем черный ящик.

Первым шагом будет сохранить значение со входа в массив как в револьвер патроны. если в ячейке уже есть значение - выбрасываем его и вставляем новое, проворачиваем барабан.

Следующее действие - прокрутить барабан на 360 градусов, и просуммировать все патроны, полученную сумму разделить на количество ячеек в барабане-массиве, мы получим среднее значение N последних измерений.

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

Учение - изучение правил. Опыт - изучение исключений.

Ссылка на комментарий
Поделиться на другие сайты

хорошо попробуем вдолбить попроще

Y(n) = (15*Y(n-1)+X(n))/16

X(n) - текущие значение АЦП

Y(n) - текущие усредненное значение

Y(n-1) - предыдущие усредненное значение

ЗЫ это эквивалентно тому что предлагает Alexeyslav только с учетом того, что это массив на 260 элементов и без танцев с бубном с кольцевым буфером

Ссылка на комментарий
Поделиться на другие сайты

хорошо попробуем вдолбить попроще

в том то и дело вдолбешка не дает понимания, я смотрю на это уровнение и вопросы, откуда оно взялось? куда его вставить? как его вставить? Откуда взять предыдущее усрендненое значение если для его нахождения надо знать предыдущее усредненное значение а для этого предыдущего еще предыдущее, замкнутый круг и тд и тп. Попробую с массивом с ним понятнее.

Ссылка на комментарий
Поделиться на другие сайты

:)http://we.easyelectr...ovoy-filtr.html

adc = (old_adc<<4 - old_adc + tmp)>>4; - это измененная формула (5) из ссылки выше из которой вообще исключена операция умножения 15x = x(16 - 1) = x<<4 - x

Ссылка на комментарий
Поделиться на другие сайты

Я не знаю как вывести сумму элементов массива кроме как вручную печатать =))))

:)http://we.easyelectr...ovoy-filtr.html

adc = (old_adc<<4 - old_adc + tmp)>>4; - это измененная формула (5) из ссылки выше из которой вообще исключена операция умножения 15x = x(16 - 1) = x<<4 - x

Тема вроде называется "начинающим" =)))) по ссылке явно не для начинающих. Не осилил.

Вот так правильно?

int adcsf (s);
adcsf (s){
 unsigned char adcs [128];
  for (a=0;a<127;a++){
 ADCON0bits.GO = 1; //запускаем ацп
	  adcs [a] = (ADRESH<<8)+ADRESL; //значение ацп
 ADCON0bits.GO = 0; //вырубаем ацп
  }
 s = сумма adcs массива поделить на 128.
}

Ссылка на комментарий
Поделиться на другие сайты

я не понимаю почему.

я прогоняю цикл от 0 до 128 и запсываю полученые значения ацп за каждый прогон в массив с индексами по порядку. а потом просто складываю и делю на 128 нахожу среднее арифметическое. В чем не правильность?

Ссылка на комментарий
Поделиться на другие сайты

В чем не правильность?

считываете значение АЦП

инкриминируете счетчик массива и значение АЦП заносите в массив

когда нужно получить средние тупо в цикле складываете элементы массива и делите на его размер

Ссылка на комментарий
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.
Примечание: Ваш пост будет проверен модератором, прежде чем станет видимым.

Гость
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Ответить в этой теме...

×   Вставлено с форматированием.   Восстановить форматирование

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

Загрузка...
  • Последние посетители   0 пользователей онлайн

    • Ни одного зарегистрированного пользователя не просматривает данную страницу

×
×
  • Создать...