Здравствуйте, Давыдов Сергей Владимирович!
Для получения результата не обойтись без прерывания таймера.
Воспользуемся таймером 0. Для которого задаем делитель = 8, т.к.
данный таймер 8-битный и без делителя необходимое значение
просто не поместится в регистр. Можно было использовать 16-битный таймер 1,
но, полагаю, это совершенно не принципиально.
Таймер загружаем таким значением, чтобы он срабатывал каждый полупериод
нашего меандра, т.к. нам необходимо переключать значения порта.
Кроме того, считаем данные прерывания в переменной типа int (2 байта)
Для первой тысячи обнуляем порт, для второй для каждого прерывания меняем значение порта
[code h=200]#include<avr/io.h>
#include<avr/interrupt.h>
#include <avr/iom8.h>
#define F_CPU 1048576L //устанавливаем частоту МК 1МГц
#define TICK_COUNT 65 //(500*F_CPU)/(1000000*8)
//число тиков таймера равно длине полупериода = 500мкс,
//деленной на время тика процессора в мкс (1000000/F_CPU)
//и деленной на делитель таймера (8)
#define TIMER_INIT (256-TICK_COUNT) //таймер растет до переполнения 255->0
#define TIMER_COUNT 2000 //число полупериодов в 1 сек (1000Гц*2)
unsigned char a; //оператор описания переменных а
unsigned char s=0b11001100; //сигнал "s" -событие=204=0ХСС=0b11001100
unsigned char v=0b11100111; //сигнал "v"- авария=231=0ХЕ7=0b1110011
int count; //счетчик полупериодов
int main(void)
{
DDRB= 0b11111111; //инициализация регистра DDR порта В
PORTB=0b00000000; //порт В-все линии выходы с лог. 0
DDRD= 0b00000000; //инициализация регистра DDR порта D
PORTD=0b11111111; //порт D -все линии входы с подтягивающими резисторами.
DDRC= 0b01100000; //инициализация регистра DDR порта С
PORTC=0b10011111; //порт С-все линии порта входы, кроме РС5 и РС6
TCCR0 = 1<<CS01; //делитель clk/8 (1048576/8 = 131072)
//1 тик таймера = 1/131072 = 7,62939453125 мкс
//500 мкс (1 полупериод) = 65,536 * 7,62939453125
TCNT0 = TIMER_INIT; //инициируем счетчик таймера
TIMSK = 1<<TOIE0; //разрешаем прерывания от 0 таймера
count = TIMER_COUNT; //иницируем счетчик полупериодов
sei(); //разрешаем прерывания глобально
while(1){} //пустой основной цикл, вся работа в прерывании
}
SIGNAL (SIG_OVERFLOW0) //прерывание 0 таймера
{
TCNT0 = TIMER_INIT; //инициируем заново счетчик
a = PIND; //читаем код
if (a==v) //авария?
{
PORTC |= _BV(6); //если в порту D авария то на РС6 уст. лог 1
PORTC &= _BV(5); //если в порту D авария то на РС5 уст. лог 0
}
else if (a==s) //событие?
{
PORTC &= ~_BV(6); //на РС6 уст. лог 0
if (--count == 0) //уменьшаем счетчик до 0
count = TIMER_COUNT; //если нуль, то инициируем заново
if (count < (TIMER_COUNT/2))//если первые 0.5 с
PORTC &= ~_BV(5); //то на РС5 уст. лог 0
else if (count & 1) //во второй половине для нечетных
PORTC |= _BV(5); //взводим 1
else //для четных
PORTC &= ~_BV(5); //взводим 0
//т.о., получаем меандр с частотой 1КГц
}
else // если ни одно условие не выполняется то в порт С записываем все лог.0
{
PORTC &= ~_BV(5);
PORTC &= ~_BV(6);
}
}[/code]