// // Created by vlad on 17.08.22. // #include "platform.h" #include "config.h" #include #include static char systick_flag; uint16_t sensor_1; uint16_t sensor_2; ISR(TIMER1_OVF_vect) { systick_flag = 1; // LED2_Toggle(); } void platform_init() { // инициализация GPIO DDRD = INIT_DDRD; DDRB = INIT_DDRB; DIDR = 0x03; // отключение цифрового ввода/вывода на входах компаратора // инициализация юарта uart_init(); // инициализация таймера 1 (16-ти битный) systick_flag = 0; // mode=14 (FastPWM, top in ICR1), x64, ICR1=1000000/64=15625 TCCR1B = (1 << WGM13) | (1 << WGM12); TCCR1A = (1 << WGM11); // выставляем TOP ICR1 = (uint16_t)(F_CPU / 64); // разрешаем прерывание по переполнению TIMSK |= (1 << TOV1); TCCR1B |= (1 << CS11) | (1 << CS10); // выставляем x64, то есть запускаем таймер sei(); } void platform_wait_for_interrupt() { // для режима сна Idle нужно отрубить компаратор (в даташите просили) // в других режимах сна он отрубается автоматически char acsr = ACSR; ACSR |= (1 << ACD); // чтобы отрубить компаратор нужно записать 1 в этот бит MCUCR |= (1 << SE); asm volatile ("sleep"); MCUCR &= ~(1 << SE); // восстанавливаем состояние компаратора ACSR |= acsr; } void systick_sync() { systick_flag = 0; // можно не запрещать прерывания: операция атомарна for(;;) { cli(); char flag = systick_flag; if (flag) { systick_flag = 0; } // else { // platform_wait_for_interrupt(); // } sei(); if (flag) { return; } } } void uart_init() { // U2X=1, baud=9600, error=0.2%, f=1M UBRRH = 0; UBRRL = 12; UCSRA = (1 << U2X); UCSRB = (1 << TXEN) | (1 << RXEN); } void uart_deinit() { UCSRB = 0; // снимаем RXEN и TXEN } void uart_write_char(char c) { while ((UCSRA & (1 << UDRE)) == 0) ; UDR = c; } void uart_write_str(const char* str) { while (1) { char c = *(str++); if (c == '\0') { break; } uart_write_char(c); } } void uart_write_fstr(PGM_P str) { while (1) { char c = pgm_read_byte(str++); if (c == '\0') { break; } uart_write_char(c); } } char uart_read_char() { while (!(UCSRA & (1 << RXC))) ; return UDR; } void uart_discard_input() { while (UCSRA & (1 << RXC)) { char __attribute__((__unused__)) _tmp = UDR; } } void platform_read_sensors() { EXTPWR_EN_Set(); systick_sync(); sensor_1 = 0; sensor_2 = 0; uint8_t states = FRQ_Gpio & (FRQ1_Pin | FRQ2_Pin); for(;;) { uint8_t tmp = FRQ_Gpio; if ((tmp & FRQ1_Pin) != (states & FRQ1_Pin)) { states = (states & (~FRQ1_Pin)) | tmp; sensor_1++; } if ((tmp & FRQ2_Pin) != (states & FRQ2_Pin)) { states = (states & (~FRQ2_Pin)) | tmp; sensor_2++; } cli(); char flag = systick_flag; if (flag) { systick_flag = 0; } sei(); if (flag) { break; } } EXTPWR_EN_Reset(); // быстрое деление на 2 (считалось каждое изменение) sensor_2 >>= 1; sensor_1 >>= 1; }