MAL4X Научно-технический форум разработчиков симуляторов и автоматики


Симуляторы перегрузок. DIY электроника. ЭВМ. Компьютерные сети.
Up

Attiny85 и АЦП

Техническая поддержка нахаляву, но не оперативная.

Модераторы: Death_Morozz, FELiS, null

Attiny85 и АЦП

Сообщение thor_nsk » 17 ноя 2016, 13:29

Приветствую всех. Кодеры, надеюсь на вашу помощь.
Имею проблемы с ADC на Tiny85, а точнее не могу заставить работать. ADC проходит только раз при включении (либо это "помехи" включения МК) и все, больше значения не меняются. Игрался с делителем ADC, ручным и автозапуском ничего не получилось. Код на С прилагаю. Если кому не трудно, гляньте пожалуйста. Коротко о программе. Надо включить питание сенсора, провести АЦП, сверить полученные данные с эталоном и если все "плохо", то включить помпу на полив цветов. Затем уснуть на 24часа. Проснуться и повторить программу сначала. Все получается кроме "провести АЦП".
Опорное напряжение (выставил в регистрах) берется с ноги питания. Нулевой пин порта В (по даташиту там Aref) сконфигурирован на выход, на нем висит светодиод. Теоретически не должно мешать. По началу грешил на энергосбережение и на функции пробуждения, думал не все включается. Поэтому для пробы сделал отдельный проект, просто АЦП в цикле. Еще была проблема мониторинга числа получаемого после АЦП. Единственный быстрый вариант смог сделать на светодиодной матрице с max 7219. Я на нее в двоичном коде выводил старший и младший байт результата АЦП. Та же песня, после подачи питания что-то появляется в регистре АЦП и потом не меняется. Либо не стартует начало преобразования, либо не срабатывает прерывание по окончанию АЦП. Что я делаю не так? :(
Движок сайта не позволил подцепить текстовый файл как вложение поэтому код под спойлером.
Скрытый текст
/*******************************************************
Chip type : ATtiny85
AVR Core Clock frequency: 1,000000 MHz
Memory model : Small
External RAM size : 0
Data Stack size : 128
не смог запустить АЦП :(
*******************************************************/
#include <delay.h>
#include <tiny85.h>
#include <sleep.h>

#define led_pin PORTB0 // сигнал "я жду"
#define sensor_on PORTB1 // включение питания сенсора
#define sensor PORTB3 // данные сенсора
#define motor_on PORTB2 // помпа

#define NextTime 1 // сколько интервалов (8сек + мигание светиком) ждать 24часа=10732

// Voltage Reference: AVCC pin
// Выбран вход PB3
#define ADC_VREF_TYPE ((0<<REFS1) | (0<<REFS0) | (0<<REFS2) | (0<<ADLAR) | (0<<MUX3) | (0<<MUX2) | (1<<MUX1) | (1<<MUX0))

unsigned int kw;
unsigned int adc_data;

// ADC interrupt service routine
interrupt [ADC_INT] void adc_isr(void)
{
// Read the AD conversion result
adc_data=ADCW;

}

// Watchdog timeout interrupt service routine
interrupt [WDT] void wdt_timeout_isr(void)
{
sleep_disable();
}

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

// Crystal Oscillator division factor: 8
#pragma optsize-
CLKPR=(1<<CLKPCE);
CLKPR=(0<<CLKPCE) | (0<<CLKPS3) | (0<<CLKPS2) | (1<<CLKPS1) | (1<<CLKPS0);
#ifdef _OPTIMIZE_SIZE_
#pragma optsize+
#endif

// Input/Output Ports initialization
// Port B initialization
// Function: Bit5=In Bit4=In Bit3=In Bit2=Out Bit1=Out Bit0=Out
DDRB=(0<<DDB5) | (0<<DDB4) | (0<<DDB3) | (1<<DDB2) | (1<<DDB1) | (1<<DDB0);
// State: Bit5=T Bit4=T Bit3=T Bit2=0 Bit1=0 Bit0=0
PORTB=(0<<PORTB5) | (0<<PORTB4) | (0<<PORTB3) | (0<<PORTB2) | (0<<PORTB1) | (0<<PORTB0);

// Timer/Counter 0 initialization
// Clock source: System Clock
// Clock value: Timer 0 Stopped
// Mode: Normal top=0xFF
// OC0A output: Disconnected
// OC0B output: Disconnected
TCCR0A=(0<<COM0A1) | (0<<COM0A0) | (0<<COM0B1) | (0<<COM0B0) | (0<<WGM01) | (0<<WGM00);
TCCR0B=(0<<WGM02) | (0<<CS02) | (0<<CS01) | (0<<CS00);
TCNT0=0x00;
OCR0A=0x00;
OCR0B=0x00;

// Timer/Counter 1 initialization
// Clock source: System Clock
// Clock value: Timer1 Stopped
// Mode: Normal top=0xFF
// OC1A output: Disconnected
// OC1B output: Disconnected
// Timer1 Overflow Interrupt: Off
// Compare A Match Interrupt: Off
// Compare B Match Interrupt: Off
PLLCSR=(0<<PCKE) | (0<<PLLE) | (0<<PLOCK);

TCCR1=(0<<CTC1) | (0<<PWM1A) | (0<<COM1A1) | (0<<COM1A0) | (0<<CS13) | (0<<CS12) | (0<<CS11) | (0<<CS10);
GTCCR=(0<<TSM) | (0<<PWM1B) | (0<<COM1B1) | (0<<COM1B0) | (0<<PSR1) | (0<<PSR0);
TCNT1=0x00;
OCR1A=0x00;
OCR1B=0x00;
OCR1C=0x00;

// Timer(s)/Counter(s) Interrupt(s) initialization
TIMSK=(0<<OCIE1A) | (0<<OCIE1B) | (0<<OCIE0A) | (0<<OCIE0B) | (0<<TOIE1) | (0<<TOIE0);

// External Interrupt(s) initialization
// INT0: Off
// Interrupt on any change on pins PCINT0-5: Off
GIMSK=(0<<INT0) | (0<<PCIE);
MCUCR=(0<<ISC01) | (0<<ISC00);

// USI initialization
// Mode: Disabled
// Clock source: Register & Counter=no clk.
// USI Counter Overflow Interrupt: Off
USICR=(0<<USISIE) | (0<<USIOIE) | (0<<USIWM1) | (0<<USIWM0) | (0<<USICS1) | (0<<USICS0) | (0<<USICLK) | (0<<USITC);

// Analog Comparator initialization
// Analog Comparator: Off
// The Analog Comparator's positive input is
// connected to the AIN0 pin
// The Analog Comparator's negative input is
// connected to the AIN1 pin
ACSR=(1<<ACD) | (0<<ACBG) | (0<<ACO) | (0<<ACI) | (0<<ACIE) | (0<<ACIS1) | (0<<ACIS0);
ADCSRB=(0<<ACME);
// Digital input buffer on AIN0: On
// Digital input buffer on AIN1: On
DIDR0=(0<<AIN0D) | (0<<AIN1D);

// ADC initialization
// ADC Clock frequency: 125,000 kHz
// ADC Voltage Reference: AVCC pin
// ADC Bipolar Input Mode: Off
// ADC Reverse Input Polarity: Off
// ADC Auto Trigger Source: ADC Stopped
// Digital input buffers on ADC0: Off, ADC1: Off, ADC2: Off, ADC3: On
DIDR0|=(1<<ADC0D) | (1<<ADC2D) | (0<<ADC3D) | (1<<ADC1D);
ADMUX=ADC_VREF_TYPE;
ADCSRA=(1<<ADEN) | (0<<ADSC) | (0<<ADATE) | (0<<ADIF) | (1<<ADIE) | (0<<ADPS2) | (1<<ADPS1) | (1<<ADPS0);
ADCSRB=(0<<BIN) | (0<<IPR) | (0<<ADTS2) | (0<<ADTS1) | (0<<ADTS0);

// Watchdog Timer initialization
// Watchdog Timer Prescaler: OSC/1024k
// Watchdog timeout action: Interrupt
#pragma optsize-
WDTCR=(0<<WDIF) | (0<<WDIE) | (1<<WDP3) | (1<<WDCE) | (0<<WDE) | (0<<WDP2) | (0<<WDP1) | (1<<WDP0);
WDTCR=(1<<WDIF) | (1<<WDIE) | (1<<WDP3) | (0<<WDCE) | (0<<WDE) | (0<<WDP2) | (0<<WDP1) | (1<<WDP0);
#ifdef _OPTIMIZE_SIZE_
#pragma optsize+
#endif

#asm("sei")
PORTB&=~(1<<motor_on);
PORTB&=~(1<<sensor_on);
PORTB&=~(1<<led_pin);

while (1)
{
adc_data=0;
// начать новое АЦ преобразование
PORTB|=(1<<sensor_on); // влючаю питание сенсора
ADCSRA|=0x40;
while (adc_data){} // жду готовности ADC
if (adc_data>0)
{
// земля сухая, надо полить
PORTB|=(1<<motor_on); // включаю помпу
delay_ms(3000);
PORTB&=~(1<<motor_on); // выключаю помпу
}
PORTB&=~(1<<sensor_on); // вылючаю питание сенсора
for (kw=0; kw<NextTime; kw++)
{
PORTB^=(1<<led_pin);
delay_ms(50);
PORTB^=(1<<led_pin);
sleep_enable();
powerdown();
}
}
}
Аватара пользователя
thor_nsk
Комсорг
 
Сообщения: 154
Зарегистрирован: 03 мар 2011, 08:12
Благодарил (а): 0 раз.
Поблагодарили: 1 раз.
Баллы репутации: 0

Re: Attiny85 и АЦП

Сообщение Ale » 18 ноя 2016, 23:34

А зачем ты прерывание для АЦП юзаешь? И вообще, немного странный (для меня) метод ожидания данных от АЦП...

Я, к примеру, не стал бы инициализировать прерывание, а просто ждал бы появления флага ADIF. Вот так, например

Код: Выделить всё
...
// при инициализации НЕ включаем прерывание от АЦП
ADCSRA=(1<<ADEN) | (0<<ADSC) | (0<<ADATE) | (0<<ADIF) | (0<<ADIE) | (0<<ADPS2) | (1<<ADPS1) | (1<<ADPS0);
...
//Дальше в цикле...
   adc_data=0;
   // начать новое АЦ преобразование
   PORTB|=(1<<sensor_on); // влючаю питание сенсора
   ADCSRA|=0x40;
   while (!ADCSRA.ADIF){} // жду готовности ADC
   ADCSRA.ADIF=1; // сбрасываем флаг
   // Read the AD conversion result
   adc_data=ADCW;
   if (adc_data>0)
     {....
Аватара пользователя
Ale
Разработчик
 
Сообщения: 1477
Зарегистрирован: 01 фев 2011, 20:48
Откуда: Дубна
Благодарил (а): 570 раз.
Поблагодарили: 595 раз.
Баллы репутации: 277
ТехнарьТехнарьТехнарь

Re: Attiny85 и АЦП

Сообщение thor_nsk » 21 ноя 2016, 07:03

Ale писал(а):А зачем ты прерывание для АЦП юзаешь? И вообще, немного странный (для меня) метод ожидания данных от АЦП...

Спасибо, что отозвался на зов о помощи :)
Это я уже как мог пытался найти баг. Результат АЦП не изменялся ни разу после старта, в прерывание не попадал. Может я с инициализацией что-то напутал, ноги не так сконфигурировал или физически что-то не подключил? Попробую твою заготовку, может случится чудо...
Аватара пользователя
thor_nsk
Комсорг
 
Сообщения: 154
Зарегистрирован: 03 мар 2011, 08:12
Благодарил (а): 0 раз.
Поблагодарили: 1 раз.
Баллы репутации: 0

Re: Attiny85 и АЦП

Сообщение thor_nsk » 23 ноя 2016, 04:45

Нашел свою ошибку. Не в том порядке читал старший и младший байт результата АЦП. Только не понятно почему у меня не работало при чтении сразу всего результата, а не побайтно. Сейчас всё фурычит. Спасибо :)
Аватара пользователя
thor_nsk
Комсорг
 
Сообщения: 154
Зарегистрирован: 03 мар 2011, 08:12
Благодарил (а): 0 раз.
Поблагодарили: 1 раз.
Баллы репутации: 0


Вернуться в Техподдержка

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 5

cron
x

#{title}

#{text}