📄 f_13_24_irdet_biphase.c
字号:
#include "config.h"
#include "serial.c"
#include "serio.c"
#include "i2cmsu.c"
// decodes IR signal using Timer1 and CCP capture capability
// uses biphase mode
//prototypes
void do_ircap(void);
void reset_ir(void);
volatile unsigned int last_capture, this_capture;
volatile unsigned long delta;
volatile unsigned char tmr1_ov; // timer 1 overflow cnt
#define MAXBYTES 8
volatile unsigned char cbuff[MAXBYTES];
volatile unsigned char bitcount, bytecount,bit_edge;
volatile unsigned char state,edge_capture,current_bit;
volatile unsigned char this_byte;
void do_ircap(void);
#define IDLE_TIME 4
#define BITCHANGE 10000
#define IDLE 0
#define START_PULSE 1
#define BIT_CAPTURE 2
#define IO_FINISH 3
#if defined(HI_TECH_C)
void interrupt timer_isr(void)
#endif
#if defined(__18CXX)
#pragma interrupt timer_isr
void timer_isr(void)
#endif
{
if (TMR1IF) {
tmr1_ov++; // increment timer1 overflow
}
if (CCP1IF) {
this_capture = CCPR1;
if (!tmr1_ov) {
// no overflow at all
delta = this_capture - last_capture ;
} else {
delta = tmr1_ov-1;
delta = (delta << 16);
last_capture = 0 - last_capture;
delta = delta + last_capture;
delta = delta + this_capture;
}
last_capture = this_capture;
tmr1_ov = 0; // clear timer 1 overflow count
if (CCP1CON & 0x01) {
CCP1CON = 0x0; //reset first
CCP1CON = 0x4; //falling edge
}
else {
CCP1CON = 0x0; //reset first
CCP1CON = 0x5; // rising edge
}
edge_capture = 1;
}
do_ircap();
}
// decode IR biphase
void do_ircap(void){
TMR1IF = 0; CCP1IF = 0;
switch (state) {
case IDLE:
// wait for line to become idle
if (tmr1_ov > IDLE_TIME){
tmr1_ov = 0;
state = START_PULSE;
edge_capture = 0;
}
break;
case START_PULSE:
if (edge_capture) { // wait for edge
edge_capture = 0;
bit_edge = 0;
state = BIT_CAPTURE;
}
break;
case BIT_CAPTURE:
// wait for edge or idle condition
if (tmr1_ov > 1) { // finished
// disable capture,timer1 interrupts
CCP1IE = 0; TMR1IE = 0; TMR1ON = 0;
state = IO_FINISH;
} else if (edge_capture) {
edge_capture = 0;
//accumulating bits, MSB to LSB
if ((delta > BITCHANGE) || bit_edge) {
if (delta > BITCHANGE) {
// toggle current bit if wide pulse
current_bit = ~current_bit;
}
if (current_bit) this_byte = this_byte | 0x01; //set LSbit
bitcount++;
bit_edge = 0; // next edge is not a bit
if (bitcount == 8) {
bitcount = 0;
cbuff[bytecount] = this_byte;
bytecount++;
this_byte = 0;
} else{
this_byte = this_byte << 1;
}
} else if (!bit_edge)
bit_edge = 1;
}
break;
}//end switch
}// end do_ircap()
void reset_ir(void) {
state = IDLE; // look for idle
CCP1CON = 0; // turn off when changing modes
CCP1CON = 0x4; // capture every falling edge
current_bit = ~(0);
bitcount = 0; bytecount = 0;
tmr1_ov = 0; // clear timer 1 overflow count
last_capture = 0;
// enable capture and timer1 interrupts
CCP1IF = 0; CCP1IE = 1;
TMR1IF = 0; TMR1IE = 1; TMR1ON = 1;
}
unsigned char i, t_bytecount, t_bitcount, t_this_byte, cnt;
unsigned char tbuff[MAXBYTES];
void main(void){
serial_init(95,1); // 19200 in HSPLL mode, crystal = 7.3728 MHz
// initialize timer 1, prescale by 1, internal clock
T1CKPS1 = 0; T1CKPS0 = 0; T1OSCEN = 0; TMR1CS = 0;
// set CCP1 as input,
bitset(TRISC,2);
IPEN = 0; PEIE = 1; GIE = 1;
cnt = 0;
reset_ir();
pcrlf(); printf("Ready for capture\n"); pcrlf();
while(1) {
// wait for IR data to arrive
while (state != IO_FINISH);
// copy interrupt data to safe place
t_bytecount = bytecount;
t_bitcount = bitcount;
t_this_byte = this_byte;
for (i = 0;i < t_bytecount;i++) {
tbuff[i] = cbuff[i];
cbuff[i] = 0;
}
reset_ir();
// print out last captured data
if (t_bitcount != 0) {
// adjust last byte assuming input bits are zero
for (i=t_bitcount; i < 7; i++) t_this_byte = t_this_byte << 1;
tbuff[t_bytecount] = t_this_byte;
t_bytecount++;
}
printf("(%d): Received %d bytes, %d bits.",
cnt,t_bytecount, t_bitcount); pcrlf();
for (i = 0;i < t_bytecount;i++) {
printf(" Byte RX: %x", tbuff[i]);pcrlf();
}
cnt++;
}
}
//for MCC18, place the interrupt vector goto
#if defined(__18CXX)
#if defined(HIGH_INTERRUPT)
#pragma code HighVector=HIGH_INTERRUPT
#else
#pragma code HighVector=0x0008
#endif
void HighVector (void)
{
_asm goto timer_isr _endasm
}
#pragma code
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -