вот пока не спится (2:31) решил добавить немного инфы:
если кратко в двух словах - ловим задний фронт сигнала, пытаемся выловить паузу между посылками (для этого запускаем таймер и по пришедшему переднему фронту смотрим, тикнул таймер или нет... если да - значит дальше можно считывать данные, если нет - снова пытаться поймать паузу)... ну а считываем по задним фронтам тактового сигнала... вроде несложно.... только ловится вот такая ерунда
001111101111110001111001111100001111011111100001
001111011111100001111001111101001111101111110101
101111000000011001111100000000001111000000011101
001111000000010001111000000011001111100000000101
001111100000000101111000000011101111100000000001
001111100000001001111100000000001111000000011001
001111011111100001111001111100101111001111101101
101111000000010101111000000010101111000000011001
001111100000000101111000000010001111000000010101
... в которой распознать двоичный дополнительный код ну никак не удаётся... то ли лыжи не едут.. то ли руки...
а вот и код:
Код
#include "ioavr.h"
#include "intrinsics.h"
#define SCALE_IDLE 1
#define SCALE_SEARCHPAUSE 2
#define SCALE_WAITPAUSE 3
#define SCALE_READDATA 4
#define SCALE_READY 5
unsigned char scale_status = SCALE_IDLE;
bool scale_timer_tick = false;
unsigned int troubles = 0;
unsigned char data[50] = {0x00};
unsigned int i = 0;
volatile unsigned char input1 = 0, input2 = 0, input3 = 0;
volatile unsigned char tcnt1 = 0;
#pragma vector = INT4_vect
__interrupt void INT4_ISR(void)
{
switch (scale_status)
{
case SCALE_SEARCHPAUSE: //on falling edge
{
//configuire pin 6 to be sensitive to rising edge of signal
EIMSK &= ~(1<<INT4);
EICRB |= (1<<ISC41) | (1<<ISC40);
EIFR |= (1<<INTF4);
EIMSK |= (1<<INT4);
TCNT1 = 0; //reset timer counter
scale_timer_tick = false; //clear timer flag
TCCR1B |= (1<<CS12) | (1<<CS10); //start timer
scale_status = SCALE_WAITPAUSE;
break;
}
case SCALE_WAITPAUSE: //on rising edge
{
if (scale_timer_tick)
{
//pause found, prepare to read 48 bits data
i = 0;
scale_status = SCALE_READDATA;
}
else
{
//no pause found
++troubles; //test
scale_status = SCALE_SEARCHPAUSE; //go back to "SEARCH PAUSE" status
}
scale_timer_tick = false; //clear flag
//configuire pin 6 to be sensitive to falling edge of signal
EIMSK &= ~(1<<INT4);
EICRB |= (1<<ISC41) | (0<<ISC40);
EIFR |= (1<<INTF4);
EIMSK |= (1<<INT4);
break;
}
case SCALE_READDATA: //on falling edge
{
//read data three times to avoid glitches
input1 = PINE;
__delay_cycles(10);
input2 = PINE;
__delay_cycles(10);
input3 = PINE;
if ((input1 & (1<<PINE5)) && (input2 & (1<<PINE5)) && (input3 & (1<<PINE5)))
data[i] = 1;
else
data[i] = 0;
++i;
if (i >= 48)
{
troubles = 0;
i = 0;
scale_status = SCALE_IDLE; < breakpoint here
}
break;
}
}
}
#pragma vector = TIMER1_COMPA_vect
__interrupt void TIMER1_COMPA_ISR(void)
{
PORTC = 0xFF;
tcnt1 = TCNT1;
scale_timer_tick = true; //set flag
TCCR1B &= ~((1<<CS12) | (1<<CS10)); //stop timer
PORTC = 0x00;
}
void init_pins(void)
{
//pin6 - PORTE4 - clock, pin7 - PORTE5 - data
DDRE &= ~((1<<DDE4) | (1<<DDE5)); //pins 6, 7 are set as inputs
PORTE |= ((1<<PORTE4) | (1<<PORTE5)); //enable pull-up resistors at pins 6, 7
//configuire pin 6 to be sensitive to falling edge of signal
EIMSK &= ~(1<<INT4);
EICRB |= (1<<ISC41) | (0<<ISC40);
EIFR |= (1<<INTF4);
EIMSK |= (0<<INT4);
DDRC = 0xFF;
PORTC = 0x00;
}
void init_scale_timer()
{
//set timer 1 to 100ms interval
TCCR1A = 0x00;
TCCR1B = (1<<WGM12) | (0<<CS12) | (0<<CS10); //CTC Timer1 mode, (OCR1A)
TCCR1C = 0x00;
OCR1A = 1210; //310 ms <============================ depend on system clock!
TIMSK |= (1<<OCIE1A); //enable interrupt from system timer
TIFR |= (1<<OCF1A); //clear flag
}
int main (void)
{
init_pins();
init_scale_timer();
__enable_interrupt();
for (;;)
{
if (scale_status == SCALE_IDLE)
{
scale_status = SCALE_SEARCHPAUSE;
EIMSK |= (1<<INT4);
}
__delay_cycles(10000);
}
return 0;
}
может свежим взглядом какой косяк заметен?