|
|
View previous topic :: View next topic |
Author |
Message |
bschriek
Joined: 18 Dec 2007 Posts: 80
|
Array |
Posted: Sat Oct 24, 2020 3:46 am |
|
|
IDE 5.092 PCW 16F1939
I do a compare between two array's, bit by bit to detect if something is changed.
This worked fine 2 years ago and now with the latest compiler it doesn't.
This instruction doesn't work anymore: if ( (out_ [i]) != (out_backup [i]) )
Small piece of code because I know exactly what line causes the problem:
//----------------------------------------------------------------------
Code: | short out_ [17] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
short out_backup [17] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
int test=0, surge_counter=0;
int i, y=0, z=0;
for (i=16; i>=1; i--) // 16 to 1.
{
printf("%u ",out_ [i]);
printf("%u ",out_backup [i]);
printf(",");
if ( (out_ [i]) != (out_backup [i]) )
{
set_pwm1_duty(0);
surge_counter = 0;
}
out_backup [i] = out_ [i];
if (out_ [i] == 1)
output_high(SER_IN);
else
output_low (SER_IN);
delay_us(20);
output_high(SRCK); // Serial-in clock at rising edge.
delay_us(20);
output_low(SRCK); // Serial-in clock at rising edge
} |
//----------------------------------------------------------------------
If I replace the variable by a constant like the line underneath it works well again.
if ( (out_ [8]) != (out_backup [8]) )
The name of the variable "out_" and "out_backup" are not the problem.
I replaced the name of these variables and the problem is still there.
short or int1 for i has no effect.
Serial monitor output:
surge_counter: 10 ,
1 1 ,1 1 ,1 1 ,1 1 ,1 1 ,1 1 ,0 0 ,0 0 ,1 1 ,0 0 ,0 0 ,0 0 ,0 0 ,0 0 ,0 0 ,0 0 ,
1 1 ,1 1 ,1 1 ,1 1 ,1 1 ,1 1 ,0 0 ,0 0 ,0 1 ,0 0 ,0 0 ,0 0 ,0 0 ,0 0 ,0 0 ,0 0 ,
1 1 ,1 1 ,1 1 ,1 1 ,1 1 ,1 1 ,0 0 ,0 0 ,0 0 ,0 0 ,0 0 ,0 0 ,0 0 ,0 0 ,0 0 ,0 0 ,
1 1 ,1 1 ,1 1 ,1 1 ,1 1 ,1 1 ,0 0 ,0 0 ,0 0 ,0 0 ,0 0 ,0 0 ,0 0 ,0 0 ,0 0 ,0 0 ,
1 1 ,1 1 ,1 1 ,1 1 ,1 1 ,1 1 ,0 0 ,0 0 ,1 0 ,0 0 ,0 0 ,0 0 ,0 0 ,0 0 ,0 0 ,0 0 ,
surge_counter: 10 ,
1 1 ,1 1 ,1 1 ,1 1 ,1 1 ,1 1 ,0 0 ,0 0 ,1 1 ,0 0 ,0 0 ,0 0 ,0 0 ,0 0 ,0 0 ,0 0 ,
1 1 ,1 1 ,1 1 ,1 1 ,1 1 ,1 1 ,0 0 ,0 0 ,1 1 ,0 0 ,0 0 ,0 0 ,0 0 ,0 0 ,0 0 ,0 0 ,
1 1 ,1 1 ,1 1 ,1 1 ,1 1 ,1 1 ,0 0 ,0 0 ,1 1 ,0 0 ,0 0 ,0 0 ,0 0 ,0 0 ,0 0 ,0 0 ,
1 1 ,1 1 ,1 1 ,1 1 ,1 1 ,1 1 ,0 0 ,0 0 ,0 1 ,0 0 ,0 0 ,0 0 ,0 0 ,0 0 ,0 0 ,0 0 ,
1 1 ,1 1 ,1 1 ,1 1 ,1 1 ,1 1 ,0 0 ,0 0 ,0 0 ,0 0 ,0 0 ,0 0 ,0 0 ,0 0 ,0 0 ,0 0 ,
surge_counter: 10 ,
1 1 ,1 1 ,1 1 ,1 1 ,1 1 ,1 1 ,0 0 ,0 0 ,1 0 ,0 0 ,0 0 ,0 0 ,0 0 ,0 0 ,0 0 ,0 0 ,
1 1 ,1 1 ,1 1 ,1 1 ,1 1 ,1 1 ,0 0 ,0 0 ,1 1 ,0 0 ,0 0 ,0 0 ,0 0 ,0 0 ,0 0 ,0 0 ,
1 1 ,1 1 ,1 1 ,1 1 ,1 1 ,1 1 ,0 0 ,0 0 ,1 1 ,0 0 ,0 0 ,0 0 ,0 0 ,0 0 ,0 0 ,0 0 ,
1 1 ,1 1 ,1 1 ,1 1 ,1 1 ,1 1 ,0 0 ,0 0 ,1 1 ,0 0 ,0 0 ,0 0 ,0 0 ,0 0 ,0 0 ,0 0 ,
1 1 ,1 1 ,1 1 ,1 1 ,1 1 ,1 1 ,0 0 ,0 0 ,1 1 ,0 0 ,0 0 ,0 0 ,0 0 ,0 0 ,0 0 ,0 0 ,
You can see the code: if ( (out_ [i]) != (out_backup [i]) ) doesn't work because the variable "surge_counter" is not changed.
Who has an idea? |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9228 Location: Greensville,Ontario
|
|
Posted: Sat Oct 24, 2020 4:48 am |
|
|
I don't see where surge_counter became 10 or printed out...
then again your code WAS black and text 1st time I saw it, 10 minutes later, it's now green and 'code'.....
Jay |
|
|
bschriek
Joined: 18 Dec 2007 Posts: 80
|
|
Posted: Sat Oct 24, 2020 8:21 am |
|
|
Hello Temtronic,
I know, this is just a few lines of code.
Code: |
i=8;
if ( (out_ [i]) != (out_backup [i]) ) doesn't work.
And
if ( (out_ [8]) != (out_backup [8]) ) does work.
|
But I will start a new project with only a few lines of code so I can post the whole program.
Thank you in advance, |
|
|
bschriek
Joined: 18 Dec 2007 Posts: 80
|
Short Code |
Posted: Sat Oct 24, 2020 9:19 am |
|
|
Who can tell me why it doesn't print "SOLVED" ??
Code: |
#include <16F1939.H>
#Fuses HS,NOWDT,PLL_SW
#Fuses PUT,NOMCLR,NOPROTECT,NOCPD
#Fuses BROWNOUT,NOCLKOUT,NOIESO
#Fuses NOFCMEN,NOWRT
#Fuses NOVCAP,NOSTVREN,BORV25
#Fuses NODEBUG,NOLVP
#use delay(clock=12000000)
int i=0;
short out_ [17] = {0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0}; // [8] is different.
short out_backup [17] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; //
//////////////////////////////// MAIN LOOP /////////////////////////////////////
void main()
{
setup_oscillator(OSC_PLL_OFF);
SETUP_DAC(DAC_OFF);
setup_comparator(NC_NC_NC_NC);
#use rs232(ICD, xmit=PIN_B7) // Dit werkt met ICD-U64 en Telnet input 38400b. 5 Sec delay!
delay_ms(1000);
printf("Start");
printf("\r\n");
while(1)
{
delay_ms(1000);
for (i=16; i>=1; i--) // 16 t/m 1.
{
printf("%u ",i);
printf("%u ",out_ [i]);
printf("%u ",out_backup [i]);
printf(", ");
if ( (out_ [i]) != (out_backup [i]) )
{
printf("SOLVED");
}
}
if ( (out_ [8]) != (out_backup [8]) ) //Different
{
printf("8");
}
if ( (out_ [7]) == (out_backup [7]) ) //Same
{
printf("7");
}
printf("\r\n");
}
}
|
RS232 output:
Start
16 0 0 , 15 0 0 , 14 0 0 , 13 0 0 , 12 0 0 , 11 0 0 , 10 0 0 , 9 0 0 , 8 1 0 , 7 0 0 , 6 0 0 , 5 0 0 , 4 0 0 , 3 0 0 , 2 0 0 , 1 0 0 , 87
16 0 0 , 15 0 0 , 14 0 0 , 13 0 0 , 12 0 0 , 11 0 0 , 10 0 0 , 9 0 0 , 8 1 0 , 7 0 0 , 6 0 0 , 5 0 0 , 4 0 0 , 3 0 0 , 2 0 0 , 1 0 0 , 87
16 0 0 , 15 0 0 , 14 0 0 , 13 0 0 , 12 0 0 , 11 0 0 , 10 0 0 , 9 0 0 , 8 1 0 , 7 0 0 , 6 0 0 , 5 0 0 , 4 0 0 , 3 0 0 , 2 0 0 , 1 0 0 , 87
16 0 0 , 15 0 0 , 14 0 0 , 13 0 0 , 12 0 0 , 11 0 0 , 10 0 0 , 9 0 0 , 8 1 0 , 7 0 0 , 6 0 0 , 5 0 0 , 4 0 0 , 3 0 0 , 2 0 0 , 1 0 0 , 87 |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Sat Oct 24, 2020 11:59 am |
|
|
For those who want to work on this problem, I have striped his program
down to a simplified version that shows the problem. (I can't do anymore
now because I have an appointment soon).
This program will print the following when compiled with CCS vs. 5.096
and run in MPLAB vs. 8.92 simulator:
Changing the int1 arrays to int8 makes it work OK (ie., it prints SOLVED).
Test program:
Code: | #include <16F1939.H>
#use delay(crystal=12M)
#use rs232(baud=9600, UART1, ERRORS)
int8 i=0;
int1 out[1] = 1;
int1 out_backup[1] = 0;
//==============================
void main()
{
printf("Start \r");
i = 0;
if(out[i] != out_backup[i])
printf("SOLVED \r");
printf("Done \r");
printf("\r");
while(TRUE);
} |
|
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9228 Location: Greensville,Ontario
|
|
Posted: Sat Oct 24, 2020 2:15 pm |
|
|
My gut was telling me it HAS to be a 'bit' problem, and PCMP's 'byte' version works, kinda proves that.
While using 17 bytes to store 17 bits of inforamtion may be wasteful, that PIC does have 1024 of RAM, so it shouldn't be a problem.
I did the same thing, 2 decades ago. It was just easier than trying to keep the bits straight.
One possible cause 'might' be that the array isn't on a page of memory ? I don't know if the compiler is putting all 17 bits into 3 contiguous bytes but 'something' is wrong. A dump of the listing to see what the actual code is should prove useful...
For the time being, I'd use bytes and move on......
leave the 'head scratching - 3rd pot of coffee' for another day....
Jay |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Sat Oct 24, 2020 8:01 pm |
|
|
It's a bug in ASM code for the comparison line. (CCS vs. 5.096)
CCS would probably call this an optimization bug.
This bug should be reported to CCS.
Code: | ...... i = 0;
003C: CLRF i
......
...... if(out[i] != out_backup[i])
003D: MOVF i,W
003E: MOVWF array_index
003F: MOVLW out+-2
0040: MOVWF @READBITA.P1+1
0041: MOVLW out+-32
0042: MOVWF @READBITA.P1
0043: CALL @READBITA // Read value of out[i]
0044: MOVF @78,W // It is returned in @78
0045: MOVWF @@25 // Save value of out[i] in @@25
0046: MOVF i,W
0047: MOVWF array_index
0048: MOVLW out_backup+-3
0049: MOVWF @READBITA.P1+1
004A: MOVLW out_backup+-32
004B: MOVWF @READBITA.P1
004C: CALL @READBITA // Read value of out_backup[i]
// It is returned in @78
004D: MOVF 25,W // w = value of out[i]
004E: ANDLW 01 // w = w & 1
004F: MOVWF @78 // *** Bug: result of out_backup[i] is over-written
// *** by value of out[i]
0050: ANDLW 01
0051: SUBWF @78,W // Compare the two array values
0052: BTFSC STATUS.Z // Skip next line if they are !=
0053: GOTO 056
.................... result = TRUE; // if they are !=
0054: MOVLW 01
0055: MOVWF result
....................
.................... while(TRUE);
0056: GOTO 056
.... |
A work-around is to put the result of out1[i] in a temporary variable as
shown below in bold. Then it works.
Quote: |
#include <16F1939.H>
#use delay(crystal=12M)
#use rs232(baud=9600, UART1, ERRORS)
int8 i=0;
int1 out[1] = 0;
int1 out_backup[1] = 1;
//==============================
void main()
{
int8 result = FALSE;
int1 temp1;
i = 0;
temp1 = out[i];
if(temp1 != out_backup[i])
result = TRUE;
printf("result = %u \r", result);
while(TRUE);
} |
|
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19516
|
|
Posted: Sun Oct 25, 2020 1:58 am |
|
|
PCM, he says he is using 5.092. I tested with this version, and it has a slightly different error!...
The result of the READBITA call is read from the wrong register on the
second call on this version.
There is a 'sneaky' fix that applies in both cases:
Code: |
#include <16F1939.H>
#Fuses HS,NOWDT,PLL_SW
#Fuses PUT,NOMCLR,NOPROTECT,NOCPD
#Fuses BROWNOUT,NOCLKOUT,NOIESO
#Fuses NOFCMEN,NOWRT
#Fuses NOVCAP,NOSTVREN,BORV25
#Fuses NODEBUG,NOLVP
#use delay(clock=12000000)
int i=0;
short out_ [24] = {0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0}; // [8] is different.
short out_backup [24] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; //
//////////////////////////////// MAIN LOOP /////////////////////////////////////
void main()
{
setup_oscillator(OSC_PLL_OFF);
SETUP_DAC(DAC_OFF);
setup_comparator(NC_NC_NC_NC);
#use rs232(UART1, ERRORS) // Dit werkt met ICD-U64 en Telnet input 38400b. 5 Sec delay!
delay_ms(1000);
printf("Start");
printf("\r\n");
while(TRUE)
{
delay_ms(1000);
for (i=16; i>=1; i--) // 16 t/m 1.
{
printf("%u ",i);
printf("%u ",out_ [i]);
printf("%u ",out_backup [i]);
printf(", ");
if ( (out_ [i]==TRUE) != (out_backup [i]) )
{
printf("SOLVED");
}
}
if ( (out_ [8]) != (out_backup [8]) ) //Different
{
printf("8");
}
if ( (out_ [7]) == (out_backup [7]) ) //Same
{
printf("7");
}
printf("\r\n");
}
}
|
Forcing the logic level test makes it store the value correctly.
It is interesting that this has been wrong for a while. It's OK in 5.070,
but wrong in 5.080.
It is interesting, since I have seen 'issues' with using logic tests on bit
variables several times recently, and have started to always use a
test against TRUE/FALSE like this to avoid the problem. |
|
|
bschriek
Joined: 18 Dec 2007 Posts: 80
|
|
Posted: Sun Oct 25, 2020 3:28 am |
|
|
Thank you all for your help!
I'm happy it's not because of me but because of a stupid bug.
And it's not the fist time a new Compiler version causes problems
I will use the suggested extra variable for now.
Thanks again, |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9228 Location: Greensville,Ontario
|
|
Posted: Sun Oct 25, 2020 4:43 am |
|
|
yeesh, this is a 'bit' much for me....depending on the compiler version a DIFFERENT bug appears.....sigh.
My concern is WHAT happens when the next upgrade is done.....will it work or not ???
While there are 'fixes' to do the bit by bit testing, it seems to me easier to just use bytes. Although it takes 14 more bytes of RAM, it does work and I suspect actual codespace is far less AND faster testing.
Jay |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19516
|
|
Posted: Sun Oct 25, 2020 7:16 am |
|
|
You don't need to waste an extra variable. Just do the logic test as I show.
It actually generates what is effectively a 'temporary' variable to hold the
result of the test, but it is in the scratch area, so doesn't waste any RAM.
In fact there is another solution, use XOR (^) instead of !=.
The XOR operator, returns '1' (TRUE), if the two values are different,
but '0' if they are the same. So:
if (out_[i] ^ out_backup [i]) //true if different
Merrily solves the problem, adds no extra variable, and is smaller than
the other solutions.
It actually gives exactly the same code size as the faulty version, but works. |
|
|
bschriek
Joined: 18 Dec 2007 Posts: 80
|
|
Posted: Sun Oct 25, 2020 1:18 pm |
|
|
Perfect, thanks. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Mon Nov 02, 2020 3:59 pm |
|
|
CCS support says the bug discussed in this thread has been fixed,
per their message below:
Quote: | It has already been fixed for the 5.097 release. |
|
|
|
bschriek
Joined: 18 Dec 2007 Posts: 80
|
|
Posted: Tue Nov 03, 2020 2:31 am |
|
|
Ok but the message "already been fixed" is a bit predictive.
The latest PCW version for download is 5.096.
But let's wait and see when the new version is available.
Many thanks, |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Tue Nov 03, 2020 4:51 am |
|
|
They have multiple bugs to fix. They've fixed this one.
They are working on others. When the get them all done, they
will release them as vs. 5.097. |
|
|
|
|
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
|