Вообще, я просто хотел использовать измеренное в фуннкции getAVccVoltage напряжение питания при расчете замеряемого напряжения на четвертом пине ацп.
вообще, при нестабильном напряжении питания методика, когда вы сначала меряете напряжение VCC по внутреннему опорному, а потом внешнее по VCC - будет по определению давать крайне неточные результаты.
Эту проблему лучше решать аппаратно - берете стабилитрон и заводите его выход на AREF в качестве надежного опорного.
вот почему у меня навернулся замер внешнего напряжения?? что изменилось??
#define F_CPU 16000000UL
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
unsigned int z=0;//переменная для икpементирования
unsigned char x=1;//переменная для функции ISR
unsigned int R1=0,R2=0, R3=0;
unsigned int y=0;//переменная для икpементирования
//unsigned int zzz;
float Uvh;//переменная для записи напряжения
const int Koef=1;//коэффициент
int K1;
unsigned int sec;
//unsigned int sec1;
float Vcc;
float U;
static const float internalRefference = 1.1;//измеренное вольтметром внутреннее опорное напряжение
// Делитель частоты для ADC
static const uint8_t adcPrescaler =(1<<ADPS2) | (1<<ADPS1) | (1<<ADPS0);//устанавливаем частоту дискретизации делитель 128(частота дискретизации 16000000/128=125кГц)
static const uint8_t refAVcc = (1<<REFS0); // AVcc как опорное
static const uint8_t inpVbg = (1<<MUX3) | (1<<MUX2) | (1<<MUX1); // измеряем Vbg (1.1В)
// Включение ADC
static inline void adcEnable(void) {
PRR &= ~(1<<PRADC);//пишем нуль в нулевой бит регистра, отвечающего за обесточивание компонентов МК, чтобы исключить выключение ацп
ADCSRA |= (1<<ADEN);//включаем ацп
//ADCSRB|=(0<<ADTS2)|(0<<ADTS1)|(0<<ADTS0);//включаем режим постоянного измерения
}
//
// Замер напряжения питания
//
float getAVccVoltage(void) {
adcEnable();
ADMUX = refAVcc | inpVbg; // Измеряем Vbg, используя AVcc как опорное
ADCSRA |= adcPrescaler | (1<<ADSC); // Запускаем преобразование
while(ADCSRA & (1<<ADSC)); // Ждём завершения преобразования
return internalRefference * 1023 / ADC; // Считаем AVcc
}
/*замер внешнего напряжения*/
float voltage_ext(void){
adcEnable();
ADCSRA|=adcPrescaler;//делитель 128(частота дискретизации 16000000/128=125кГц)
ADMUX|=refAVcc;//источник опорного напряжения 5 вольт
ADMUX|=(0<<MUX3)|(1<<MUX2)|(0<<MUX1)|(0<<MUX0);//включаем ADC4 0100
ADMUX|=(0<<ADLAR);//выравнивание
ADCSRA|=(1<<ADSC);//запускаем работу ацп
while(ADCSRA & (1<<ADSC)); // Ждём завершения преобразования
return ADC*5.00/1024;// напряжение в вольтах
}
unsigned int digits[10]=
{
~0b00111111,//0
~0b00000110,//1
~0b01011011,//2
~0b01001111,//3
~0b01100110,//4
~0b01101101,//5
~0b01111101,//6
~0b00000111,//7
~0b01111111,//8
~0b01101111,};//9
/*настраиваем таймер-счетчик 0*/
void init_TC0(void){
TCCR0A|=(0<<WGM00)|(0<<WGM01);//режим normal(сброс по переполнению)
TCCR0B |=(1<<CS02)|(0<<CS01)|(0<<CS00);//делитель 256
TIMSK0|=(1<<TOIE0);//сброс по переполнению
TIFR0|=(1<<TOV0);
TCNT0=0;
}
/*настраиваем порты*/
void init_ports(void){
DDRC|=(1<<PC0)|(1<<PC1)|(1<<PC2);//аноды семисегментника
DDRC&=~(1<<PC4);//adc4
//DDRB|=(1<<PB0)|(1<<PB2)|(1<<PB4);//leds
//DDRB&=~(1<<PB5);//button
DDRD=0xFF;//весь порт Д на выход(катоды семисегментника)
//PORTB|=(0<<PB0)|(0<<PB2)|(0<<PB4)|(1<<PB5);//leds&&button
PORTC|=(1<<PC0)|(1<<PC1)|(1<<PC2)|(1<<PC4);
PORTD =0xFF;//логическая единица на порту Д,чтобы семисегментник не светился
}
/*обрабатываем прерывания при переполнении счетчика*/
ISR(TIMER0_OVF_vect){
if(x==1){PORTC=0b00000100;PORTD=digits[R1];} //при первом прерывании на порту С включаем третий бит, в порт д выводим число, высчитанное в функции vse_chislo
if(x==2){PORTC=0b00000010;PORTD=digits[R2];if(Uvh>=10){PORTD&=~(1<<PD7);}
else {PORTD&=~(0<<PD7);}}
if(x==3){PORTC=0b00000001;PORTD=digits[R3];if(Uvh<10){PORTD&=~(1<<PD7);}
else{PORTD&=~(0<<PD7);}}
x++;
if(x>3){x=1;};
}
void number(unsigned int part_of_number){
R1=part_of_number%10; //единицы
R2=part_of_number%100/10;//десятки
R3=part_of_number/100;}//сотни
int main(void){
init_ports();
init_TC0();
sei();
while(1){
//выводим на семисегментник напряжение, измеряемое на 4ом пине ацп
if (TCNT0==255)sec++;
if(sec==100){Uvh=voltage_ext();sec=0;}//записываем в переменную значения ацп по таймеру
if(Uvh<10)
{
K1=100;
}
else
{K1=10;
}
number(Uvh*K1); //вывод в вольтах
}
}
Наверное, потому, что в посте #50 Вы просто не измеряете его. Вы же просто выбросили все вызовы функции getAVccVoltage и не вызываете её нигде ни разу. И как же она Вам змерять-то будет?
вообще, при нестабильном напряжении питания методика, когда вы сначала меряете напряжение VCC по внутреннему опорному, а потом внешнее по VCC - будет по определению давать крайне неточные результаты.
Эту проблему лучше решать аппаратно - берете стабилитрон и заводите его выход на AREF в качестве надежного опорного.
Спасибо за подсказку.
Просто у меня задача не сварганить некий вольтметр, а ликбез.
Я тут сушу вам мозг не затем, чтобы заиметь вольтметр, а затем, чтобы познать новое)
вот почему у меня навернулся замер внешнего напряжения?? что изменилось??
#define F_CPU 16000000UL
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
unsigned int z=0;//переменная для икpементирования
unsigned char x=1;//переменная для функции ISR
unsigned int R1=0,R2=0, R3=0;
unsigned int y=0;//переменная для икpементирования
//unsigned int zzz;
float Uvh;//переменная для записи напряжения
const int Koef=1;//коэффициент
int K1;
unsigned int sec;
//unsigned int sec1;
float Vcc;
float U;
static const float internalRefference = 1.1;//измеренное вольтметром внутреннее опорное напряжение
// Делитель частоты для ADC
static const uint8_t adcPrescaler =(1<<ADPS2) | (1<<ADPS1) | (1<<ADPS0);//устанавливаем частоту дискретизации делитель 128(частота дискретизации 16000000/128=125кГц)
static const uint8_t refAVcc = (1<<REFS0); // AVcc как опорное
static const uint8_t inpVbg = (1<<MUX3) | (1<<MUX2) | (1<<MUX1); // измеряем Vbg (1.1В)
// Включение ADC
static inline void adcEnable(void) {
PRR &= ~(1<<PRADC);//пишем нуль в нулевой бит регистра, отвечающего за обесточивание компонентов МК, чтобы исключить выключение ацп
ADCSRA |= (1<<ADEN);//включаем ацп
//ADCSRB|=(0<<ADTS2)|(0<<ADTS1)|(0<<ADTS0);//включаем режим постоянного измерения
}
//
// Замер напряжения питания
//
float getAVccVoltage(void) {
adcEnable();
ADMUX = refAVcc | inpVbg; // Измеряем Vbg, используя AVcc как опорное
ADCSRA |= adcPrescaler | (1<<ADSC); // Запускаем преобразование
while(ADCSRA & (1<<ADSC)); // Ждём завершения преобразования
return internalRefference * 1023 / ADC; // Считаем AVcc
}
/*замер внешнего напряжения*/
float voltage_ext(void){
adcEnable();
ADCSRA|=adcPrescaler;//делитель 128(частота дискретизации 16000000/128=125кГц)
ADMUX|=refAVcc;//источник опорного напряжения 5 вольт
ADMUX|=(0<<MUX3)|(1<<MUX2)|(0<<MUX1)|(0<<MUX0);//включаем ADC4 0100
ADMUX|=(0<<ADLAR);//выравнивание
ADCSRA|=(1<<ADSC);//запускаем работу ацп
while(ADCSRA & (1<<ADSC)); // Ждём завершения преобразования
return ADC*5.00/1024;// напряжение в вольтах
}
unsigned int digits[10]=
{
~0b00111111,//0
~0b00000110,//1
~0b01011011,//2
~0b01001111,//3
~0b01100110,//4
~0b01101101,//5
~0b01111101,//6
~0b00000111,//7
~0b01111111,//8
~0b01101111,};//9
/*настраиваем таймер-счетчик 0*/
void init_TC0(void){
TCCR0A|=(0<<WGM00)|(0<<WGM01);//режим normal(сброс по переполнению)
TCCR0B |=(1<<CS02)|(0<<CS01)|(0<<CS00);//делитель 256
TIMSK0|=(1<<TOIE0);//сброс по переполнению
TIFR0|=(1<<TOV0);
TCNT0=0;
}
/*настраиваем порты*/
void init_ports(void){
DDRC|=(1<<PC0)|(1<<PC1)|(1<<PC2);//аноды семисегментника
DDRC&=~(1<<PC4);//adc4
//DDRB|=(1<<PB0)|(1<<PB2)|(1<<PB4);//leds
//DDRB&=~(1<<PB5);//button
DDRD=0xFF;//весь порт Д на выход(катоды семисегментника)
//PORTB|=(0<<PB0)|(0<<PB2)|(0<<PB4)|(1<<PB5);//leds&&button
PORTC|=(1<<PC0)|(1<<PC1)|(1<<PC2)|(1<<PC4);
PORTD =0xFF;//логическая единица на порту Д,чтобы семисегментник не светился
}
/*обрабатываем прерывания при переполнении счетчика*/
ISR(TIMER0_OVF_vect){
if(x==1){PORTC=0b00000100;PORTD=digits[R1];} //при первом прерывании на порту С включаем третий бит, в порт д выводим число, высчитанное в функции vse_chislo
if(x==2){PORTC=0b00000010;PORTD=digits[R2];if(Uvh>=10){PORTD&=~(1<<PD7);}
else {PORTD&=~(0<<PD7);}}
if(x==3){PORTC=0b00000001;PORTD=digits[R3];if(Uvh<10){PORTD&=~(1<<PD7);}
else{PORTD&=~(0<<PD7);}}
x++;
if(x>3){x=1;};
}
void number(unsigned int part_of_number){
R1=part_of_number%10; //единицы
R2=part_of_number%100/10;//десятки
R3=part_of_number/100;}//сотни
int main(void){
init_ports();
init_TC0();
sei();
while(1){
//выводим на семисегментник напряжение, измеряемое на 4ом пине ацп
if (TCNT0==255)sec++;
if(sec==100){Uvh=voltage_ext();sec=0;}//записываем в переменную значения ацп по таймеру
if(Uvh<10)
{
K1=100;
}
else
{K1=10;
}
number(Uvh*K1); //вывод в вольтах
}
}
Наверное, потому, что в посте #50 Вы просто не измеряете его. Вы же просто выбросили все вызовы функции getAVccVoltage и не вызываете её нигде ни разу. И как же она Вам змерять-то будет?
непосредственно тут я хотел измерять некое внешнее напряжение. Ну да ладно, домой пришел, все завелось. Хз, что за ерунда была.
Просто у меня задача не сварганить некий вольтметр, а ликбез.
Я тут сушу вам мозг не затем, чтобы заиметь вольтметр, а затем, чтобы познать новое)
я вам уже несколько раз писал - вам книжки надо читать. А вы вместо этого пытаетесь программировать бездумным подбором операторов. Никакой пользы от этого вам не будет - через неделю все забудете, как и не знали.
Вообще, я просто хотел использовать измеренное в фуннкции getAVccVoltage напряжение питания при расчете замеряемого напряжения на четвертом пине ацп.
вообще, при нестабильном напряжении питания методика, когда вы сначала меряете напряжение VCC по внутреннему опорному, а потом внешнее по VCC - будет по определению давать крайне неточные результаты.
Эту проблему лучше решать аппаратно - берете стабилитрон и заводите его выход на AREF в качестве надежного опорного.
Вроде как не стабилитрон полагается, а специальный источник опорного напряжения.
вообще, я не понимаю, почему вся программа ломается, если поэкспериментировать в каком-либо месте, а затем вернуть все на свои места?
Потому, что Вы её не понимаете.
вот почему у меня навернулся замер внешнего напряжения?? что изменилось??
Наверное, потому, что в посте #50 Вы просто не измеряете его. Вы же просто выбросили все вызовы функции getAVccVoltage и не вызываете её нигде ни разу. И как же она Вам змерять-то будет?
вообще, при нестабильном напряжении питания методика, когда вы сначала меряете напряжение VCC по внутреннему опорному, а потом внешнее по VCC - будет по определению давать крайне неточные результаты.
Эту проблему лучше решать аппаратно - берете стабилитрон и заводите его выход на AREF в качестве надежного опорного.
Спасибо за подсказку.
Просто у меня задача не сварганить некий вольтметр, а ликбез.
Я тут сушу вам мозг не затем, чтобы заиметь вольтметр, а затем, чтобы познать новое)
Потому, что Вы её не понимаете.
Это очень бы хотелось исправить)
вот почему у меня навернулся замер внешнего напряжения?? что изменилось??
Наверное, потому, что в посте #50 Вы просто не измеряете его. Вы же просто выбросили все вызовы функции getAVccVoltage и не вызываете её нигде ни разу. И как же она Вам змерять-то будет?
непосредственно тут я хотел измерять некое внешнее напряжение. Ну да ладно, домой пришел, все завелось. Хз, что за ерунда была.
Просто у меня задача не сварганить некий вольтметр, а ликбез.
Я тут сушу вам мозг не затем, чтобы заиметь вольтметр, а затем, чтобы познать новое)
я вам уже несколько раз писал - вам книжки надо читать. А вы вместо этого пытаетесь программировать бездумным подбором операторов. Никакой пользы от этого вам не будет - через неделю все забудете, как и не знали.
Все верно. Так и сделаю. Пойду читать программистскую библию.