View previous topic :: View next topic |
Author |
Message |
Graham Webb
Joined: 18 Apr 2008 Posts: 9
|
printf not working with for loop |
Posted: Thu May 20, 2010 8:12 am |
|
|
When I add for loops to my code ALL my printf functions cease to function. Even the printf functions that come before the for loops. But the rest of the code works fine. If I remove the for loops, the printf functions work.
What is going on?!
This is a fragment of the main code .. it receives some values on interrupt and sets some command flags that drives the case structure.
Code: | #include <C:\Program files\PICC\devices\16f876a.H>
#include <C:\Program files\PICC\drivers\stdio.h>
#fuses HS,NOWDT,NOPROTECT,NOLVP, NOBROWNOUT
#use delay(clock=20000000)
#use RS232(Baud=9600,XMIT=PIN_C6,RCV=PIN_C7, ERRORS)
void main(void)
{
current_state = STOPPED;
initialise_pic();
pulse_width = 40;
printf("\tTest \n\n\r");
while (true)
{
if(command_status)
{
get_pc_command();
command_status = NO_COMMAND;
}
switch(current_state)
{
printf("\t current_state %s\n\n\r", current_state);
case STIMULATING :
printf("\t Stimulating \n\n\r");
output_high(PIN_C2); //Blue LED
output_high(PIN_B7); //test pin
for(i=0;i<pulse_width;++i)
{
delay_us(1);
}
output_low(PIN_B7); //test pin
for(n=0;n<off_time;++n)
{
delay_us(1);
}
break;
case STOPPED :
printf("\t Stopped \n\n");
output_low(PIN_B7); //test pin
output_low(PIN_C2); //Blue LED
break;
case ILLEGAL_COMMAND :
printf("\t illegal command \n\n\r");
break;
}
} |
|
|
|
Graham Webb
Joined: 18 Apr 2008 Posts: 9
|
|
Posted: Thu May 20, 2010 8:26 am |
|
|
I didn't have data direction registers! But how that should be altered with for loops defeats me. |
|
|
rnielsen
Joined: 23 Sep 2003 Posts: 852 Location: Utah
|
|
Posted: Thu May 20, 2010 8:32 am |
|
|
You should post a _compilable_ code in case we want to check things out ourselves. You don't show what initialise_pic() does. This code may not be necessary but I always insert some initializing code:
Code: | setup_adc_ports(NO_ANALOGS);
setup_adc(ADC_OFF);
setup_spi(FALSE);
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
setup_timer_1(T1_DISABLED);
setup_timer_2(T2_DISABLED,0,1);
setup_comparator(NC_NC_NC_NC);
setup_vref(FALSE);
enable_interrupts(INT_RDA);
enable_interrupts(GLOBAL);
|
Plus, I would have an interrupt routine for your serial port:
Code: | #int_RDA
RDA_isr()
{
}
|
That may be why things hang up because you don't have that ISR defined.
Ronald |
|
|
Graham Webb
Joined: 18 Apr 2008 Posts: 9
|
|
Posted: Thu May 20, 2010 8:41 am |
|
|
That was a fragment, this is the complete code. The problem still exists :-(
Not very tidy, but I think it's all there ..
Code: |
#include <C:\Program files\PICC\devices\16f876a.H>
#include <C:\Program files\PICC\drivers\stdio.h>
#fuses HS,NOWDT,NOPROTECT,NOLVP, NOBROWNOUT
#use delay(clock=20000000)
#use RS232(Baud=9600,XMIT=PIN_C6,RCV=PIN_C7, BRGH1OK)
/***************************************************************************************************
FUNCTION PROTOTYPES
***************************************************************************************************/
void initialise_pic(void);
void get_pc_command(void);
int decimal_adjust_int(void);
long decimal_adjust_int16(void);
long decimal_adjust_int32(void);
/***************************************************************************************************
DECLARATIONS
***************************************************************************************************/
#define GD00 PIN_C0 //pin C0 = out
#define GD02 PIN_C1 //pin C1 = out
#define SPI_CS PIN_C2 //pin C2 = out
#define SPI_CLK PIN_C3 //pin C3 = out
#define SPI_DI PIN_C4 //pin C4 = out
#define SPI_DO PIN_C5 //pin C5 = out
#define TX PIN_C6 //pin C6 = out RS232 Tx
#define RX PIN_C7 //pin C7 = inp RS232 Rx
#define PORTA_DIRECTION 0b00000000
#define PORTB_DIRECTION 0b00000000
#define PORTC_DIRECTION 0b00000001
SET_TRIS_A(PORTA_DIRECTION);
SET_TRIS_B(PORTB_DIRECTION);
SET_TRIS_C(PORTC_DIRECTION);
char command_string[8];
byte status = 0;
#BIT COMMAND_STATUS = status.0
int current_state;
#define STIMULATING 0
#define STOPPED 1
#define ILLEGAL_COMMAND 3
#define NEW_COMMAND 1
#define NO_COMMAND 0
#define ON 1
#define OFF 0
int montage; //m
int intensity; //i
long pulse_width; //p
long off_time; //b
long i, n;
/***************************************************************************************************
FUNCTION main
***************************************************************************************************/
void main(void)
{
current_state = STOPPED;
initialise_pic();
pulse_width = 40;
while (true)
{
if(command_status)
{
get_pc_command();
command_status = NO_COMMAND;
}
switch(current_state)
{
printf("\t current_state %s\n\n\r", current_state);
case STIMULATING :
printf("\t Stimulating \n\n\r");
output_high(PIN_C2); //Blue LED
output_high(PIN_B7); //test pin
for(i=0;i<pulse_width;++i)
{
delay_us(1);
}
output_low(PIN_B7); //test pin
for(n=0;n<off_time;++n)
{
delay_us(1);
}
break;
case STOPPED :
// printf("\t Stopped \n\n");
output_low(PIN_B7); //test pin
output_low(PIN_C2); //Blue LED
break;
case ILLEGAL_COMMAND :
printf("\t illegal command \n\n\r");
break;
}
}
}
/***************************************************************************************************
FUNCTION : ISRs
Arguments : none
Return Value: none
Purpose : handles interrupts
***************************************************************************************************/
#INT_RDA
RS232_receive()
{
output_high(PIN_C1); //Green LED
gets(command_string);
command_status = NEW_COMMAND;
output_low(PIN_C1); //Green LED
}
/***************************************************************************************************
FUNCTION : get_pc_command
Arguments : none
Return Value: none
Purpose :
start s
stop x
intensity ixxx int
pulse width pxxxxx long
montage mxxxxx long
off time bxxxxxx long long?
***************************************************************************************************/
void get_pc_command(void)
{
switch(command_string[0])
{
case 's' :
current_state = STIMULATING;
printf("\t state change stimulating \n\n\r");
COMMAND_STATUS = NO_COMMAND;
break;
case 'x' :
current_state = STOPPED;
printf("\t state change stopped \n\n\r");
COMMAND_STATUS = NO_COMMAND;
break;
case 'm' :
montage = decimal_adjust_int();
printf("\t new value montage %i\n\n\r", montage);
COMMAND_STATUS = NO_COMMAND;
break;
case 'i' :
intensity = decimal_adjust_int();
printf("\t new value intensity %i\n\n\r", intensity);
COMMAND_STATUS = NO_COMMAND;
break;
case 'p' :
pulse_width = decimal_adjust_int16();
printf("\t new value pulse_width %lu\n\n\r", pulse_width);
COMMAND_STATUS = NO_COMMAND;
break;
case 'b' :
off_time = decimal_adjust_int32();
printf("\t new value off time %lu\n\n\r", off_time);
COMMAND_STATUS = NO_COMMAND;
break;
default :
current_state = ILLEGAL_COMMAND;
printf("\t state change ILLEGAL_COMMAND \n\n\r");
COMMAND_STATUS = NO_COMMAND;
break;
}
}
/***************************************************************************************************
FUNCTION : decimal_adjust_int
Arguments : 3 chars
Return Value: int8
Purpose : used for intensity
***************************************************************************************************/
int decimal_adjust_int(void)
{
return ((command_string[1] - 0x30) * 100) +
((command_string[2] - 0x30) * 10) +
(command_string[3] - 0x30);
}
/***************************************************************************************************
FUNCTION : decimal_adjust_int16
Arguments : 5 chars
Return Value: int16
Purpose : used for pulse_width
***************************************************************************************************/
long decimal_adjust_int16(void)
{
long temp;
long temp2 = 0;
temp = command_string[1] - 0x30;
temp2 += temp * 10000;
temp = command_string[2] - 0x30;
temp2 += temp * 1000;
temp = command_string[3] - 0x30;
temp2 += temp * 100;
temp = command_string[4] - 0x30;
temp2 += temp * 10;
temp = command_string[5] - 0x30;
temp2 += temp;
return(temp2);
}
/***************************************************************************************************
FUNCTION : decimal_adjust_int32
Arguments : 6 chars
Return Value: int32
Purpose : Used for off_time
***************************************************************************************************/
long decimal_adjust_int32(void)
{
long temp3;
long temp4 = 0;
temp3 = command_string[1] - 0x30;
temp4 += temp3 * 100000;
temp3 = command_string[2] - 0x30;
temp4 += temp3 * 10000;
temp3 = command_string[3] - 0x30;
temp4 += temp3 * 1000;
temp3 = command_string[4] - 0x30;
temp4 += temp3 * 100;
temp3 = command_string[5] - 0x30;
temp4 += temp3 * 10;
temp3 = command_string[6] - 0x30;
temp4 += temp3;
return(temp4);
}
/***************************************************************************************************
FUNCTION : Initialise_PIC
Arguments : none
Return Value: none
Purpose : Initialises PIC
***************************************************************************************************/
void initialise_pic(void)
{
ENABLE_INTERRUPTS(GLOBAL);
ENABLE_INTERRUPTS(INT_RDA);
printf("\t-------------------------- \n\r");
printf("\tStimulator Controller \n\r");
printf("\t-------------------------- \n\r"); | [/code] |
|
|
Wayne_
Joined: 10 Oct 2007 Posts: 681
|
|
Posted: Thu May 20, 2010 8:50 am |
|
|
Does this work :-
Code: |
switch(current_state)
{
printf("\t current_state %s\n\n\r", current_state);
case STIMULATING :
|
Putting code between a switch statement and the first case ?
Could be a problem.
Is it all the for loops in your code that cuase a problem ? |
|
|
Graham Webb
Joined: 18 Apr 2008 Posts: 9
|
|
Posted: Thu May 20, 2010 8:58 am |
|
|
Yes both. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19520
|
|
Posted: Fri May 21, 2010 3:05 am |
|
|
What compiler version?.
The 'odd' thing, is that you can get the code to compile, with the printf, inside the switch statement.
This is 'invalid' syntactically, and if I try your code as posted, the compiler immediately complains about this....
Best Wishes |
|
|
ckielstra
Joined: 18 Mar 2004 Posts: 3680 Location: The Netherlands
|
|
Posted: Fri May 21, 2010 5:19 am |
|
|
Just a few other issues, not related to your reported problem:
Code: | long decimal_adjust_int32(void) | In the CCS compiler a 'long' is an int16, not int32 as you intended. Result is that this function will wrong values for any input string larger than 65535.
Code: | SET_TRIS_A(PORTA_DIRECTION);
SET_TRIS_B(PORTB_DIRECTION);
SET_TRIS_C(PORTC_DIRECTION); | These are function calls and should be located inside a function and not at the global level where they are now.
Best is to remove these lines as the CCS compiler will automatically set the TRIS registers for you on every I/O operation. Setting the TRIS registers manually will save a bit of code space but this only works when you have the compiler directive '#use FAST_IO' at the start of your program.
Code: | #use RS232(Baud=9600,XMIT=PIN_C6,RCV=PIN_C7, BRGH1OK) | It's been a long time I saw the BRGH1OK directive. It doesn't hurt to have it in here but it is a feature only used on a few old processor models with UART hardware errors. I doubt it has any effect in your program.
To avoid problems with the UART stalling on receive buffer overflow it is good practice to add the ERRORS directive to the RS232 line.
Code: | #INT_RDA
RS232_receive()
{
output_high(PIN_C1); //Green LED
gets(command_string); | This code has several problems:
1) gets() has no check on buffer overflows. If your input string is longer than 8 characters (including the terminating 0), then you will overwrite random memory.
2) gets() shouldn't be used inside an interrupt routine. As the name of an interrupt implies it should be an action to break out of normal program flow, do its thing, and then as soon as possible continue with the normal program flow. Receiving multiple bytes from a UART is _very_ slow from a computer speed of view. See the example program ex_sisr.c for an elegant method to buffer incoming data in the background. |
|
|
|