реклама на сайте
подробности

 
 
> Работа с АЦП в TINY13, Нужны примеры на С
Bogila Anton
сообщение Aug 10 2009, 14:38
Сообщение #1


Участник
*

Группа: Участник
Сообщений: 15
Регистрация: 4-09-07
Из: Kiev
Пользователь №: 30 288



Сабж, а конкретнее: есть VСС=4.90V, подаю на вход АЦП (PORTB.2) через делитель от 0 до 4900mV согласно правилам. Нужен пример где идет постоянное измерение напряжения, и в результате чтоб была конечная переменная со значением в mV. Не понятно: какой Vref, и какие типы данных следует применять. Супер-мега точность не нужна.
В CodeVision выставляю вот это (на картинке).
Куски кода которые относятся к АЦП:

//9000mV on Batt = 4900mV on ADC (4900*1.84 = 9016mV) kv = 1.84

#define ADC_VREF_TYPE 0x00 //(что значит эта строка?)
#define VREF 4900 //mV (не знаю нодо ли это, или как правильно?)

unsigned int VCC, kv=1.84; //(какой тип данных следует применять?)

// Read the AD conversion result
unsigned int read_adc(unsigned char adc_input)
{
ADMUX=adc_input | (ADC_VREF_TYPE & 0xff);
// Delay needed for the stabilization of the ADC input voltage
delay_us(10);
// Start the AD conversion
ADCSRA|=0x40;
// Wait for the AD conversion to complete
while ((ADCSRA & 0x10)==0);
ADCSRA|=0x10;
return ADCW;
}

void BATT_VCC () { //vichislenie BATT_VCC (mV)
VCC = read_adc(1); // VСС = 0-1024, 1 - nomer kanala ADC
VCC = VCC*VREF/1024;
VCC = VCC*kv; //(VСС mV)
}

BATT_VCC ();

Это правильно?

Сообщение отредактировал Bogila Anton - Aug 10 2009, 14:40
Эскизы прикрепленных изображений
Прикрепленное изображение
 
Go to the top of the page
 
+Quote Post
 
Start new topic
Ответов
Bogila Anton
сообщение Aug 12 2009, 10:14
Сообщение #2


Участник
*

Группа: Участник
Сообщений: 15
Регистрация: 4-09-07
Из: Kiev
Пользователь №: 30 288



Спасибо, вычесления понятны
/* VСС - ?mV
ADC=1023 ---> 9000mV
k=9000mV/ADC=9000/1023=8.797
VCC=ADC*k
Чтобы не сильно потерять в точности при целочисленной арифметике,
подбираем K таким, чтобы дробная часть была как можно меньше,
и чтобы MAX(ADC) * K уложилось в unsigned short диапазон.
k=k*4=8.797*4=35.188
k=35
VCC=ADC*(35/4)
*/
и в теории все сходится, а на практике у меня не очень. Хочу уточнить результат ADC это 0-1023 ведь?
Вот такой код у меня как пример работы вышел, может что-то где-то не так?
А выходит следующие, я указал значение 6100mV и при реальных 6100 +/- там, сходится в теории и в реале, теперь пишу в коде 6000 а срабатывает гораздо ниже где-то на 5000mV. Делитель вроде верный 3300 Ohm к + и 3980 Ohm к земле.

/*****************************************************
Port Definition
PB0 = OUT (0) (PWM)
PB1 = IN (Pull Up) (Switch)
PB2 = IN (ADC)
PB3 = OUT (1) (RED)
PB4 = IN
PB5 = IN
******************************************************
Hard info
Vmax on Batt = 9000mV
V on ATTINY13 = 4900mV
Vmax on ADC = 4900mV
******************************************************
Chip type : ATtiny13
AVR Core Clock frequency: 9,600000 MHz
Memory model : Tiny
External RAM size : 0
Data Stack size : 16
*****************************************************/

#include <tiny13.h>
#include <delay.h>

#define ADC_VREF_TYPE 0x00

unsigned int ADC, power_good;
unsigned short VCC;


void RED_ON (void) {PORTB.3=0;}
void RED_OFF (void) {PORTB.3=1;}

// External Interrupt 0 service routine
interrupt [EXT_INT0] void ext_int0_isr(void)
{

}

// Read the AD conversion result
unsigned int read_adc(unsigned char adc_input)
{
ADMUX=adc_input | (ADC_VREF_TYPE & 0xff);
// Delay needed for the stabilization of the ADC input voltage
delay_us(10);
// Start the AD conversion
ADCSRA|=0x40;
// Wait for the AD conversion to complete
while ((ADCSRA & 0x10)==0);
ADCSRA|=0x10;
return ADCW;
}


void BATT_VCC () {
ADC = read_adc(1); // 1 - ADC channel
/* VСС - ?mV
ADC=1023 ---> 9000mV
k=9000mV/ADC=9000/1023=8.797
VCC=ADC*k
Чтобы не сильно потерять в точности при целочисленной арифметике,
подбираем K таким, чтобы дробная часть была как можно меньше,
и чтобы MAX(ADC) * K уложилось в unsigned short диапазон.
k=k*4=8.797*4=35.188
k=35
VCC=ADC*35/4
*/
VCC=ADC*(35/4);
}


// Declare your global variables here

void main(void)
{
// Declare your local variables here

// Crystal Oscillator division factor: 1
#pragma optsize-
CLKPR=0x80;
CLKPR=0x00;
#ifdef _OPTIMIZE_SIZE_
#pragma optsize+
#endif

// Input/Output Ports initialization
// Port B initialization
// Func5=In Func4=In Func3=Out Func2=In Func1=In Func0=Out
// State5=T State4=T State3=1 State2=T State1=P State0=0
PORTB=0x0A;
DDRB=0x09;

// Timer/Counter 0 initialization
// Clock source: System Clock
// Clock value: 9600,000 kHz
// Mode: Phase correct PWM top=FFh
// OC0A output: Non-Inverted PWM
// OC0B output: Disconnected
TCCR0A=0x81;
TCCR0B=0x01;
TCNT0=0x00;
OCR0A=0x00;
OCR0B=0x00;

// External Interrupt(s) initialization
// INT0: On
// INT0 Mode: Low level
// Interrupt on any change on pins PCINT0-5: Off
GIMSK=0x40;
MCUCR=0x00;
GIFR=0x40;

// Timer/Counter 0 Interrupt(s) initialization
TIMSK0=0x00;

// Analog Comparator initialization
// Analog Comparator: Off
ACSR=0x80;
ADCSRB=0x00;

// ADC initialization
// ADC Clock frequency: 75,000 kHz
// ADC Bandgap Voltage Reference: Off
// ADC Auto Trigger Source: None
// Digital input buffers on ADC0: Off, ADC1: Off, ADC2: On, ADC3: Off
DIDR0&=0x03;
DIDR0|=0x2C;
//ADMUX=ADC_VREF_TYPE & 0xff; // dafault generated by CVAVR
ADMUX=1|(ADC_VREF_TYPE & 0xff);
ADCSRA=0x87;


// Global enable interrupts
#asm("sei")

BATT_VCC ();

while (1)
{

// power_good chek begin
BATT_VCC ();
if (VCC>6100) { //mV
delay_ms(100);
if (VCC>6100) {
power_good=0;
};
}
else {
power_good=1;
};

// power_good chek end

if (power_good==0) {
RED_ON ();
}
else {
RED_OFF ();
};

};
}

Сообщение отредактировал Bogila Anton - Aug 12 2009, 10:24
Go to the top of the page
 
+Quote Post



Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 21st July 2025 - 15:06
Рейтинг@Mail.ru


Страница сгенерированна за 0.01383 секунд с 7
ELECTRONIX ©2004-2016