/*
* GccApplication2.cpp
*
* Created: 20.04.2023 14:42:21
* Author : BTS-5662-1
*/
#include <avr/io.h>
#include <avr/interrupt.h>
#define F_CPU 8000000
#define IRQs_FOR_DUTY_CHANGE 20
uint8_t irq_counter = 0; // Counter of IRQs for changing PWM duty
int main(void)
{
CCP = 0xD8; // можем редактировать CLKMSR, CLKPSR, WDTCSR
CLKPSR = 0x00; // предделитель ядра 1
DDRA|=(1<<DDRA5);
// Настройка работы АЦП
ADCSRA=(1 << ADEN)|(1 << ADPS2)|(1 << ADIE); // разрешение использования АЦП, делитель АЦП 1:16, разрешение прерывания по завершению цикла преобразования
ADMUX=(1 << MUX1)|(1 << MUX0)|(0 << REFS1)|(0 << REFS0); // текущий канал АЦП PA[6], ИОН - напряжение питания
ADCSRB|=(1 << ADLAR);// выравнивание по левому краю
// Настройка работы таймера
TCCR0A|=(1 << COM0B1)|(1 << COM0B0)|(1 << WGM00); // инверсный ШИМ сброс при обнулении, установка при совпадении
TCCR0B|=(1 << CS01) |(1 << CS00); // предделитель таймера 64
TIMSK0|=(1 << TOIE0);
GTCCR = (1 << REMAP);
//ICR0=1023; // TOP, чтоб f=122 Гц, (8*10^6)/(64*1*(1+1023))=122
//TIMSK0|=(1<<TOIE0); // разрешение прерывания по переполнению таймера
sei(); // глобальное разрешение прерываний
while(1)
{
// Вся работа идет в прерываниях
}
}
//Обработчик прерывания по переполнению таймера
ISR(TIM0_OVF_vect)
{
irq_counter++;
// Раз в 20 прерываний запускаем единичное АЦП-преобразование
if (irq_counter == IRQs_FOR_DUTY_CHANGE)
{
irq_counter = 0; // Reset the counter
ADCSRA|=(1 << ADSC); // единичное АЦП-преобразование
}
}
//Обработчик прерывания по завершению АЦП преобразования
ISR(ADC_vect)
{
OCR0B = ADCH; // считываем значения с обоих регистров
}
2я прога:
#include <avr/io.h>
#include <avr/interrupt.h>
#define F_CPU 8000000
#define USART_BAUDRATE 9600 // скорость передачи данных
#define BAUD_PRESCALE ((F_CPU / (USART_BAUDRATE * 16))-1)
#define ADC_FS 5
int main(void)
{
CCP = 0xD8; // можем редактировать CLKMSR, CLKPSR, WDTCSR
CLKPSR = 0x00; // предделитель ядра 1
// Настройка режима работы UART
UCSRC|=(1 << UCSZ1)|(1 << UCSZ0)|(1 << USBS); // 8-битная посылка, 1 стоп-бит
//UCSRC|=(0 << UPM1)|(0 << UPM0) по умолчанию и так нули - без проверки на четность
UBRRH=(BAUD_PRESCALE >> 8); // скорость передачи данных - запихиваем BAUD_PRESCALE
UBRRL=BAUD_PRESCALE;
UCSRB|=(1 << TXEN)|(1 << RXEN); // разрешение передачи данных, разрешение приема данных
// Настройка работы АЦП
ADCSRA|=(1 << ADEN)|(1 << ADPS2)|(1 << ADIE); // разрешение использования АЦП, делитель АЦП 1:16, разрешение прерывания по завершению цикла преобразования
ADMUX|=(1 << MUX1)|(1 << MUX0)|(0 << REFS1)|(0 << REFS0); // текущий канал АЦП PA[6], ИОН - напряжение питания
ADCSRA|=(1 << ADATE);// выравнивание по левому краю => автозапуск АЦП-преобразования, тк в ADTS[2:0] - 000
ADCSRB|=(1 << ADLAR);// выравнивание по левому краю (нам нужен ADCH)
// Настройка работы таймера
TCCR0B|= (1 << WGM02)|(1 << CS02); // режим СТС, предделитель таймера 256
TCCR0A|= (1 << COM0A0); // переключение при совпадении
OCR0A=(F_CPU/(2*ADC_FS*256)-1); // TOP, f=5 Гц, ADC_FS=(F_CPU)/(2*256*1*(1+TOP))
TIMSK0|=(1<<OCIE0A); // разрешение прерывания по совпадению
sei(); // глобальное разрешение прерываний
while(1)
{
// Вся работа идет в прерываниях
}
}
//Обработчик прерывания по завершению АЦП преобразования
ISR(ADC_vect)
{
uint16_t analogReading = ADCL | (ADCH << 8); // Сохраняем результат в переменной analogReading (всё!)
UDR = (analogReading >> 8); // Посылаем только старшие биты по UART
//while (!(UCSRA & (1 << UDRE))) {}
}