KEROL писал(а):
Пингвин, не скромничай, выкладывай свой алгоритм, у тебя он хоть какой-то есть... вот его и обсудим... добавим, убавим, исправим, дополним...
Как я тебя понял у тебя прием осуществляется так:
0. Ждемс прерывание... елаем все остальные вещи...
1. Уходим по спаду от ТСОП в прерывание...
2. В прерывании врубаем счетчик, включаем прерывание подъему...
3. Ждемс прерывание... делаем все остальные вещи...
4. Уходим по подъему от ТСОП в прерывание...
5. В прерывании включаем прерывание по спаду, "проверяем значение счетчика"... обнуляем его и включаем его (счетчик)...
В "проверяем значение счетчика":
0. Значение = 2400, 1200, 600 +-10%???
ДА - заполняем биты приема... 2 или 3 шт плюс Хидер (3-й бит проверка, как у ЛВ)
или, если пришла "пауза"=600, например, где-нить фиксируем, что пришла пауза...
НЕТ - обнуляем биты приема, отправляем звук "Пули летят над головой"
1. Биты заполнены?
ДА - анализ полного пакета, соответствующие действия...
НЕТ - уходим из прерывания для приема следущего бита/паузы...
Так я не понял - о каком алгоритме идет речь?
Тот, который в этой ветке обсуждаем - пока не реализованный (во всяком случае я не реализовывал), или тот, который в "Аскете" работает?
Так описывал уже вроде.
Крутиться главный цикл, который проверяет поочерёдно переменные-события.
Все события генерируются прерываниями.
Главный цикл при наступлении какого-либо события выполняет соответствующую функцию - обработчик события.
А в остальном - почти все правильно описали.
Только окончание приема фиксируется по тайм-ауту и в прерываниях функций-обработчиков событий нет, только фиксируется событие - "пакет принят" или "ошибка приема".
На самом деле не так просто все описать, как оказалось!
Это же не линейный алгоритм, а событийный автомат получается.
Код куда проще и понятней выглядит.
Вот код (извиняюсь за "портянку") - тут события генерируются, давайте обсудим - что не понятно?
Код:
#include "ltag_ascetic.h"
#include "milshot_snd.h"
//#include "joystick_driver.h"
//#include "hitraw.h"
/**************************************************************************************
* Обработчик прерываний таймера 2 (72 КГц)
***************************************************************************************/
ISR(TIMER2_COMP_vect){
timer1++;
volatile uint8_t prt;
prt = TSOP_IN&TSOP_PIN;
if (prt==0) //На ножке ИК-приемника низкий уровень сигнала (пойман сигнал несущей)
{
low_level_counter++;//Увеличиваем счетчик длительности низкоуровнего сигнала на ножке ИК-приемника
if (chit_detected_counter < (IR_ZERO*1000)) chit_detected_counter++;
if (chit_detected_counter >= (IR_ZERO*1000)) chit_detected=true;
}
else //На ножке ИК-приемника высокий уровень сигнала (нет сигнала несущей)
{
chit_detected_counter = 0;
if (chit_detected) chit_detected=false;
high_level_counter++;///Увеличиваем счетчик длительности высокоуровнего сигнала на ножке ИК-приемника
if((start_bit_received)&&(high_level_counter > IR_ZERO*8))
{//Фиксируем окончание приема по таймауту
start_bit_received = false; //отменяем прием
rx_event = RX_COMPLETE; //Генерим событие "принят пакет"
}
}
if (ir_transmitter_on==true)
{//Если передача разрешена
if (ir_pulse_counter > 0) //необходимая длительность пачки импульсов
{ //ещё не достигнута, "мигаем" дальше
IR_LED_INVERT; //необходимая длительность пачки
ir_pulse_counter--;
}
else //пачка импульсов была отправлена,
{
IR_LED_OFF; //тушим ИК-диод
if ( ir_space_counter > 0) //проверим, выдержан ли промежуток между импульсами
{ //нет, промежуток не выдержан
IR_LED_OFF; //тушим ИК-диод
ir_space_counter--; //уменьшаем обратный счетчик паузы на один "тик"
}
else //Пакет импульсов и промежуток между битами переданы
{ //нужно формировать следующую пачку (передаваемый бит)
if (data_packet.data[cursor_position]!=0) //если указатель указывает не на пустую ячейку
{
ir_pulse_counter =data_packet.data[cursor_position++] ; //передадим импульс указанной длительностью
ir_space_counter = IR_SPACE; //и про паузу не забудем
}
else //Все данные переданы (элемент, на который ссылается указатель, равен 0)
{
ir_transmitter_on=false; //выключаем передатчик
FIRE_LED_OFF;
display_bullets_update_now++;
}
}
}
}
else {//Если передача запрещена
}
}
/**************************************************************************************
* Обработчик внещних прерываний вывода INT0 (выход TSOPа)
***************************************************************************************/
ISR(INT0_vect){
if(!(MCUCR&_BV(ISC00))) //если прерывание вызвано спадом
{
MCUCR |=_BV(ISC00); //следующее прерывание будет сгенерировано фронтом
if (start_bit_received)//Если старт-бит принят, то идет прием пакета
{
if((high_level_counter < (IR_SPACE + ERROR_TOLERANCE))&&(high_level_counter > (IR_SPACE - ERROR_TOLERANCE)))//Проверим длительность паузы между битами
{
//длительность паузы между импульсами корректна
}
else //Длительность паузы между приемом битов не корректна
{//Фиксируем ошибку приёма
start_bit_received = false; //отменяем прием
bit_in_rx_buff = 0; //очищаем буфер
rx_event = RX_ERROR; //генерируем событие - "ошибка приёма"
}
}
low_level_counter = 0;//Обнуляем счетчик длительности низкоуровнего сигнала на ножке ИК-приёмника
high_level_counter = 0;//Обнуляем счетчик длительности высокоуровнего сигнала на ножке ИК-приёмника
}
else //прерывание вызвано фронтом
{
MCUCR &=~_BV(ISC00); //следующее прерывание будет сгенерировано спадом
if (start_bit_received)//Если старт-бит принят, то идет прием пакета
{
if((low_level_counter < (IR_ZERO + ERROR_TOLERANCE))&&(low_level_counter > (IR_ZERO - ERROR_TOLERANCE)))//Проверим, соответствует ли длительность пакета нулевому биту
{
set_buffer_bit(bit_in_rx_buff++, false);//Длительность пачки соответствует биту со значением 0, заносим ноль в буфер приема
}
else //Нет, это не бит со значением 0
{
if((low_level_counter < (IR_ONE + ERROR_TOLERANCE))&&(low_level_counter > (IR_ONE - ERROR_TOLERANCE)))//, может это бит со значением 1?
{
set_buffer_bit(bit_in_rx_buff++, true);//Длительность пачки соответствует биту со значением 1, заносим еденицу в буфер приема
}
else //Это ни единица, ни ноль - это помеха
{
start_bit_received = false; //отменяем прием
bit_in_rx_buff = 0; //очищаем буфер
rx_event = RX_ERROR; //генерируем событие - "ошибка приёма"
}
}
}
else //Старт-бит ещё не принят
{
if ((low_level_counter < (IR_START + ERROR_TOLERANCE))&&(low_level_counter > (IR_START - ERROR_TOLERANCE))) //Может это старт-бит?
{//Это старт-бит
bit_in_rx_buff = 0; //очищаем буфер
start_bit_received = true; //разрешаем прием пакетов (бит)
}
else //это не старт-бит, это помеха
{
//Игнорируем
}
}
low_level_counter = 0;//Обнуляем счетчик длительности низкоуровнего сигнала на ножке ИК-приёмника
high_level_counter = 0;//Обнуляем счетчик длительности высокоуровнего сигнала на ножке ИК-приёмника
}
}
Вот, собственно - и вся реализация приема и передачи пакетов...