|
|
View previous topic :: View next topic |
Author |
Message |
tienchuan
Joined: 25 Aug 2009 Posts: 175
|
Problem when change from PIC18F4680 to PIC18F46k22 |
Posted: Mon May 27, 2013 3:03 am |
|
|
Hi all.
In my project, PIC18F4680 is died so that i must change used to PIC18F46K22, can not buy a new PIC18F4680
My code run normal with PIC18F4680, but in PIC18F46K22 had a problems with external RB0 and PortB on change interrupts, my program always jump to int_rb interrupts function and with int_ext, it is not work.
1. I configured fuses for PIC18F46K22 as below:
Code: |
#include <18F46K22.h>
#fuses HSH,PUT,NOPROTECT,NOLVP,NOWDT,NOBROWNOUT,NOPLLEN,NOPBADEN
//setup_oscillator(OSC_32MHZ);
#device *=16 WRITE_EEPROM = NOINT // TAM DUNG GHI EPPROM KHI CO NGAT, NGAT XONG GHI TIEP //HIGH_INTS=TRUE
#use delay(clock=20000000)
#use rs232(baud=4800, xmit=PIN_C6, rcv=PIN_C7, errors) // HARD UART
//!#use i2c(master, sda=DS1307_SDA, scl=DS1307_SCL)
//#priority ext,rb,rda
#use fast_io (A)
#use fast_io (D)
#use fast_io (E)
|
2. config interrupts:
Code: |
setup_oscillator(OSC_PLL_OFF);
port_b_pullups (TRUE);
delay_us (100); // Allow time for weak pullups to rise up
temp=input_b(); // Read PortB to clear change condition
clear_interrupt (int_rb);
//------------------------------------------------
// INIT INTERRUPTS EDGE --- int EXT 0
//------------------------------------------------
ext_int_edge (0, H_TO_L) ;
clear_interrupt (int_ext);
enable_interrupts (int_ext);
enable_interrupts (int_rb);
enable_interrupts (int_rda);
enable_interrupts (global);
|
3. Interrupts service function
Code: |
#int_ext
void ngat_rb0()
{
output_low(PIN_E1);
//delay_ms(500);
while(input(PIN_B0)==0)
{
//delay_ms(100);
}
check_rcv_send=0;
check_ack_change_c=0;
status_counter_change = 1;
//delay_ms (100);
output_toggle (PIN_e1);
count_send++;
count_change = 1;
check_ack_val=0;
//enable_interrupts (int_ext);
}
#int_rb // detect ON/OFF BIEN TAN
void ngat_rb()
{
output_low(PIN_E0);
if(input(PIN_B5)==0)
{
output_low(PIN_E0);
}
else
{
output_high(PIN_E0);
}
check_rcv_send=0;
check_ack_change_s=0;
status_onoff_change = 1;
check_ack_sa_so=0;
clear_interrupt(int_rb);
enable_interrupts (int_rb);
}
|
Please show me way to fix it.
Thanks all. _________________ Begin Begin Begin !!! |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9245 Location: Greensville,Ontario
|
|
Posted: Mon May 27, 2013 5:16 am |
|
|
first error...
HSH is NOT a valid fuse option for the 46k22.
second error..
You've enabled an ISR(serial #1) without a handler.
program will crash..
third..
Never enable an interrupt from inside itself.
program will crash.
suggestion...
create the '1Hz flashing LED program' and verify it does run correctly before going any further, there are other errors in your code, but as shown we cannot 'cut and paste' it to test.
hth
jay |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Mon May 27, 2013 11:34 am |
|
|
Quote: | my program always jump to int_rb interrupts function
|
If you get instant #int_rb interrupt when the program starts, there is
probably something wrong in this area:
Quote: |
port_b_pullups (TRUE);
delay_us (100); // Allow time for weak pullups to rise up
temp=input_b(); // Read PortB to clear change condition
|
I notice you increased the delay from 10us to 100us. That didn't help,
and it should not be necessary.
Next thing, you are using a new PIC. What if the pull-ups operate
differently in the new PIC ? You should suspect this. Look at the
I/O Ports section of the 18F46K22 data sheet. It says:
Quote: | 10.3.1 WEAK PULL-UPS
Each of the PORTB pins has an individually controlled
weak internal pull-up. When set, each bit of the WPUB
register enables the corresponding pin pull-up. |
That means you don't use TRUE and FALSE for the port_b_pullups() function.
Read the CCS manual:
Quote: |
port_x_pullups ( )
Parameters: value is TRUE or FALSE on most parts, some parts that allow pullups to be specified on individual pins permit an 8 bit int here, one bit for each port pin. |
This means you can turn on all PortB pullups with:
Code: | port_b_pullups(0xFF); |
or, using binary notation:
Code: | port_b_pullups(0b11111111); |
|
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Mon May 27, 2013 11:44 am |
|
|
temtronic wrote: | first error...
HSH is NOT a valid fuse option for the 46k22.
|
It is valid in vs. 4.141 and other recent versions. See the fuses in the
header file below:
Quote: | //////// Standard Header file for the PIC18F46K22 device ////////////////
#device PIC18F46K22
#nolist
//////// Program memory: 32768x16 Data RAM: 3896 Stack: 31
//////// I/O: 36 Analog Pins: 28
//////// Data EEPROM: 1024
//////// C Scratch area: 00 ID Location: 200000
//////// Fuses: LP,XT,HSH,HSM,ECH,ECH_IO,RC,RC_IO,INTRC_IO,INTRC,ECM,ECM_IO |
temtronic wrote: |
third..
Never enable an interrupt from inside itself.
program will crash.
|
You are referring to this line from his code:
Quote: | void ngat_rb()
{
.
.
.
clear_interrupt(int_rb);
enable_interrupts (int_rb);
} |
That's OK. The int_rb interrupts are already enabled when the code
is inside the isr. They are not disabled inside the isr. It's the GLOBAL
interrupts that are disabled inside the isr, and should not be enabled.
The line in bold is OK, but it's not necessary. Also, the compiler adds
hidden code to clear the interrupt flag, so the other line is also not
necessary. |
|
|
tienchuan
Joined: 25 Aug 2009 Posts: 175
|
|
Posted: Tue May 28, 2013 3:26 am |
|
|
Thanks u,PCM
I repaired my program follow your instructions, but the result no change
Quote: | port_b_pullups(0xFF); |
I'm afraid problems with Portb on change interrupts
In my project, I used pin RB5 to check interrupts on change, but pin RB5 is CCP3 input, and i setting off CCP in main program, but it still no change
Code: |
void main(void)
{
//setup_oscillator(OSC_PLL_OFF);
setup_ccp3 (CCP_OFF);
......
}
|
Please show me to fix it, thanks u . _________________ Begin Begin Begin !!! |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19546
|
|
Posted: Tue May 28, 2013 4:04 am |
|
|
Some comments inline:
Code: |
#include <18F46K22.h>
#fuses HSH,PUT,NOPROTECT,NOLVP,NOWDT,NOBROWNOUT,NOPLLEN,NOPBADEN
#device WRITE_EEPROM = NOINT
//*=16, does nothing on a PIC18.
#use delay(clock=20000000)
#use rs232(baud=4800, xmit=PIN_C6, rcv=PIN_C7, errors) // HARD UART
#use fast_io (A)
#use fast_io (D)
#use fast_io (E)
|
Where do you set the tris on these ports?. You have told the compiler not to control TRIS, but you are not taking over doing this.....
Code: |
setup_oscillator(OSC_PLL_OFF);
port_b_pullups (0xFF);
delay_us (100); // Allow time for weak pullups to rise up
temp=input_b(); // Read PortB to clear change condition
clear_interrupt (int_rb);
//------------------------------------------------
// INIT INTERRUPTS EDGE --- int EXT 0
//------------------------------------------------
ext_int_edge (0, H_TO_L) ;
clear_interrupt (int_ext);
enable_interrupts (int_ext);
enable_interrupts (int_rb);
enable_interrupts (int_rda);
enable_interrupts (global);
|
Where is INT_RDA?. You must never enable an interrupt without a handler. This will hang the chip. Your code enables three interrupts but you show only two handlers...
Code: |
#int_ext
void ngat_rb0(void)
{
output_low(PIN_E1);
//delay_ms(500);
//Good thing this is disabled, this will result in interrupts being disabled
//in _every_ bit of code that uses delays. Do not use delays in the ISR
while(input(PIN_B0)==0)
{
//delay_ms(100);
}
//This will stop anything else working, while RB0==0.....
//Reprogram the edge, and get out of the interrupt
check_rcv_send=0;
check_ack_change_c=0;
status_counter_change = 1;
//delay_ms (100);
output_toggle (PIN_e1);
count_send++;
count_change = 1;
check_ack_val=0;
}
#int_rb // detect ON/OFF BIEN TAN
void ngat_rb(void)
{
output_low(PIN_E0);
if(input(PIN_B5)==0)
{
output_low(PIN_E0);
}
else
{
output_high(PIN_E0);
}
check_rcv_send=0;
check_ack_change_s=0;
status_onoff_change = 1;
check_ack_sa_so=0;
}
|
I'd suspect your main problem is INT_RDA.
Best Wishes |
|
|
tienchuan
Joined: 25 Aug 2009 Posts: 175
|
|
Posted: Tue May 28, 2013 5:56 am |
|
|
Thanks u, Ttelmah
Because my program is too long, i only post shorter code.
I configured tris in main program
Code: |
void main(void)
{
delay_ms (100);
set_tris_a (0); // control A0 - A3: cs1, rst, cs2, cs3
set_tris_b (0xff); // keypad
set_tris_c (0x80); //
set_tris_d (0);
set_tris_e (0); // control
....
} |
and i have a RDA handler in my program, and it also too long, i shortened it.
Code: |
#int_rda //HIGH
void ngat_rs232()
{
c = getc ();
switch (c)
{
case '&':
{
count_hi_rcv = getc ();
count_lo_rcv = getc ();
count_bbc_rcv = getc ();
if (check_one_rcv == 0)
{
if ( (count_hi_rcv ^ count_lo_rcv) == count_bbc_rcv)
{
output_toggle(PIN_E2);
count_rcv = make16 (count_hi_rcv, count_lo_rcv);
count_send = count_send + count_rcv;
check_bbc_rcv = 1;
check_one_rcv = 1;
}
}
}
break;
//---------------------------------------------------------------------------------
case '$':
{
index = 0;
}
break;
//---------------------------------------------------------------------------------
case '#':
{
//******************************************************************************
// KIEM TRA KET NOI VOI PC ----- > $1LINK#
//******************************************************************************
if ( (str_rs232[0] == '1')&& (str_rs232[1] == 'L')&& (str_rs232[2] == 'I')&& (str_rs232[3] == 'N')&& (str_rs232[4] == 'K') )
{
check_link_pc = 1;
}
//******************************************************************************
// KIEM TRA KET NOI VOI PC ----- > $1LINK#
//******************************************************************************
else if ( (str_rs232[0] == '1')&& (str_rs232[1] == 'R')&& (str_rs232[2] == 'E')&& (str_rs232[3] == 'S'))
{
check_restore_pc = 1;
}
//******************************************************************************
// KIEM TRA CAP NHAT GIA TRI COUNTER ----- > $1SEND#
//******************************************************************************
else if ( (str_rs232[0] == '1')&& (str_rs232[1] == 'S')&& (str_rs232[2] == 'E')&& (str_rs232[3] == 'N')&& (str_rs232[4] == 'D') )
{
check_send_count_data = 1;
check_rcv_send=1;
}
//******************************************************************************
// KIEM TRA RESET TU PC
//******************************************************************************
else if ((str_rs232[0] == '1')&& (str_rs232[1] == 'R')&& (str_rs232[2] == 'S') && (str_rs232[3] == 'T'))
{
check_reset_pc = 1;
}
//******************************************************************************
// KIEM TRA PHAN HOI ACK TU PC
//******************************************************************************
else if ( (str_rs232[0] == '1')&& (str_rs232[1] == 'A')&& (str_rs232[2] == 'C') && (str_rs232[3] == 'K'))
{
if ((str_rs232[4] == 'V')&& (str_rs232[5] == 'A')&& (str_rs232[6] == 'L') )
{
check_ack_val = 1; //NHAN CHUOI $1ACKVAL# < - > PC DA NHAN DUNG GIA TRI SA
check_ack_counter=1;
status_counter_change=0;
}
//--------------------------------------------------------------------------------
else if ((str_rs232[4] == 'S')&& (str_rs232[5] == 'A'))
{
check_ack_sa_so = 1; //NHAN CHUOI $1ACKSA# < - > PC DA NHAN DUNG GIA TRI SA
status_onoff_change=0;
}
//--------------------------------------------------------------------------------
else if ((str_rs232[4] == 'S')&& (str_rs232[5] == 'O'))
{
check_ack_sa_so = 1; //NHAN CHUOI $1ACKSO# < - > PC DA NHAN DUNG GIA TRI SO
status_onoff_change=0;
}
//--------------------------------------------------------------------------------
else if ((str_rs232[4] == 'C')&& (str_rs232[5] == 'A'))
{
check_ack_change = 1; //NHAN CHUOI $1ACKCA# < - > PC DA NHAN DUNG GIA TRI SO
}
else if((str_rs232[4] == 'N')&& (str_rs232[5] == 'G'))
{
check_ack_ng=1;
}
}
}
break;
//-----------------------------------------------------------------------------
default:
{
str_rs232[index] = c;
index++;
}
break;
//-----------------------------------------------------------------------------
} // end of switch
}
|
And i don't think have problems with RDA interrupts handler, but problems is continued
Thanks u. _________________ Begin Begin Begin !!! |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19546
|
|
Posted: Tue May 28, 2013 7:29 am |
|
|
I think you have problems with int_rda.
The RDA interrupt, means that _one_ character (just one), is ready to be read. Your handler will hang the chip. You need something like a state machine to handle the data. This _is_ a major problem.
There is also another problem. You have the comment '//HIGH' against this handler, suggesting you are perhaps using hardware interrupt priorities. Read the data sheet. Realise that if you use INT_EXT, it _always_ uses high priority, if interrupt priorities are used.
Also, nowhere do I see you turning off the analog functions. These override the I/O functions on many of the pins you are using.
Seriously, the first place to begin with debugging, is to cut the code down to the minimum showing the problem, and post _compilable_ code. Otherwise we haven't got a hope of knowing what is really going on. |
|
|
tienchuan
Joined: 25 Aug 2009 Posts: 175
|
|
Posted: Sun Jun 02, 2013 11:12 pm |
|
|
Ttelmah wrote: | I think you have problems with int_rda.
The RDA interrupt, means that _one_ character (just one), is ready to be read. Your handler will hang the chip. You need something like a state machine to handle the data. This _is_ a major problem.
There is also another problem. You have the comment '//HIGH' against this handler, suggesting you are perhaps using hardware interrupt priorities. Read the data sheet. Realise that if you use INT_EXT, it _always_ uses high priority, if interrupt priorities are used.
Also, nowhere do I see you turning off the analog functions. These override the I/O functions on many of the pins you are using.
Seriously, the first place to begin with debugging, is to cut the code down to the minimum showing the problem, and post _compilable_ code. Otherwise we haven't got a hope of knowing what is really going on. |
Thanks u,Ttelmah.
I think RDA interrupt handler is normal, because all source code run true in Pic18F4680, but when i change to Pic18F46K22, the problem is appear in PortB interrupts Onchange.
In Pic18F4680, i fix the port b interrupt on change ( autorun when program start) with help of PCM Programmer:
Code: |
port_b_pullups (0xff);
delay_us (10); // Allow time for weak pullups to rise up
temp=input_b(); // Read PortB to clear change condition
clear_interrupt (int_rb);
|
The code run exactly in PIC18F4680
But when i change to use PIC18F46K22, i fixed PortB pull up also with help of PCM Programmer:
Code: | port_b_pullups (0xff); |
But the errors is continued.
Pls show me way to fix it.
Thanks and Regards _________________ Begin Begin Begin !!! |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19546
|
|
Posted: Mon Jun 03, 2013 12:22 am |
|
|
Unfortunately, this is a little like the person who found they could slow their car, by pulling the choke. Just because it apparently works, doesn't make it even remotely good programming. You are _mishandling_ the interrupt, and basically making it pointless using it....
Key mantra on all interrupts, is that the code should _just_ handle the hardware event signalled by the interrupt. As little as possible more.
Step back and do this:
"the first place to begin with debugging, is to cut the code down to the minimum showing the problem, and post _compilable_ code. Otherwise we haven't got a hope of knowing what is really going on".
This is the core of all debugging. |
|
|
|
|
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
|