запускаем протеус и рисуем схему:
или собираем такую-же на макетке.
запускаем кодеВижен, запускаем мастер выбираем чип и его частоту, я поставил 9,6МГц и деление на 8 (частота по умолчанию)
потом настраиваем порты порт со светодиодом - на выход, порт с переменником на вход без подтяжки, остальные - вход с подтяжкой.
далее настраиваем АЦП:
цифры: (следует учитывать, что это не только настройка тини, но и написание предварительного кода)
1 - включение самого блока АЦП
2 - вызвать прерывание по завершению оцифровки
3 - 8битная точность (как она достигается я писал несколькими постами выше)
4 - дописывает в функцию получения значения АЦП остановку процессора тиньки чтоб снизить наводки на блок АЦП
5 - выбор опорного напряжения (если стоит - встроенная опора 1,1в, если нет - внешнее питание)
6 - тактирование (КВАвр сам посчитает делитель) д.ш. рекомендует 50-200кГц
7 - режим запуска преобразования (выбранный режим означает перезапуск АЦП сразу после завершения оцифровки)
(режим "ADC stopped" - означает, что преобразование каждый раз нужно запускать вручную, я бы его назвал "однократный режим")
8 - если включить, то после каждого преобразования АЦП переключается на следующий вход покругу (диапазон входов задается) это чисто софтовая примочка т.е. сам АЦП этого не умеет.
9 - отключение соответствующей ноги от дискретного порта (если поставить галочку, то ни подтяжку ни сигнал в/из порта уже не получить - защитит от ошибочного переключения порта и искажения напряжения на ноге). галочку можно поставить в окошке "1".
_____________
генерируем код, сохраняем и получаем это:
Спойлер
Код: Выделить всё
#include <tiny13a.h>
#include <delay.h>
// Declare your global variables here
// Bandgap Voltage Reference: Off
#define ADC_VREF_TYPE ((0<<REFS0) | (0<<ADLAR))
// ADC interrupt service routine
interrupt [ADC_INT] void adc_isr(void)
{
unsigned int adc_data;
// Read the AD conversion result
adc_data=ADCW;
// Place your code here
}
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=Out Bit3=In Bit2=In Bit1=In Bit0=In
DDRB=(0<<DDB5) | (1<<DDB4) | (0<<DDB3) | (0<<DDB2) | (0<<DDB1) | (0<<DDB0);
// State: Bit5=P Bit4=0 Bit3=P Bit2=T Bit1=P Bit0=P
PORTB=(1<<PORTB5) | (0<<PORTB4) | (1<<PORTB3) | (0<<PORTB2) | (1<<PORTB1) | (1<<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 0 Interrupt(s) initialization
TIMSK0=(0<<OCIE0B) | (0<<OCIE0A) | (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);
// 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);
// Digital input buffer on AIN0: On
// Digital input buffer on AIN1: On
DIDR0=(0<<AIN0D) | (0<<AIN1D);
// ADC initialization
// ADC Clock frequency: 150,000 kHz
// ADC Bandgap Voltage Reference: Off
// ADC Auto Trigger Source: Free Running
// Digital input buffers on ADC0: On, ADC1: On, ADC2: On, ADC3: On
DIDR0|=(0<<ADC0D) | (0<<ADC2D) | (0<<ADC3D) | (0<<ADC1D);
ADMUX=ADC_VREF_TYPE;
ADCSRA=(1<<ADEN) | (0<<ADSC) | (1<<ADATE) | (0<<ADIF) | (1<<ADIE) | (0<<ADPS2) | (1<<ADPS1) | (1<<ADPS0);
ADCSRB=(0<<ADTS2) | (0<<ADTS1) | (0<<ADTS0);
// Globally enable interrupts
#asm("sei")
while (1)
{
// Place your code here
}
}
Спойлер
Код: Выделить всё
while (1)
{
// Place your code here
if (adc_data>512) {PORTB|=(1<<4);}else{PORTB&=~(1<<4);};
}
}я сделал переменную глобальной.
компилирую - компиляция проходит, но не работает...
вспоминаю, что про вход у нас ничего не спрашивали, наверно включен вход 0, а нам нужен 1
лезем в д.ш.: в регистре ADMUX есть соседствующие биты MUX0 и MUX1, которые отвечают за выбор входа
Спойлер
ADMUX=ADC_VREF_TYPE | (inputADC<<MUX0);
и если надо менять вход - создадим переменную, если не надо - задефайним inputADC присвоив ей требуемое значение (в нашем случае 1).
компилим, запускаем - не работает! конечно, после завершения оцифровки АЦП перезапустится, но первый раз его нужно завести вручную
допишем перед главным циклом:
// Start the AD conversion
ADCSRA|=(1<<ADSC);
(вместо этого можно 0 на 1 поменять в соответствующем месте настройки - результат будет тот-же)
компилим - теперь работает!
вот весь полученный код:
Спойлер
Код: Выделить всё
#include <tiny13a.h>
#include <delay.h>
// Declare your global variables here
unsigned int adc_data;
// Bandgap Voltage Reference: Off
#define ADC_VREF_TYPE ((0<<REFS0) | (0<<ADLAR))
//выбор входа
#define inputADC 1
// ADC interrupt service routine
interrupt [ADC_INT] void adc_isr(void)
{
// Read the AD conversion result
adc_data=ADCW;
// Place your code here
}
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=Out Bit3=In Bit2=In Bit1=In Bit0=In
DDRB=(0<<DDB5) | (1<<DDB4) | (0<<DDB3) | (0<<DDB2) | (0<<DDB1) | (0<<DDB0);
// State: Bit5=P Bit4=0 Bit3=P Bit2=T Bit1=P Bit0=P
PORTB=(1<<PORTB5) | (0<<PORTB4) | (1<<PORTB3) | (0<<PORTB2) | (1<<PORTB1) | (1<<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 0 Interrupt(s) initialization
TIMSK0=(0<<OCIE0B) | (0<<OCIE0A) | (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);
// 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);
// Digital input buffer on AIN0: On
// Digital input buffer on AIN1: On
DIDR0=(0<<AIN0D) | (0<<AIN1D);
// ADC initialization
// ADC Clock frequency: 150,000 kHz
// ADC Bandgap Voltage Reference: Off
// ADC Auto Trigger Source: Free Running
// Digital input buffers on ADC0: On, ADC1: On, ADC2: On, ADC3: On
DIDR0|=(0<<ADC0D) | (0<<ADC2D) | (0<<ADC3D) | (0<<ADC1D);
ADMUX=ADC_VREF_TYPE | (inputADC<<MUX0);
ADCSRA=(1<<ADEN) | (0<<ADSC) | (1<<ADATE) | (0<<ADIF) | (1<<ADIE) | (0<<ADPS2) | (1<<ADPS1) | (1<<ADPS0);
ADCSRB=(0<<ADTS2) | (0<<ADTS1) | (0<<ADTS0);
// Globally enable interrupts
#asm("sei")
// Start the AD conversion
ADCSRA|=(1<<ADSC);
while (1)
{
// Place your code here
if (adc_data>512) {PORTB|=(1<<4);}else{PORTB&=~(1<<4);};
}
}
ПС: сейчас у меня стоит кодевижен версии 3.42. возможно в другой версии настройка АЦП удобнее...