Попытаюсь объяснить что тут я накрутил.
Оговорюсь сразу. Скомпилировал - работает. Другое дело что считает неправильно, но тут я думаю что все закручено на типах переменных и приведении чисел к человекочитаемому виду.
С немецким наигрался в доволь )
Да, помогите пожалуйста нормально посчитать числа. а то неполучается (
Код: Выделить всё
/*****************************************************
Chip type : ATmega8
Program type : Application
AVR Core Clock frequency: 4,000000 MHz
Memory model : Small
External RAM size : 0
Data Stack size : 256
*****************************************************/
#include <mega8.h>
#asm
.equ __lcd_port=0x18 ;PORTB
#endasm
#include <lcd.h>
#include <delay.h>
#include <stdio.h>
#include <math.h>
//************************************ Статус системы ****************************************//
_Bool R_Umwandlung=0; // режим преобразования да/нет
_Bool Arbeit_END=0; // работа окончена да/нет
_Bool LCD_UP=0; // вывод на экран да/нет
//**************************************** Переменные ****************************************//
volatile float S_RES=0.00; // результат S_RES
volatile float S_INT=0.00; // S_intermediate (Проможуточное S)
volatile float CURRENT=0.00; // ток
unsigned int ACP_Anzahl=0; // DAS IST ACP_Anzahl
//********************************* Переменные времени ***************************************//
volatile unsigned int KOL=0; // кол-во положительных подсчетов (синусоида наростает либо спадает, но недоходя до граничной зоны)
volatile unsigned int MS=0; // дискретность 0.2 секунды, хватит на 2621 секунду работы
volatile unsigned int SCHLECHT_Anzahl=0; // число плохих подсчетов
unsigned unsigned int WATCH=0; // Выводимое время, хватит на 13105 секунд но count'а хватит на 2621 секунд, поэтому всеравно 2621
//*************************************** Макросы ********************************************//
#define ADC_MIN 2 // порог срабатывания АЦП
#define WAIT_EN 250 // сколько измерений должно быть ниже порога, чтобы импульс считать закончившимся
#define WAIT_ST 250 // сколько измерений должно быть, включить FLAG=Warten_START
#define Kt 0.1 //коэффициент преобразования из значения АЦП в ток.
// Массивы
char TIME[12];
char RES_IMP[12];
char STROM[12];
//********************************************************************************************//
interrupt[TIM2_COMP] void timer2_comp_isr(void){ // прерывание по совпадению 5кГц
ACP_Anzahl=ADCW; // Anzahl
if(ACP_Anzahl<ADC_MIN){ // если с АЦП пришло маленькое число, ну прям очень маленькое
SCHLECHT_Anzahl++; // считаем сколько раз отдаваемое с АЦП число плохое
if((SCHLECHT_Anzahl==WAIT_EN) && (R_Umwandlung==1)){ // если режим (R_Umwandlung=тру) а это возможно когда хоть раз проскочил импульс выше чем минимальная уставка (это в свою очередь означает что аппарат работал (если конечно не помешала наводка или шумы, ну тут на практике загрубим и будет норм), а если работал то при ожидании 250 прерываний (тоесть синусоида пришла и больше не возвращается) отключаемся и выводим флаг окончания измерений)
SCHLECHT_Anzahl=0;
Arbeit_END=1; // Arbeit_END вывод на экран окончания результата измерения
lcd_clear();
TIMSK=0; // больше нету прерываний, переменные остаются неизменными
TCCR2=0; // больше нету таймера по совпадению OCR2
ADCSR=0;
}else{
if(SCHLECHT_Anzahl==1000){SCHLECHT_Anzahl=0;}} // это режим ожидания запуска. Сброс счетчика обусловлено (шоб не крутил много)
}else{
R_Umwandlung=1; // режим преобразования
KOL++; // считаем кол-во
if(SCHLECHT_Anzahl>0){KOL=KOL+SCHLECHT_Anzahl; SCHLECHT_Anzahl=0;} // если есть плохое время плюсуем его к времени текущих полож. подсчетов. Прикол в том что В ДВУХПОЛУПЕРИОДНОМ выпрямлении синусоида спадает до 0 а потом нарастает. И если считать только время положительных значений то можно потерять реальное время наличия синусоиды. Визуальное обьяснение в приложеной картинке
if(KOL==1000){MS++; KOL=0; LCD_UP=1;} // 0.2 секунды
CURRENT=(float) ACP_Anzahl/100; // (ACP_Anzahl/10) дело в том что в реальности есть подстроечный резюк в цепи ООС операционника, а это значит что могу подганять аналоговую часть к цифровой. Другими словами посчитаю как здесь будет удобно, а потом подберу коэф. усиления.
S_INT=CURRENT*CURRENT;
S_RES=S_RES+S_INT;
}}
void Update_LCD(){
lcd_gotoxy(0,0);
sprintf(STROM,"im:%d02A",ACP_Anzahl);
lcd_puts(STROM);
if(MS%5==0){WATCH++;} // 1 секунда
lcd_gotoxy(10,0);
sprintf(TIME,"t:%ds",WATCH);
lcd_puts(TIME);
S_RES=S_RES/5000; // 5 кГ
lcd_gotoxy(0,1);
sprintf(RES_IMP,"A:%dA2*s",S_RES);
lcd_puts(RES_IMP);
}
void end_LCD(){
CURRENT=sqrt((S_RES/5000)/WATCH);
lcd_gotoxy(0,0);
sprintf(STROM,"I:%dA",CURRENT);
lcd_puts(STROM);
lcd_gotoxy(10,0);
sprintf(TIME,"t:%ds",WATCH);
lcd_puts(TIME);
lcd_gotoxy(0,1);
sprintf(RES_IMP,"A:%dA2*s",S_RES);
lcd_puts(RES_IMP);
}
void main(void){
//****************************** Системные настройки ******************************//
ADMUX=0xC0; // Номер порта и опорное напряжение 2.56
ADCSR=(1<<ADEN | 1<<ADSC | 1<<ADFR | 0<<ADIF | 0<<ADIE | 1<<ADPS2 | 1<<ADPS1 | 0<<ADPS0); // Настройки АЦП
TCCR2=(0<<CS22 | 1<<CS21 | 0<<CS22 | 1<<WGM21); // 5 kHz и по совпадению OCR2
OCR2=0x64; // число 100
TIMSK=(1<<OCIE2); // включили счетчик
lcd_init(16); // инициализация экрана
#asm("sei") // разрешение прерывания
//*********************************************************************************//
// первый запуск (режим ожидания)
lcd_gotoxy(0,0);
lcd_puts("I:0A");
lcd_gotoxy(10,0);
lcd_puts("t:0s");
lcd_gotoxy(0,1);
lcd_puts("A:0kA2*s");
while(1){
if(LCD_UP==1){Update_LCD(); LCD_UP=0;};
if(Arbeit_END==1){end_LCD();}}
}


