Задание:
1) При включении кнопки зажигается фонарик на полную мощность (кнопка фиксируемая) - 1 подаем на PB0
2) При полунажатии на кнопку должен переключиться режим, экономящий яркость - 1-ки подаем на PB0 и PB1
3) При повторном полунажатии фонарик должен вернуться в первоначальный режим (вот здесь и есть проблема, пока что всеми попытками переключение только в одну сторону)
4) Раз в минуту контролируется уровень батареи, подключенной к PB4 (он же ADC2), суть в считывании уровней АЦП (эта часть вроде как работает), при достижении определенных уровней, зажигаем синий или красный светодиоды.
Переключение режимов так же смотрится по уровню ADC2, при полунажатии происходит падение уровня, которое должно фиксироваться. Собрано на резистивном делителе с номиналами 30 кОм и 10 кОм. (Схема пинов во вложении)
Код: Выделить всё
#include "main.h" // < All settings are here
#include <util/delay.h>
#include <avr/io.h>
#include <avr/sleep.h>
#include <avr/interrupt.h>
#include <stdbool.h> // bool in C99
// Яркость нагрузки, 0 - выключен, 255 - максимальная (ШИМ)
u8 rate;
// Направление изменения яркости нагрузки, 1 - прибавить ШИМ, 0 - убавить ШИМ
u8 rate_dir = 0;
// Состояние заднего светодиода LED2
bool led_state = false;
int count = 0;
uint8_t countMode = 0; //????? ?????????? ??????
uint8_t reqChangeMode = 0; //????, ???????????? ????? ????????? ???????? ?????
volatile _Bool direction = 0; // Направление бегущего огонька
u16 x;
void bat_check_low(void) {
u8 adc_raw = bat_getvoltage();
if (adc_raw < BAT_WARNING_BLUE) {
while (adc_raw < BAT_WARNING_BLUE) {
PORTB = 0b00000111;
}
}
if (adc_raw < BAT_WARNING_RED)
{
PORTB = 0b00001011;
}
if (adc_raw > BAT_WARNING_BLUE)
{
PORTB = 0b00001111;
}
if (adc_raw < BAT_SHUTDOWN)
PORTB = 0b00001100;
}
ISR( TIM0_COMPA_vect)
{
}
void knopka_check(void) {
// Проверка заряда батареи
u8 adc_knopki = bat_getvoltage();
u16 bat_time_low = 0;
if (adc_knopki < 150)
{
while (adc_knopki < 150)
{
count++;
if ((count < 250)&&(count > 30))
{
direction = !direction; // Меняем направление
PORTB = 0b00001111;
count = 0;
#ifdef BAT_CHECK_LOW
if (bat_time_low == BAT_CHECK_PERIOD) { // Проверка заряда батареи через определенный интервал
bat_time_low = 0;
bat_check_low();
}
bat_time_low++;
#endif
_delay_ms(1);
}
}
}
}
int main(void) {
setup();
sei ();
u16 bat_time = 0;
while(1) {
knopka_check();
#ifdef BAT_CHECK
if (bat_time == BAT_CHECK_PERIOD) {
bat_time = 0;
bat_check();
}
bat_time++;
#endif
_delay_ms(1);
}
}
ISR(INT0_vect) {}
ISR(ADC_vect) {}
void setup(void){
ADMUX =
(1 << ADLAR) | (1 << REFS0) | (1 << MUX1) | (0 << MUX0);
ACSR |= (1 << ACD);
ADCSRA = (1 << ADIE);
TCCR0B = (0 << CS02) | (1 << CS01) | (0 << CS00 );
TCCR0A = (0 << WGM02) | (1 << WGM01) | (0 << WGM00);
OCR0A = 69;
TCNT0 = 0;
TIMSK0|=(1<<OCIE0A)|(0<<TOIE0);
DDRB = 0b00001111;
PORTB = 0b00001101;
wakeup();
}
void wakeup(void) {
if (led_state)
LED_RED_on
#ifndef RATE_REMEMBER // Если нет памяти яркости
rate = RATE_DEFAULT; // включается сразу на мин. яркость
#endif
OCR0A = rate;
ADCSRA |= (1 << ADPS1) | (1 << ADPS0) | (1 << ADEN) ;
ADCSRA |= (1 << ADSC);
}
u8 bat_getvoltage(void) {
_delay_us(50);
ADCSRA |= (1 << ADSC);
while (ADCSRA & (1 << ADSC));
return ADCH;
}
void bat_check(void) {
u8 adc_raw = bat_getvoltage();
if (adc_raw < BAT_WARNING_BLUE) {
while (adc_raw < BAT_WARNING_BLUE) {
PORTB = 0b00000101;
}
}
if (adc_raw < BAT_WARNING_RED)
{
PORTB = 0b00001001;
}
if (adc_raw < BAT_SHUTDOWN)
PORTB = 0b00001100;
if (adc_raw > BAT_WARNING_BLUE)
{
PORTB = 0b00001101;
}
}
- Вложения
-
- Безымянный.jpg
- (52.76 КБ) 266 скачиваний





