|
|
View previous topic :: View next topic |
Author |
Message |
masterat
Joined: 17 Jul 2010 Posts: 26
|
12F675 toggle problem |
Posted: Sun Aug 08, 2010 1:19 am |
|
|
Hi all..
I have a problem about toggle to high on 12F675 I/O pin at below code. When I push IR remote on + button pin_A0 should toggle to high until I push on + button again, but they show high a while which long as time relay 200ms then go to low. I test same this code on 16F688 and all work fine. Please let me know what is wrong.
My ccs c is V 4.108.
Code: |
// This is code for an IR remote control decoder
// using the 12 bit SIRC protocol. Based on code
// by Aurelian Nichita.
// Hardware - TSOP1738 to GP2 of 12F675. Two LEDs
// on GP4 and GP5 as indicators.
// Sample signal at TSOP data output (taken using
// PICKit2 as a logic analyzer):
//
// ??????\________/??\__/??\__/??\__/??\__/??\__/??\__/??\__/??\____/??\__/??\__/??\__/??\__/?????
// (idle)| (start) | bit0| bit0| bit0|bit0| bit0| bit0| bit0| bit1 | bit0| bit0| bit0|bit0|(idle)
//
// TSOP data is inverted; it idles high.
// [??\_ : negative going edge; _/?? : positive going edge]
//
//original on Rohit de Sa 15Aug08 v1.0
//--------------------------------------------------------------------------------
#include <12f675.h>
#fuses INTRC_IO,noWDT,PUT,PROTECT,BROWNOUT,noMCLR,CPD
#use delay(clock=4000000) //one instruction=1us
#use fast_io(a)
#zero_ram
#define one_min 1450 //no of counts to safely detect bit1
#define one_max 2200 //optimal @4 MHz is 1800
#define zero_min 600 //no of counts to safely detect bit0
#define zero_max 1440 //optimal @4 MHz is 1200
#define out1 PIN_A0
#define out2 PIN_A4
int16 irframes[14]; //holds incoming IR data
int8 ircount =0; //counts no if bits received
int1 irdone=false; //flag bit
int1 okbit =true;
//--------------------------------------------------------------------------------
#int_ext //IR bits detected by edge triggering
void ext_isr()
{
if(irdone) return;
irframes[ircount++]=get_timer1();
if(ircount>=13) //if 13 triggers(ie 12 bits+start) found
irdone=TRUE; //set "done" flag
set_timer1(0); //restart timer for new bit
enable_interrupts(int_timer1); //(is this necessary? I dont really know)
}
//--------------------------------------------------------------------------------
#int_timer1 //(is this isr necessary? I dont really know)
void timer1_isr()
{
disable_interrupts(int_timer1);
}
//--------------------------------------------------------------------------------
#separate
int1 decode_ir(int8 &addr,int8 &cmd) //IR decoding function
{
int8 i;
int8 mask;
int1 bits[12];
addr=0;
cmd=0;
irframes[13]=1200; //last bit is always zero
for(i=2;i<=13;i++)
{
if((one_min<=irframes[i])&&(irframes[i]<=one_max))
bits[i-2]=0x01; //if the sampled signal lies within limits
else //set to 1
if((zero_min<=irframes[i])&&(irframes[i]<=zero_max))
bits[i-2]=0x00; //if the sampled signal lies within limits
else //set to 0
return false; //otherwise clear flag
}
mask=0x01; //format command
for (i=0;i<=6;i++)
{
if (bits[i])
cmd=cmd|mask;
mask<<=1;
}
mask=0x01; //format address
for (i=7;i<=11;i++)
{
if(bits[i])
addr=addr|mask;
mask<<=1;
}
return TRUE; //set flag
}
//--------------------------------------------------------------------------------
void start_ir()
{
ircount=0;
memset(irframes,0x00,sizeof(irframes));
irdone=false;
}
//--------------------------------------------------------------------------------
void main()
{
int8 addr, cmd;
delay_ms(50); //setting up PIC
set_tris_a(0b00000100); // PINA5,A4,A3,A1,A0 =Output ,PINA2 =Input
//timer prescaler dependent on oscillator speed
setup_timer_1(T1_INTERNAL|T1_DIV_BY_1);
ext_int_edge(0,H_to_L);
enable_interrupts(global);
enable_interrupts(int_ext);
start_ir();
while(TRUE)
{
if (irdone)
{
decode_ir(addr, cmd);
delay_ms(50);
if (okbit)
{
output_bit(out2, 1);
delay_ms(20);
output_bit(out2, 0);
if (addr==1||addr==0)
{
switch (cmd)
{
case (0x07): //push "8"
{
output_bit(out1, 1);
delay_ms(50);
output_bit(out1, 0);
}
case (0x12): //push "+"
{
output_toggle(out1);
delay_ms(200);
}
case (0x04): //push "5"
{
output_bit(out1, 1);
delay_ms(200);
output_bit(out1, 0);
}
}
}
start_ir();
}
}
}
} |
|
|
|
masterat
Joined: 17 Jul 2010 Posts: 26
|
|
Posted: Tue Aug 10, 2010 10:36 pm |
|
|
Any one please give me some hint? |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Wed Aug 11, 2010 2:00 pm |
|
|
When you modify some code that you found on the forum, and have a
question about it, you should:
1. Post a link to the original code.
2. Post a list of the modifications that you did, and give the reasons
why you did each one.
If the original code has some timing calculations, such as a timer
interrupt rate, you should show how your modified code maintains
the same timing as the original code. |
|
|
masterat
Joined: 17 Jul 2010 Posts: 26
|
|
Posted: Wed Aug 11, 2010 8:07 pm |
|
|
Thank you for your kindly suggestion.I hope will have some one who pass this test and get some experience wellcome to give me a hints. |
|
|
bkamen
Joined: 07 Jan 2004 Posts: 1615 Location: Central Illinois, USA
|
|
Posted: Wed Aug 11, 2010 8:41 pm |
|
|
masterat wrote: | Thank you for your kindly suggestion.I hope will have some one who pass this test and get some experience wellcome to give me a hints. |
You're not making any sense...
If you can't explain more than just posting code and asking for help even when someone tries to get you to elaborate more, you're going to find yourself in a very quiet room. (virtually speaking)
-Ben _________________ Dazed and confused? I don't think so. Just "plain lost" will do. :D |
|
|
pmuldoon
Joined: 26 Sep 2003 Posts: 218 Location: Northern Indiana
|
|
Posted: Thu Aug 12, 2010 11:23 am |
|
|
try adding 'break;' at the end of each case statement so they don't flow into the next case. |
|
|
bkamen
Joined: 07 Jan 2004 Posts: 1615 Location: Central Illinois, USA
|
|
Posted: Thu Aug 12, 2010 3:07 pm |
|
|
That's a good point...
is:
Code: |
case (0x04): //push "5"
{
output_bit(out1, 1);
delay_ms(200);
output_bit(out1, 0);
}
|
Valid 'C' syntax?
It looks like you're writing in something scripting-like for Unix. (the braces) and yes, it's missing the break;
That almost looks like PERL. _________________ Dazed and confused? I don't think so. Just "plain lost" will do. :D |
|
|
andrewg
Joined: 17 Aug 2005 Posts: 316 Location: Perth, Western Australia
|
|
Posted: Thu Aug 12, 2010 8:48 pm |
|
|
bkamen wrote: | That's a good point...
is:
Code: |
case (0x04): //push "5"
{
output_bit(out1, 1);
delay_ms(200);
output_bit(out1, 0);
}
|
Valid 'C' syntax?
|
Yes. Braces can show up just about anywhere. I'll do things like: Code: |
// code here
#ifdef DEBUG
{
int8 i;
// debug code that uses i here
}
#endif
// more code here | The braces let me keep any variables needed by the debug code with the debug code. See http://en.wikipedia.org/wiki/Duffs_device for more interesting syntax. _________________ Andrew |
|
|
masterat
Joined: 17 Jul 2010 Posts: 26
|
|
Posted: Fri Aug 13, 2010 4:50 am |
|
|
pmuldoon wrote: | try adding 'break;' at the end of each case statement so they don't flow into the next case. |
Thank you for all suggestion.Edit to last code include break; command in final of all case and reduce some out but result same. Especially output_toggle() command will toggle till end of delay time then switch to 0 .
Below is last code.
Code: | #include <12f675.h>
#fuses INTRC_IO,NOWDT,PUT,PROTECT,NOBROWNOUT,NOMCLR,CPD
#use delay(clock=4000000) //one instruction=1us
#use fast_io(a)
#zero_ram
#rom 0x3ff={0x3494} // get value from pkit2 function
#define one_min 1450 //no of counts to safely detect bit1
#define one_max 2200 //optimal @4 MHz is 1800
#define zero_min 600 //no of counts to safely detect bit0 600
#define zero_max 1440 //optimal @4 MHz is 1200
#define out1 PIN_A0
#define out2 PIN_A4
int16 irframes[14]; //holds incoming IR data
int8 ircount =0; //counts no if bits received
int1 irdone=false; //flag bit
//--------------------------------------------------------------------------------
#int_ext //IR bits detected by edge triggering
void ext_isr()
{
if(irdone) return;
irframes[ircount++]=get_timer1();
if(ircount>=13) //if 13 triggers(ie 12 bits+start) found
irdone=TRUE; //set "done" flag
set_timer1(0); //restart timer for new bit
disable_interrupts(int_timer1);
}
//--------------------------------------------------------------------------------
#separate
int1 decode_ir(int8 &addr,int8 &cmd) //IR decoding function
{
int8 i;
int8 mask;
int1 bits[12];
addr=0;
cmd=0;
irframes[13]=1200; //last bit is always zero
for(i=2;i<=13;i++)
{
if((one_min<=irframes[i])&&(irframes[i]<=one_max))
bits[i-2]=0x01; //if the sampled signal lies within limits
else //set to 1
if((zero_min<=irframes[i])&&(irframes[i]<=zero_max))
bits[i-2]=0x00; //if the sampled signal lies within limits
else //set to 0
return false; //otherwise clear flag
}
mask=0x01; //format command
for (i=0;i<=6;i++)
{
if (bits[i])
cmd=cmd|mask;
mask<<=1;
}
mask=0x01; //format address
for (i=7;i<=11;i++)
{
if(bits[i])
addr=addr|mask;
mask<<=1;
}
return TRUE; //set flag
}
//--------------------------------------------------------------------------------
void flash (char x) {
while (x>0) {
output_low (out1);
delay_ms (250);
output_high (out1);
delay_ms (250);
x--;
}
}
//--------------------------------------------------------------------------------
void start_ir()
{
ircount=0;
memset(irframes,0x00,sizeof(irframes));
irdone=false;
}
//--------------------------------------------------------------------------------
void main()
{
int8 addr, cmd;
set_tris_a(0b00000100); // PINA5,A4,A3,A1,A0 =Output ,PINA2 =Input
output_a(0b00000000); // clear all bit =0
flash (5); //flash out1 5 time tell that running ok
delay_ms(50); //setting up PIC
//timer prescaler dependent on oscillator speed
setup_timer_1(T1_INTERNAL|T1_DIV_BY_1);
ext_int_edge(0,H_to_L);
enable_interrupts(global);
enable_interrupts(int_ext);
start_ir();
while(TRUE)
{
if (irdone)
{
decode_ir(addr, cmd);
delay_ms(50);
output_bit(out1, 1);
delay_ms(20);
output_bit(out1, 0);
if (addr==1||addr==0)
{
switch (cmd)
{
case (0x07): //push "8"
{
output_bit(out2, 1);
delay_ms(50);
output_bit(out2, 0);
break;
}
case (0x12): //push "+"
{
output_toggle(out2); // Out2 should be toggle between 1 or 0
delay_ms(200); // delay for leave from IR button
break;
}
case (0x04): //push "5"
{
output_bit(out2, 1);
delay_ms(200);
output_bit(out2, 0);
break;
}
}
}
start_ir();
}
}
} |
When power on cpu start up output flash 5 times to PIN_A0 is working fine then wait for receive IR Remote ,every time when I press on remote code 0x12 PIN_A4 toggle a while and goto 0.Another remote code work fine.
Seem,when end case loop cpu sent some auto command to set bit low.
ccsC asm list code is
Code: | 122: switch (cmd)
123: {
1BC 084B MOVF 0x4b, W
1BD 3A07 XORLW 0x7
1BE 1903 BTFSC 0x3, 0x2
1BF 29C7 GOTO 0x1c7
1C0 3A15 XORLW 0x15
1C1 1903 BTFSC 0x3, 0x2
1C2 29CD GOTO 0x1cd
1C3 3A16 XORLW 0x16
1C4 1903 BTFSC 0x3, 0x2
1C5 29D3 GOTO 0x1d3
1C6 29D9 GOTO 0x1d9
124: case (0x07): //push "8"
125: {
126: output_bit(out2, 1);
1C7 1605 BSF 0x5, 0x4
127: delay_ms(50);
1C8 3032 MOVLW 0x32
1C9 00CD MOVWF 0x4d
1CA 2060 CALL 0x60
128: output_bit(out2, 0);
1CB 1205 BCF 0x5, 0x4
129: break;
1CC 29D9 GOTO 0x1d9
130: }
131: case (0x12): //push "+"
132: {
133: output_toggle(out2); // Out2 should be toggle between 1 or 0
1CD 3010 MOVLW 0x10
1CE 0685 XORWF 0x5, F
134: delay_ms(200); // delay for leave from IR button
1CF 30C8 MOVLW 0xc8
1D0 00CD MOVWF 0x4d
1D1 2060 CALL 0x60
135: break;
1D2 29D9 GOTO 0x1d9
136: }
137: case (0x04): //push "5"
138: {
139: output_bit(out2, 1);
1D3 1605 BSF 0x5, 0x4
140: delay_ms(200);
1D4 30C8 MOVLW 0xc8
1D5 00CD MOVWF 0x4d
1D6 2060 CALL 0x60
141: output_bit(out2, 0);
1D7 1205 BCF 0x5, 0x4
142: break;
1D8 29D9 GOTO 0x1d9
143: }
144: }
145: }
146: start_ir();
1D9 2082 CALL 0x82
147: }
148: }
1DA 29A7 GOTO 0x1a7
1DB 0063 SLEEP |
Code: | 93: ircount=0;
082 01C8 CLRF 0x48
94: memset(irframes,0x00,sizeof(irframes));
083 0185 CLRF 0x5
084 302C MOVLW 0x2c
085 0084 MOVWF 0x4
086 01CC CLRF 0x4c
087 301C MOVLW 0x1c
088 00CD MOVWF 0x4d
95: irdone=false;
091 1049 BCF 0x49, 0
96: }
092 0008 RETURN
97: //-------------------------------------------------------------------------------- |
|
|
|
pmuldoon
Joined: 26 Sep 2003 Posts: 218 Location: Northern Indiana
|
|
Posted: Fri Aug 13, 2010 6:01 am |
|
|
sounds like you're int routine is firing again and resetting 'irdone'.
with the other commands it would go unnoticed, but with the toggle it will change state.
Try putting in a very long delay in start_ir() before clearing irdone. That may tell you if your unintentially processing a second command from the remote. Then you'll know what to fix. |
|
|
masterat
Joined: 17 Jul 2010 Posts: 26
|
|
Posted: Fri Aug 13, 2010 8:00 am |
|
|
pmuldoon wrote: | sounds like you're int routine is firing again and resetting 'irdone'.
with the other commands it would go unnoticed, but with the toggle it will change state.
Try putting in a very long delay in start_ir() before clearing irdone. That may tell you if your unintentially processing a second command from the remote. Then you'll know what to fix. |
Wow Thank you! Your hints is very good I found by use your delay technic. Found that output port was reset by memset command. I replace 13 irframes by normal operator all done.
Thank again.
Code: | void start_ir()
{
ircount=0;
// memset(irframes,0x00,sizeof(irframes));
irframes[0]=0x00;
irframes[1]=0x00;
irframes[2]=0x00;
irframes[3]=0x00;
irframes[4]=0x00;
irframes[5]=0x00;
irframes[6]=0x00;
irframes[7]=0x00;
irframes[8]=0x00;
irframes[9]=0x00;
irframes[10]=0x00;
irframes[11]=0x00;
irframes[12]=0x00;
irdone=false;
} |
|
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|