Pingvin писал(а):
hexFF писал(а):
не успевает прерывание отработать, тут гадать не надо. компилятор на прерывание минимум 70-80 тактов хоронит, на сохранение и восстановление РОН. на ассемблере- самое оно, тактов 25-30 вместе с уходом на вектор и возвратом.
А помочь сможете?
Я в AVR-овском ассемблере ни бум-бум...
Как то же ещё значения из переменных в регистры передать надо.
Вот, собственно, код прерывания
Код:
/**************************************************************************************
* Обработчик прерываний таймера
***************************************************************************************/
ISR(TIMER2_COMP_vect){
static volatile uint8_t prt;
prt = TSOP_IN&TSOP_PIN;
if (prt==0) //На ножке ИК-приемника низкий уровень сигнала (пойман сигнал несущей)
{
low_level_counter++;//Увеличиваем счетчик длительности низкоуровнего сигнала на ножке ИК-приемника
}
else //На ножке ИК-приемника высокий уровень сигнала (пойман сигнал несущей)
{
high_level_counter++;///Увеличиваем счетчик длительности высокоуровнего сигнала на ножке ИК-приемника
if((start_bit_received)&&(high_level_counter > IR_ZERO*8))
{//Фиксируем окончание приема по таймауту
start_bit_received = false; //отменяем прием
rx_event = RX_COMPLETE; //Генерим событие "принят пакет"
receiver_on = false;//выключаем приемник
if (ir_transmitter_on==false) TIMSK &=~_BV(OCIE2); //если передача не ведётся - выключаем прерывания
}
if((high_level_counter > IR_ZERO*8)&&(ir_transmitter_on==false))
{
receiver_on = false;//выключаем приемник
TIMSK &=~_BV(OCIE2);
}
}
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++;
// если
if (!receiver_on) //если нет приема пакета
{
TIMSK &=~_BV(OCIE2); // Запрещаем прерывания по захвату/сравнению
}
}
}
}
}
else {//Если передача запрещена
}
}
по коду едва ли, в Си я не бум-бум совершенно, но алгоритмом помогу. Так понял, что у вас ножка ИК- диода по прерыванию инвертируется. Думал над этим вариантом, выбрал другой подход. По порядку:
у меня процессор ATmega328 (выбрал из-за маленького корпуса и 32 кб флеш- памяти- её больше половины уйдет на бинарники звуков), такт 8 МГц.
алгоритм передачи "пули":
таймер 1 настраивается в режим СТС по значению в OCR1A (подбираем так, чтоб прерывание выскакивало каждые 17,7 мкс - для частоты несущей 56 килогерц), в OCR1B закидываем значение OCR1A деленное на 2. Оба прерывания (по совпадению OCR1A и OCR1B) разрешаем.
теперь самое интересное - обработчики.
по совпадению OCR1B самый простой- только одно действие- выставить неактивный уровень на ножке ИК- светодиода.
по совпадению OCR1А- тут вывод пачек импульсов- смотрим что нужно выводить, если нужно- выставляем высокий уровень на ножке, нет- не трогаем её.
на ассемблере летает на ура, на Си не знаю, пойдет ли- там компилятор есть...
таймер 2 будет для вывода звука, таймер 0- для приема пуль и как системный таймер.
Спасибо, но проблема решена в рамках существующего алгоритма- проблема была в математике!
Значение "количество тиков таймера" для СТАРТ-БИТА просто не влазило в переменную типа uint8_t - было больше, чем 255.
Пришлось поменять тип переменной на uint16_t.
Ну облегчил обработчик передающий - прием пакета перенес в другое прерывание частотой 8 КГц.
/**************************************************************************************
* Обработчик прерываний таймера
***************************************************************************************/
ISR(TIMER2_COMP_vect){
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_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++;
TIMSK &=~_BV(OCIE2); // Запрещаем прерывания по захвату/сравнению
}
}
}
}
else {//Если передача запрещена
}
}
Жду не дождусь реальных тестов с оборудованием LW.