Имею проблемы с 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();
}
}
}
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();
}
}
}