Добавлено: Чт июн 04, 2009 09:00:27
Дык а что задумывалось-то? И какие результаты? По Файлам Вашим не сильно ясно. Если работает нестабильно, можно попробовать поиграться значениями "тиков" таймера для распознавания, обычно помогает.
Здесь можно немножко помяукать :)
https://radiokot.ru/forum/
Код: Выделить всё
interrupt [EXT_INT2] void ext_int2_isr(void)
{
PORTC.0 = 1;
TCCR0=0x05;
/*
if(first_int)
{
first_int = 0;
TCNT0 = 0;
start_cond = 0;
repeat_cond = 0;
tick = 0;
x=1;
y=1;
PORTC.0=0;
}
*/
tick = TCNT0;
// типа вывод таймингов
if(ShowTiming)
{
lcd_gotoxy(x, y-1);
sprintf(a2, "%i",tick);
lcd_putstr(a2);
x+=14;
if(x>=84)
{
y+=1;
x=1;
}
if(y>7)
{
y=1;
x=1;
}
}
if (tick >= st_min && tick <st_max>= rp_min && tick <rp_max>= l_min && tick < l_max && start_cond) //если случилось от 22 до 115 тиков
{
++b_cnt; //приняли "1" и увеличили счетчик битов
if (b_cnt < 9) addr_1 = (addr_1 <<1>= 9 && b_cnt < 17) addr_0 = (addr_0 <<1>= 16 && b_cnt < 25) cmd_1 = (cmd_1 <<1>= 24) cmd_0 = (cmd_0 <<1>= s_min && tick < s_max && start_cond) //если случилось от 10 до 21 тика
{
++b_cnt; //приняли "0" и увеличили счетчик битов
if (b_cnt < 9) addr_1 = (addr_1 <<1>= 9 && b_cnt < 17) addr_0 = (addr_0 <<1>= 16 && b_cnt < 25) cmd_1 = (cmd_1 <<1>= 24) cmd_0 = (cmd_0 << 1);
}
TCNT0 = 0; //обнулили тики
if (b_cnt == 32) //если приняли уже 4 байта
{
// if ((addr_1+addr_0) == 0xFF) addr = addr_0; //закомментировано, потому как в пульте First
// else addr = 0; //16-bit адрес 0x6120, т.о. проверка адреса не проходит
if ((cmd_1 + cmd_0) == 0xFF) cmd = cmd_1; //проверили правильность приема команды
else cmd = 0;
b_cnt = 0; //обнулили счетчик битов
start_cond = 0; //сбросили стартовое условие
repeat_cond = 0;
TCCR0=0x00; //остановили таймер
TCNT0=0x00;
first_int = 1;
printf("addr = %i ... cmd = %i \n\r" , addr_1, cmd_1);
x=1;
y=1;
}
PORTC.0 = 0;
}
Код: Выделить всё
eeprom unsigned char l_min = 19; //диапазон для "длинного" (long) интервала в посылке, в "тиках" таймера, 1,28..2,176мс
eeprom unsigned char l_max = 22;
eeprom unsigned char s_min = 2; //диапазон для "короткого" (short) интервала в посылке, в "тиках" таймера, 0,704..1,088мс
eeprom unsigned char s_max = 6;
eeprom unsigned char st_min = 180; //диапазон для "старт" интервала в посылке, в "тиках" таймера, 0,704..1,088мс
eeprom unsigned char st_max = 210;
eeprom unsigned char rp_min = 160; //диапазон для "Повтор" интервала в посылке, в "тиках" таймера, 0,704..1,088мс
eeprom unsigned char rp_max = 170;
Код: Выделить всё
//...остальные хидеры
#include "rc5reciver.h"
...
//инициализация:
PORTD|=(1<<PD3); //подтяжка на приемный пин
/*прерывание инт1 сконфигурировано на любое изменение уровня, но не разрешено */
MCUCR=0x04;
GIFR=0x80;
...
int main(void)
{
//---------Локальные переменные---------//
uchar fl_change=0; //флаг события фронта
uchar fl_begin_ir=0; //флаг начала посылки
uchar time_front=0; //время между фронтами, в тиках таймера
struct ir_code ir_code; //тут храним структуру посылки
//--------------------------------------//
...
for(;;){
//----обработчик переполнения таймера - это можно и в обработчик
//(только без условия). Плюс тогда надо сделать флаг глобальным
if (TIMER0_OVERFLOW){
T0_STOP;
TCNT0=0x00;
fl_begin_ir=0;
reset_rc5();
CLEAR_FL_T0_OVERFLOW;
LED_OFF;
}
//-----------------------------------------------------------
//--------обработчик изменения уровня (можно в обработчик)
if (ANY_CHANGE_INTERRUPT){
uchar tcnt_t0=TCNT0; //чтобы уменьшить погрешность
TCNT0=0x00;
//фиксируем время между фронтами
if(fl_begin_ir)
{
time_front=tcnt_t0;
fl_change=1;
}
else
{
T0_RUN;
time_front=0;
fl_begin_ir=1;
reciever_rc5(&time_front); //здесь функция практически сразу
//завершится после входа в нее
}
CLEAR_FL_T0_OVERFLOW; //на всякий случай очищаем флаг
CLEAR_ANY_CHANGE_INTERRUPT;
}
//---------------------------------------------------------
//---------------------------------------------------------
if(fl_change){//если есть измерение между фронтами
fl_change=0;
switch (reciever_rc5(&time_front))
{
case CONTINUE:
break;
case ERROR:
fl_begin_ir=0;
T0_STOP;
TCNT0 = 0x00;
reset_rc5();
break;
case RC5_CODE:
fl_begin_ir=0;
rc5_parser(&ir_code); //загоняем код в структуру
//используем лежащий в структуре код
printf ("(%d,%d,%d,%d)",ir_code.toogle,
ir_code.device_high,ir_code.device_low,ir_code.command);
reset_rc5();
break;
}
}
//----------------------------------------------------------------------//
}
}
Код: Выделить всё
/*****************************************************
Chip type : ATmega8535
Program type : Application
AVR Core Clock frequency: 4,000000 MHz
Memory model : Small
External RAM size : 0
Data Stack size : 128
*****************************************************/
#include <mega8535.h>
unsigned char cnt_bit = 0; //счетчик принятых бит
unsigned char code [14]; //принятый код
unsigned char counter = 0; //"тики" таймера
#define l_min 40 //диапазон для "длинного" (long) интервала в посылке, в "тиках" таймера, 1,28..2,176мс
#define l_max 68
#define s_min 22 //диапазон для "короткого" (short) интервала в посылке, в "тиках" таймера, 0,704..1,088мс
#define s_max 34
bit state = 0; //флаг состояния линии приема
bit error = 0; //флаг ошибки
//переменные структуры посылки, всего 14 бит
unsigned char startbit1 = 0; //первый стартовый бит, д.б. = 1
unsigned char startbit2 = 0; //второй стартовый бит, д.б. = 1
unsigned char toggle = 0; //триггерный бит, инвертируется в посылке при нажатии кнопки, при удержании - не инв.!
unsigned char address = 0; //адрес устройства, 5 бит
unsigned char command = 0; //команда (данные), 6 бит
unsigned int COUNT;
unsigned char PTR;
unsigned char PTR1;
const unsigned char CODE_TABLE[11] = {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};
void main(void)
{
DDRA =0b11000000;
COUNT=64;
PORTB=0x00;
DDRB=0x00;
PORTC=0x00; // очистим индикатор
PORTD=0x00; // установим нулевой разряд индикатора
DDRC=0xff; // определим PC<0> - PC<7> как выходы
DDRD=0xff; // определим PD<4> - PD<7> как выходы
PORTA=0xff;
// Timer/Counter 0 initialization
// Clock source: System Clock
// Clock value: Timer 0 Stopped
// Mode: Normal top=FFh
// OC0 output: Disconnected
OCR0=0x00;
TIMSK=0b00000101;
TCCR0 = 0b00000011; //останавливаем таймер
TCNT0 = 254;
#asm("sei")
// Timer/Counter 1 initialization
// Clock source: System Clock
// Clock value: Timer1 Stopped
// Mode: Normal top=FFFFh
// OC1A output: Discon.
// OC1B output: Discon.
// Noise Canceler: Off
// Input Capture on Falling Edge
// Timer1 Overflow Interrupt: Off
// Input Capture Interrupt: Off
// Compare A Match Interrupt: Off
// Compare B Match Interrupt: Off
TCCR1A=0x00;
TCCR1B=0x01;
TCNT1H=254;
TCNT1L=254;
ICR1H=0x00;
ICR1L=0x00;
OCR1AH=0x00;
OCR1AL=0x00;
OCR1BH=0x00;
OCR1BL=0x00;
// Timer/Counter 2 initialization
// Clock source: System Clock
// Clock value: Timer2 Stopped
// Mode: Normal top=FFh
// OC2 output: Disconnected
ASSR=0x00;
TCCR2=0x00;
TCNT2=0x00;
OCR2=0x00;
// External Interrupt(s) initialization
// INT0: Off
// INT1: Off
// INT2: Off
MCUCR=0b00000010;
MCUCSR=0x00;
// Timer(s)/Counter(s) Interrupt(s) initialization
TIMSK=0b00000101;
// Analog Comparator initialization
// Analog Comparator: Off
// Analog Comparator Input Capture by Timer/Counter 1: Off
ACSR=0x80;
SFIOR=0x00;
PTR=0;
PTR1=0;
while(1)
{
if (command>0)PTR=1;
}
}
// External Interrupt 0 service routine
interrupt [EXT_INT0] void ext_int0_isr(void)
{
counter = TCNT0; //сохраяем значение таймера-счетчика
TCNT0 = 0x00; //обнуляем таймер
error = 1; //поставили ошибку - потом сбросим в теле, если все ок
if (cnt_bit == 0) //старт посылки
{
TCCR0 = 0x04; //запускаем таймер, частота 31250кГц (или надо править диапазоны тиков для интервалов)
code [cnt_bit] = !PIND.2; //записываем бит кода, PIND.2 - входная нога, прерывание 0
cnt_bit++; //увеличиваем счетчик принятых бит
state = 1; //ставим флаг, т.к. была 1
}
else //в других случаях (не первое срабатывание прерывания)
{
if ((counter>s_min) && (counter<s_max)) //проверка короткого промежутка
{
if (state) //если была 1
{
state = 0; //обнуляем состояние
error = 0; //и ошибку, т.к. все корректно
}
else //если был 0
{
state = 1; //ставим флаг, т.к. теперь - 1
code[cnt_bit] = !PIND.2; //записываем данные - состояние линии
cnt_bit++; //увеличиваем счетчик приема
error=0; //обнуляем ошибку, т.к. все корректно
};
};
if ((counter>l_min) && (counter<l_max)) //проверка длинного промежутка
{
code[cnt_bit] = !PIND.2; //записываем данные - состояние линии
cnt_bit++; //увеличиваем счетчик приема
error = 0; //обнуляем ошибку, т.к. все корректно
};
if (error == 1) //если не попали ни в один из промежутков, то
{
char i = 0; //внутренняя переменная
TCCR0 = 0x00; //останавливаем таймер
TCNT0 = 0x00; //обнуляем таймер
counter = 0; //обнуляем счетчик
cnt_bit = 0; //обнуляем счетчик принятых бит
for (i=0; i<14; i++) code[i]=0; //обнуляем массив принятого кода
};
if (cnt_bit == 14) //если приняли все 14 бит
{
char i = 0; //внутренняя переменная
TCCR0 = 0x00; //останавливаем таймер
TCNT0 = 0x00;; //обнуляем таймер
cnt_bit = 0; //обнуляем счетчик принятых бит
startbit1 = code[0]; //первый стартовый бит
startbit2 = code[1]; //второй стартовый бит
toggle = code[2]; //триггер-бит
//формируем переменные адреса и команды
address = (code[3] << 4)|(code[4] << 3)|(code[5] << 2)|(code[6] << 1)|code[7];
command = (code[8] << 5)|(code[9] << 4)|(code[10] << 3 )|(code[11] << 2)|(code[12] << 1)|code[13];
for (i=0; i<14; i++) code[i]=0; //обнуляем массив принятого кода
};
};
}
// Timer 0 overflow interrupt service routine
interrupt [TIM0_OVF] void timer0_ovf_isr(void)
{
char i = 0; //внутренняя переменная
TCCR0 = 0x00; //останавливаем таймер
TCNT0 = 0x00; //обнуляем таймер
counter = 0; //обнуляем счетчик
cnt_bit = 0; //обнуляем счетчик принятых бит
for (i=0; i<14; i++) code[i]=0; //обнуляем массив принятого кода
}
interrupt[9]void timer1_overflow(void)
{
switch (COUNT)
{
case 64:
PORTC=0x00;
PORTD=0b10000000;
PORTC=CODE_TABLE[PTR];
COUNT=128;
TCNT1H=254;
TCNT1L=254;
break;
case 128:
PORTC=0x00;
PORTD=0b01000000;
PORTC=CODE_TABLE[PTR1];
COUNT=64;
TCNT1H=254;
TCNT1L=254;
break;
};
}Код: Выделить всё
PTR=0;
PTR1=0;
while(1)
{
if (command>0)PTR=1;
}
}Код: Выделить всё
PORTC=CODE_TABLE[PTR];
...
PORTC=CODE_TABLE[PTR1];
Код: Выделить всё
if (command>0)PTR=1;
А не легче в обработчике при успешном приеме светодиод поджигать? И таймер1 пока выключить нафиг....capucin20 писал(а):...Но у меня на индикаторе высвечивается не один-ноль, у меня на индикаторе "ноль-ноль", если бы там появилась единица, я бы не задавал никаких вопросов....