View previous topic :: View next topic |
Author |
Message |
A_L_E_X
Joined: 21 Feb 2010 Posts: 11
|
Exiting from a do while loop |
Posted: Sun May 23, 2010 4:51 am |
|
|
I have a pic16f648A connected to RS232. The system reads a pressure and sends data to an LCD and to RS232 in a do while loop. When i press a button (may be any button but it would be better to be a specific one) on the keyboard, i want to exit the loop.
Code: | if (c=='k')
{
do
{
read_adc();
ADC=ADC_result;
kpa=ADC*3.125;
printf("\fReading pressure");
printf(lcd_putc,"\fThe pressure is :\n%f kPa \r",kpa);
init_ext_eeprom();
write_ext_eeprom(a,kpa);
a++;
delay_ms(100);
}
while(1); |
if i put getc() the system makes only one pass and hangs at getc(). I need something like an intrerupt. but i don't know how to do it |
|
|
tesla80
Joined: 23 May 2007 Posts: 81
|
|
Posted: Sun May 23, 2010 6:18 am |
|
|
Hi,
if you add these lines somewhere in the do-while loop, you can exit from the loop
Code: | if(input(button))
break; |
pic16f648A has hardware usart module. You can use the INT_RDA for interrupt driven rs232 connection or in the loop add this:
Code: | if(kbhit())
{
foo = getc();
} |
kbhit checks incoming rs232 information.
Read help ;) |
|
|
A_L_E_X
Joined: 21 Feb 2010 Posts: 11
|
|
Posted: Sun May 23, 2010 9:08 am |
|
|
If i don't use USART port, can i still use that code ? i can't use the usart ports because other peripherals are conected to those ports. |
|
|
A_L_E_X
Joined: 21 Feb 2010 Posts: 11
|
|
Posted: Sun May 23, 2010 9:31 am |
|
|
It worked with this code :
Code: | if(kbhit())
{
break;
} |
But then it exits from the loop only if I press a button 3 or more times. Can I do something else ? It is good this way, but it would be better if I could press a specific button only one time. |
|
|
languer
Joined: 09 Jan 2004 Posts: 144 Location: USA
|
|
Posted: Sun May 23, 2010 9:32 pm |
|
|
Best option is, of course, to use the HW USART function. Using the SW to emulate the UART, you have to poll the pin fast enough.
Excerpt for CCS help file: Quote: |
Note that in the case of software RS232 this function should be called at least 10 times the bit rate to ensure incoming data is not lost. |
The following lines in your code probably may prevent the proper polling:
Quote: | printf("\fReading pressure");
printf(lcd_putc,"\fThe pressure is :\n%f kPa \r",kpa);
...
init_ext_eeprom();
write_ext_eeprom(a,kpa);
...
delay_ms(100); |
If the pin where the RS232 input resides has an interrupt vector, then you can use the interrupt-on-change option. Unfortunately it looks like the only pin on the 648A with this capability is RB0.
A few options:
1) Re-map the IO so you use the HW USART - this is the reason for having multiplexed HW on the MCU.
2) Migrate to a newer drop-in device (e.g. 16F88) which allows interrupt-on-change on multiple pins.
3) Add the HW function to detect edge-changes external to the MCU (quite a shame, since the MCU already has some of this built-in).
4) Re-evaluate your requirements
On thing worth mentioning, you may not require to initialize the EEPROM each time you access it (checkout continuous write on the EEPROM datasheet).
A possible work-around the delay_ms(100) would be something as follows (assuming 4MHz clock):
Code: | int1 break_flag = 0;
setup_timer_1 ( T1_INTERNAL | T1_DIV_BY_2 );
set_timer1(15539);
TMR1IF = 0;
while (!TMR1IF)
(
if(kbhit())
{
break_flag = 1;
break;
}
)
if (break_flag)
{
break_flag = 0;
break
} |
|
|
|
A_L_E_X
Joined: 21 Feb 2010 Posts: 11
|
|
Posted: Tue May 25, 2010 2:50 pm |
|
|
How can i remap the IO ports ? Do you have a link or a document ? |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Tue May 25, 2010 3:37 pm |
|
|
By "remap the i/o pins", he just means to specify the TX and RX pins
for the hardware UART in the #use rs232() statement. Example:
Code: | #use rs232(baud=9600, xmit=PIN_B2, rcv=PIN_B1, ERRORS) |
But, in an earlier post, you said you can't do that because the Tx and Rx
pins are already used for some other purpose.
Another possible solution is to assign the 'rcv' to Pin B0. It has the
External Interrupt feature on that pin. You could cause an interrupt
when you get the start bit for the incoming byte on RS232. Then get
the character in the #int_ext interrupt routine. Set a global flag to
TRUE inside the interrupt routine. Then poll the flag inside your while()
loop in main. When the flag == TRUE, then exit the loop. Also set the
flag to FALSE at that time. Also initialize the flag to FALSE at the start
of main(). |
|
|
tesla80
Joined: 23 May 2007 Posts: 81
|
|
Posted: Wed May 26, 2010 4:36 am |
|
|
Additionally, the RX pin must be configured as input. |
|
|
A_L_E_X
Joined: 21 Feb 2010 Posts: 11
|
|
Posted: Mon Jun 28, 2010 5:56 pm |
|
|
Looks like the code
Code: | if(kbhit())
{
break;
} |
works only in Proteus. In real hardware it doesn't work and I don't know why.
Also I've looked at my code and looks like I can use the receive pin from the the hardware uart. Can I use hardware now even though the transmit pin is not an uart pin ?
Code: | #use rs232(baud=9600,parity=N,xmit=PIN_B0,rcv=PIN_B1) |
Also, can I use the uart to make an interrupt ? Can you give me an example ? |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Mon Jun 28, 2010 7:12 pm |
|
|
Quote: |
I use hardware now even though the transmit pin is not an uart pin ?
#use rs232(baud=9600,parity=N,xmit=PIN_B0,rcv=PIN_B1)
|
That line will not generate code to use the hardware UART.
The hardware UART is on pins B2 and B1 in the 16F648A.
See the pin diagrams near the front of the data sheet.
http://ww1.microchip.com/downloads/en/DeviceDoc/40044G.pdf
If you use the hardware UART, then kbhit() will work reliably. |
|
|
A_L_E_X
Joined: 21 Feb 2010 Posts: 11
|
|
Posted: Tue Jun 29, 2010 12:27 pm |
|
|
So there is there any other solution ? I must use those pins. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Tue Jun 29, 2010 12:32 pm |
|
|
Is pin B2 unused ? |
|
|
A_L_E_X
Joined: 21 Feb 2010 Posts: 11
|
|
Posted: Thu Jul 01, 2010 12:20 pm |
|
|
All pins are used. In fact i've already made the board and I don't want to do it again. I'm looking for a simpler solution like making the modification in the software. |
|
|
|