/
baxneo
/
test3
Обзор
Документация
Войти
/
baxneo
/
test3
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
master
src/system.h
175 строк
7 KB
Viktor Leontev
1_50_1
16 сен 2025, 23:18
16 сен 2025, 23:18
1e90660
Код
Авторство
О чём код?
#pragma once #include <avr/interrupt.h> #include <avr/io.h> #include <stdint.h> volatile unsigned long t0_millis_my = 0; // счетчик миллисекунд volatile unsigned int t0_second_my = 0; // счетчик 1000 миллисекунд (1 сек) volatile bool second_flag = false; // флаг секунды volatile unsigned long t0_second_usr = 0; // счетчик секунд пользователя volatile bool second_flag_usr = false; // флаг включения/отключения счета секунд пользователя volatile uint8_t ina_mc = 0; volatile bool ina_flag = false; // флаг 2мс - отдельный флаг для считывания данных с INA226 и работы функции ШИМ (DCDC) контроллера void timer0_init(void); //void timer1_init(void); //void timer2_init(void); unsigned long millis_my(); unsigned long micros_my(); void secondReset(void); unsigned long get_second_usr(void); void start_second_usr(void); void Timer0_outputPin6(bool state); // включить/отключить вывод сигнала 500 Гц пин 6 // Таймер 0 в режиме CTC (Count-to-Compare), генерирует прерывание каждые 1 мс inline void timer0_init() { cli(); #if F_CPU >= 32000000 TCCR0B = _BV(CS02); // Установим предделитель 256 TCCR0A = _BV(WGM01); // Режим CTC, сравнение OCR0A (Output Compare Register A) // Значение OCR0A рассчитывается для интервала примерно 1 мс при частоте CPU 32 MHz OCR0A = 124; // Подобранное значение для 1 мс TIMSK0 = _BV(OCIE0A); // Разрешаем прерывание при совпадении значения OCR0A #elif F_CPU >= 16000000 TCCR0B = (_BV(CS01) | _BV(CS00)); // Выбираем предделитель 64 TCCR0A = _BV(WGM01); // Режим CTC, сравнение OCR0A (Output Compare Register A) // Установим значение сравнения OCR0A для интервала примерно 1 мс при частоте CPU 16 MHz OCR0A = 249; // Formula: (F_CPU / prescaler * desired frequency) - 1 TIMSK0 = _BV(OCIE0A); // Разрешаем прерывание при совпадении значения OCR0A #else #error "CPU frequency not supported" #endif sei(); } // Прерывание Timer0 (обработчик события) ISR(TIMER0_COMPA_vect) { // код обработки события (каждую 1 мс) t0_millis_my++; // счет миллисекунд // отсчет 1 секунды if (++t0_second_my >= 1000) { t0_second_my = 0; second_flag = true; // флаг 1 секунды if (second_flag_usr) t0_second_usr++; // счет секунд } // отдельный флаг для считывания данных с INA226 и работы функции ШИМ (DCDC) контроллера if (!ina_flag) { if (++ina_mc >= 2) { ina_mc = 0; ina_flag = true; } } } unsigned long millis_my(void) { unsigned long m; uint8_t oldSREG = SREG; cli(); m = t0_millis_my; SREG = oldSREG; return m; } unsigned long micros_my() { uint8_t oldSREG = SREG; // запомнинаем были ли включены прерывания cli(); // выключаем прерывания unsigned long m = t0_millis_my; // счет переполнений uint8_t t = TCNT0; // считать содержимое счетного регистра if ((TIFR0 & _BV(TOV0)) && (t < 255)) // инкремент по переполнению m++; SREG = oldSREG; // если прерывания не были включены - не включаем и наоборот return (long)(((m << 8) + t) * (uint8_t)(64 / (F_CPU / 1000000L))); // вернуть микросекунды } // сброс счетчика секунд void secondReset(void) { uint8_t oldSREG = SREG; cli(); t0_second_my = 0; second_flag = false; SREG = oldSREG; sei(); } unsigned long get_second_usr(void) { unsigned long m; uint8_t oldSREG = SREG; cli(); m = t0_second_usr; SREG = oldSREG; return m; } void start_second_usr(void) { cli(); second_flag_usr = true; t0_second_usr = 0; sei(); } void Timer0_outputPin6(bool state) { if (state) TCCR0A |= (1 << COM0A0); // включить вывод сигнала 500 Гц else TCCR0A &= ~(1 << COM0A0); // отключить вывод сигнала 500 Гц } /* // Таймер 1 в режиме FastPWM, с частотой около 30 Гц inline void timer1_init() { #if F_CPU >= 32000000 // Предделитель 1024, WGM13=WGM12=1, режим FastPWM (Mode 14) TCCR1B = (_BV(WGM13) | _BV(WGM12)) | _BV(CS12) | _BV(CS10); TCCR1A = _BV(WGM11) | _BV(COM1A1); // Подключаем выход PWM на OC1A (пин 9 Arduino) // Регулируемое значение для частоты около 30 Гц OCR1A = 10666; // Чуть меньше 30 Гц при 32 МГц и предделителе 1024 #elif F_CPU >= 16000000 // Предделитель 1024, WGM13=WGM12=1, режим FastPWM (Mode 14) TCCR1B = (_BV(WGM13) | _BV(WGM12)) | _BV(CS12) | _BV(CS10); TCCR1A = _BV(WGM11) | _BV(COM1A1); // Подключаем выход PWM на OC1A (pin 9 Arduino) // Устанавливаем коэффициент заполнения (пример 50%) OCR1A = 32000; // Для частоты 30 Гц #else #error "CPU frequency not supported" #endif } // Таймер 2 в режиме Phase-correct PWM (~30 кГц) inline void timer2_init() { #if F_CPU >= 32000000 // Режим Phase-correct PWM, предделитель 8 TCCR2A = _BV(WGM20) | _BV(COM2A1); // Режим 2 (Phase-correct PWM), выходной сигнал на OC2A (Arduino Пин 3) TCCR2B = _BV(CS21); // Прескалер = 8 // Оставляем прежнее значение для выхода на 30 кГц OCR2A = 51; // Расчёт аналогичен предыдущему варианту #elif F_CPU >= 16000000 // Режим Phase-correct PWM, предделитель 8 TCCR2A = _BV(WGM20) | _BV(COM2A1); // Mode 2 (Phase-correct PWM), Output on pin OC2A (Arduino Pin 3) TCCR2B = _BV(CS21); // Prescaler = 8 // Частота примерно 30 кГц OCR2A = 51; // Freq calculation based on formula #else #error "CPU frequency not supported" #endif } */ /* #if F_CPU >= 32000000 #elif F_CPU >= 16000000 #else #error "CPU frequency not supported" #endif */ /* bool secondGet(void) { bool flag; uint8_t oldSREG = SREG; cli(); flag = second_flag; second_flag = false; SREG = oldSREG; return flag; } */