Сб дек 01, 2012 07:48:39
#include <avr/io.h> // инициализация портов ввода-вывода МК
#include <avr/wdt.h> // здесь организована работа с ватчдогом
#include <avr/sleep.h> // здесь описаны режимы сна
#include <avr/interrupt.h> // работа с прерываниями
#include <avr/delay.h> // описание программных задержек
// Обработчик прерываний
ISR (WDT_vect)
{
WDTCR |=_BV(WDE); // разрешаем прерывания по ватчдогу, иначе будет резет!
}
// Основная программа
int main()
{
// Инициализация порта кнопки (PB3)
DDRB &=~_BV(PB3); // ставит в DDRB в бит PB3 - "0" (инициирует его работу как "вход")
PORTB |= _BV(PB3); // ставит в PORTB в бит PB3 - "1" (при замыкании пина на землю она становится нулем, при размыкании - еденицей)
// Условие включения светодиода по нажатию кнопки
if((PINB & (1 << PB3)) == 0)
{
// Иницализация порта светодиода (PB4)
DDRB |= _BV(PB4); // Указатель пина
PORTB |= _BV(PB4); // Выставить на PB4 - "1"
_delay_ms (4000); // Задержка
PORTB &= ~_BV(PB4); // Выставить на PB4 - "0"
// Инициализация цикла контроля ложного включения светодиода
while ((PINB & (1 << PB3)) == 0)
{ // пока кнопка нажата (после завершения цикла включения светодиода)...
PORTB &= ~_BV(PB4); // ...светодиод не горит (до отключения, и последующего включения кнопки)
}
};
// Инициализация ватчдога
wdt_reset(); // сброс
wdt_enable(WDTO_120MS); // разрешение ватчдога раз в 120мс
WDTCR |= _BV(WDE); // разрешение прерываний по ватчдогу (иначе будет резет)!
sei(); // разрешение прерывания
// Инициализация режима сна
set_sleep_mode (SLEEP_MODE_PWR_DOWN);
while(1)
{
sleep_enable(); // разрешение режима сна
sleep_cpu(); // активация режима сна
}
}
Сб дек 01, 2012 11:32:49
Сб дек 01, 2012 11:44:23
Сб дек 01, 2012 12:05:44
ibiza11 писал(а):а кнопку будут держать дольше 4 секунд или не обязательно?
Сб дек 01, 2012 12:12:30
LedOn();
delay_ms(4000);
LedOff();
while(1);
Сб дек 01, 2012 12:57:35
ibiza11 писал(а):тогда вообще зачем здесь микроконтроллер?)))
LedOn();
delay_ms(4000);
LedOff();
while(1);
Сб дек 01, 2012 13:06:00
то можно аналогично кнопкой рулить питанием тиньки13
Сб дек 01, 2012 13:46:36
Сб дек 01, 2012 17:52:36
Вс дек 02, 2012 09:11:10
#include <avr/io.h> // инициализация портов ввода-вывода МК
#include <avr/sleep.h> // здесь описаны режимы сна
#include <avr/interrupt.h> // работа с прерываниями
#include <avr/delay.h> // описание программных задержек
// Обработчик прерываний
SIGNAL(SIG_INTERRUPT0) // Прерывание по низкому уровню на PB1
{
PORTB |= _BV(PB4); // Выставить на PB4 - "1"
_delay_ms (4000); // Задержка
PORTB &= ~_BV(PB4); // Выставить на PB4 - "0"
while ((PINB & (1 << PB1)) == 0)
{
}
}
// Основная программа
int main()
{
// PORTB &= ~_BV(PB4); // Выставить на PB4 - "0"
// DDRB |= _BV(PB4); // Указатель пина
PORTB = 0b11101111; // Выставить на PB4 - "0"
DDRB = 0b00010000; // Указатель пина
// Инициализация прерываний по INT0
GIMSK = 0b01000000; // Разрешение прерываний INT0 на входе PB1
MCUCR = 0b00000000; // при перепаде низком уровне на PB1
sei(); // Общее разрешение прерываний
// Инициализация режима сна
set_sleep_mode (SLEEP_MODE_PWR_DOWN);
while(1)
{
sleep_enable(); // разрешение режима сна
sleep_cpu(); // активация режима сна
}
}
// PORTB &= ~_BV(PB4); // Выставить на PB4 - "0"
// DDRB |= _BV(PB4); // Указатель пина
Вс дек 02, 2012 10:01:37
volatile uint8_t have_int0 = FALSE;
volatile uint8_t goto_sleep = FALSE;
// Обработчик прерываний INT0
SIGNAL(SIG_INTERRUPT0) // Прерывание по низкому уровню на PB1
{
PORTB |= _BV(PB4); // Выставить на PB4 - "1"
disable_int0(); //отключить INT0 IRQ, обязательно иначе тутже сюда залетим снова
enable_timer1(); //включить таймер на 4 сек
have_int0 = TRUE;//флаг было прерывание, можно пойти в IDLE
}
// Обработчик прерываний TIM1
interrupt TIMER1_OVF_IRQ // 4 сек прошло - залетели сюда
{
PORTB &= ~_BV(PB4); // Выставить на PB4 - "0"
disable_timer1();// отключить TIM1
enable_int0(); // включить прерывание по низкому уровню
goto_sleep = TRUE; //теперь можно полностью отключиться
}
// Основная программа
int main()
{
device_init();//настройка портов и периферии
while(1)
{
if( have_int0 == TRUE )
{
have_int0 = FALSE;
sleep_idle();//усыпить в IDLE чтоб меньше жрало, но периферия работает
};
if( goto_sleep == TRUE )
{
goto_sleep = FALSE;
sleep_power_down();//теперь все совсем отключено
};
}
}
Вс дек 02, 2012 13:21:29
Вс дек 02, 2012 18:46:21
Пн дек 03, 2012 16:19:10
Сб янв 06, 2018 20:45:27
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include <avr/io.h>
#include <avr/sleep.h>
#include <avr/eeprom.h>
#include "I2C.h"
void tea5767SetFreq(unsigned int);
#define MAX_STATIONS 32
#define FM_FREQ_MIN 870
#define FM_FREQ_MAX 1075
unsigned char vars = 0b0000;//save, next, -, +
EEMEM unsigned int stations[MAX_STATIONS] = { 1007, 1045, 1016, 924, 979, 1000, 1037, 877, 1064, 952, 1068, 997, 976, 894, 1025, 964, 945, 995, FM_FREQ_MIN, FM_FREQ_MIN, FM_FREQ_MIN, FM_FREQ_MIN, FM_FREQ_MIN, FM_FREQ_MIN, FM_FREQ_MIN, FM_FREQ_MIN, FM_FREQ_MIN, FM_FREQ_MIN, FM_FREQ_MIN, FM_FREQ_MIN, FM_FREQ_MIN, FM_FREQ_MIN };
unsigned char divider = 0;
unsigned char currentStation = 0;
unsigned int freq = 0;
ISR (TIM0_COMPA_vect) //~20Hz
{
if (++divider >= 5) //~4Hz
{
if (!(PINB & (1 << 5))) vars |= 1; //+
if (!(PINB & (1 << 3))) vars |= 1 << 1; //-
if (!(PINB & (1 << 4))) vars |= 1 << 2; else vars &= ~(1 << 2); //next
if (!(PINB & (1 << 1))) vars |= 1 << 3; else vars &= ~(1 << 3); //save
divider = 0;
}
}
int main(void)
{
if (freq == 0)
freq = eeprom_read_word(&stations[currentStation]);
CLKPR = 0x00;
// Input/Output Ports initialization
// Port B initialization
// Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In
// State5=P State4=P State3=P State2=T State1=P State0=T
DDRB = 0b000000;
PORTB = 0b111010;
// Timer/Counter 0 initialization
// Clock source: System Clock
// Clock value: 4,688 kHz
// Mode: CTC top=OCR0A
// OC0A output: Disconnected
// OC0B output: Disconnected
TCCR0A = 0x02;
TCCR0B = 0x05;
TCNT0 = 0x00;
OCR0A = 0xea;
OCR0B = 0x00;
// Timer/Counter 0 Interrupt(s) initialization
TIMSK0 = 0x04;
set_sleep_mode(SLEEP_MODE_IDLE);
asm volatile("sei");
/* Replace with your application code */
while (1)
{
if (vars & 1) //+
{
if (++freq >= FM_FREQ_MAX) freq = FM_FREQ_MIN;
tea5767SetFreq(freq);
vars &= ~1;
}
if (vars & (1 << 1)) //-
{
if (--freq <= FM_FREQ_MIN) freq = FM_FREQ_MAX;
tea5767SetFreq(freq);
vars &= ~(1 << 1);
}
if (vars & (1 << 2)) //next
{
currentStation = (currentStation < MAX_STATIONS) ? (currentStation - 1 > 0 && eeprom_read_word(&stations[currentStation]) == eeprom_read_word(&stations[currentStation - 1])) ? 0 : currentStation + 1 : 0;
freq = eeprom_read_word(&stations[currentStation]);
tea5767SetFreq(freq);
while (vars & (1 << 2)) _delay_us(30);
}
if (vars & (1 << 3)) //save
{
eeprom_update_word(&stations[currentStation], freq);
while (vars & (1 << 3)) _delay_us(30);
}
sleep_enable();
sleep_cpu();
}
}
void tea5767SetFreq(unsigned int freq)
{
unsigned int div = ((unsigned long)freq * 12500 + 28125) >> 10; // /1024
unsigned char var1 = (div >> 8) & 0x3F;
asm volatile ("cli");
i2c_start(0xC0);
i2c_write(var1);
i2c_write(div & 0xff);
i2c_write(0b00001010);
i2c_write(0b00011110);
i2c_write(0);
i2c_stop();
asm volatile ("sei");
}