|
|
View previous topic :: View next topic |
Author |
Message |
rudy
Joined: 27 Apr 2008 Posts: 168
|
STRSTR PROBLEM |
Posted: Mon Sep 18, 2023 6:26 am |
|
|
Hi, I am finalizing a program to read and control a SIM800 module, but strstr function seems to not work properly in a specific location of the routine. This is how I declare variables and buffers.
Code: | #include <18F2550.h>
#fuses INTRC, PLL5, CPUDIV1, NOWDT, NOFCMEN, NOIESO, NOCPD, NOPROTECT, NOLVP, NODEBUG, NOPUT, NOBROWNOUT, NOMCLR
#device PASS_STRINGS=IN_RAM
#use delay(clock=8000000)
#use I2C(MASTER, I2C1)
#use RS232(BAUD=9600, UART1, ERRORS)
#byte PORTA=0xF80
#byte PORTB=0xF81
#byte PORTC=0xF82
#byte PORTE=0xF84
///////////////////////SMS FUNCTIONS/////////////////////
// XXXX PASSWORD -> FIRS 4 CHARACTERS ON ALL MSG
// RLX ON -> TURN ON X RELAYS
// RLX OFF -> TURN OFF X RELAYS
// ALL ON# -> ALL RELAYS ON
// ALL OFF# -> ALL RELAYS OFF
// INVERT# -> INVERTED RELAYS STATES
// RST# -> RESET SMS COUNTERS AND SIM CARD STORAGE SMS
// NEW# -> CHANGE SMS PASSWORD, OLD PASSWORS MUST BE PROVIDED
/////////////////////////////////////////////////////////
/////////////////SYSTEM VARS////////////////////
int D1, D2, D3, D4, D5, FLAG_0, FLAG_1, FLAG_2=0X00;
int AUX_0=0X00;
/////////////////LCD VARS////////////////////////
int PX_X, PX_Y, LCD_OPR, PLT=0X4B;
/////////////////GSM VARS////////////////////////
int BFR_CNT, AUX_GSM_0=0X00;
long SMS_INN, SMS_OUT;
char TMP_CHAR;
char GSM_BFR[128]=""; //GSM BUFFER
char GSM_PASS[5]=""; //GSM PASSWORD
char * PCH;
/////////////////TEMPERATURE VARS/////////////////
long TEMPNOW=0X0000;
|
In the beginning of the routine to check SMS, I use this:
Code: | PCH=strstr(GSM_BFR,"+CMT"); //AVOID "OK" OR MISMATCH RETURN FROM SIM800 AFTER PUTC(0x1A)
if(PCH!=NULL)SMS_INN++; //SMS INCOMING UPDATE AVOID "OK" AND SO...
|
Works fine, all +CMT is detected properly, but now I need to check if the incoming SMS have the PASSWORD, a 4 byte char string, in other to enter effectively in the code to "answer" to the incoming SMS, and that’s is the problem. Sometimes it works, sometimes it not. This is the line I created to do this:
Code: | PCH=strstr(GSM_BFR,GSM_PASS); //CHECK GSM KEY
if(PCH!=NULL)GSM_KEY=1; //GSM_KEY=1;
if(GSM_KEY) //PASSWOR ACCEPTED
|
Somehow, the GSM_PASS seems not to be found in the GSM_BFR, and I really don’t know how.
1 – Do I really need the NULL '\0' terminator at the end of the GSM_PASS string?
2 – This line “PCH=strstr(GSM_BFR,GSM_PASS);” is correct?
3 – How may I see or check if there is an stack overflow issue, can somebody help me?
Regards; |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19552
|
|
Posted: Mon Sep 18, 2023 7:42 am |
|
|
First thing, tidy up your clock settings. The PLL and the CPUDIV, do not
apply when using the internal oscillator. It should default to 8MHz, but
make sure.
So:
Code: |
#include <18F2550.h>
#fuses NOWDT, NOFCMEN, NOIESO, NOCPD, NOPROTECT, NOLVP, NODEBUG, NOPUT, NOBROWNOUT, NOMCLR, STVREN
#device PASS_STRINGS=IN_RAM
#use delay(INTERNAL=8MHz)
#use I2C(MASTER, I2C1)
#use RS232(BAUD=9600, UART1, ERRORS)
|
The 'INTERNAL' syntax sets all the fuses etc., to suit the internal oscillator.
Now, we can't tell if the syntax is right. You don't show where/how you are
putting the string into the GSM_PASS array.
Yes, a string is just a character array, _with a null terminator_. It is not
a string as such until this exists. However some operations will add this
for you. Depending on how you are writing the data, it is possible that
you are overflowing the array by adding an extra terminator where one
is not needed. You need to show us how you are writing this string.
The "" generates a blank string with a null terminator. Remember though
that if the blank password is (for example), four spaces, this would need
to be declared as " ". With GSM_PASS as currently shown, strstr will
not work, since it does not search for the terminating character, and you
show GSM_PASS containing nothing except the terminator. The function
will just retiurn 0 when this is the case, whatever is in the other string.
On the stack, add the fuse STVREN. This will make the chip reset if a
stack overflow occurs. The PIC18, does not have a software stack (so the
stack is not used for variables), it only has a function call stack. So a
stack overflow as a result of code, is not likely to happen. How many stack
levels are needed for the functions is displayed at the top of the listing
file after compilation. Open this.
About ten lines down it'll have a line saying 'Stack used x locations'.
The limit is 31 locations on this chip, but keep it a couple less if using an
ICD. |
|
|
rudy
Joined: 27 Apr 2008 Posts: 168
|
|
Posted: Mon Sep 18, 2023 8:01 am |
|
|
Well, thanks for helping me, Ttelmah.
I fill the GSM_PASS this way:
Code: | void MAIN()
{
SETUP_ADC_PORTS(NO_ANALOGS);
SETUP_COMPARATOR(NC_NC_NC_NC);
SETUP_COUNTERS(RTCC_INTERNAL,RTCC_DIV_1);
SETUP_TIMER_1(T1_INTERNAL|T1_DIV_BY_8);
SETUP_TIMER_2(T2_DISABLED,0XFF,16);
SETUP_TIMER_3(T3_DISABLED);
SET_TRIS_A(0b11111111);
SET_TRIS_B(0b11111111);
SET_TRIS_C(0b11111111);
SET_TRIS_E(0b11111111);
PORT_B_PULLUPS(0b00000000);
DELAY_MS(500);
GSM_INIT();
LCD_INIT();
LCD_CLS(0, 0X85, 0XB0, 0XB7, 0B0000000); //X1, X2, Y1, Y2, COLOR
LCD_SCREEN_01();
TS_INIT();
DELAY_MS(100);
TS_INIT();
TS_CONVERT();
//BOOT START
D1=READ_EEPROM(0X00); //READ BOOT STATE
if(!D1) //D0=0, BOOTED BEFORE
{
FLAG_0=READ_EEPROM(0X01); //RELES STATES
D2=READ_EEPROM(0X02); //SMS_INN HIGH BYTE
D3=READ_EEPROM(0X03); //SMS_INN LOW BYTE
D4=READ_EEPROM(0X04); //SMS_OUT HIGH BYTE
D5=READ_EEPROM(0X05); //SMS_OUT LOW BYTE
SMS_INN=MAKE16(D2,D3); //MAKE SMS_INN
SMS_OUT=MAKE16(D4,D5); //MAKE SMS_OUT
for(D1=0;D1<4;D1++)GSM_PASS[D1]=READ_EEPROM(D1+0X06); //GSM PASSWORD
}
else //D0=0XFF -> FIRST BOOT
{
FLAG_0=0X01; //ALL RELES OFF + EE_UPD=1
SMS_INN=0X0000; //SMS_INN=0X0000
SMS_OUT=0X0000; //SMS_OUT=0X0000
GSM_PASS="1234"; //RESET GSM PASSWAORD
}
GSM_PASS[4]='\0'; //GSM_PASS NULL TERMINATOR
LCD_TMP=1;
LCD_SMS=1;
LCD_RLS=1;
BFR_CNT=0;
BFR_CLS();
ENABLE_INTERRUPTS(INT_TIMER1);
ENABLE_INTERRUPTS(INT_RDA);
ENABLE_INTERRUPTS(GLOBAL);
|
So, when first BOOT, the EEPROM Address 0X00 will be 0XFF, and I write direct to the GSM_PASS the default password “1234” and a NULL terminator at the end.
In the GSM response routine, there is a function to CHANGE the default password, if the SMS message contains the string “NEW#” as follows:
Code: | //PASSWORD CHANGE
PCH=strstr(GSM_BFR,"NEW#"); //STRING => NEW#
if(PCH!=NULL)
{
for(D1=0;D1<120;D1++)
{
if((GSM_BFR[D1]==0X4E)&&(GSM_BFR[D1+1]==0X45)&&(GSM_BFR[D1+2]==0X57)&&(GSM_BFR[D1+3]==0X23)) //DETECT "NEW#"
{
GSM_PASS[0]=GSM_BFR[D1+5];
GSM_PASS[1]=GSM_BFR[D1+6];
GSM_PASS[2]=GSM_BFR[D1+7];
GSM_PASS[3]=GSM_BFR[D1+8];
GSM_PASS[4]='\0'; //GSM_PASS NULL TERMINATOR
NEW_PASS=1; //NEW PASSWORD
break;
}
}
}
|
Please help me to solve this matter.
Regards, |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19552
|
|
Posted: Mon Sep 18, 2023 10:28 am |
|
|
Major issue here:
GSM_PASS="1234"; //RESET GSM PASSWAORD
That is not how to change a string. You can set a string like this when
it is declared as a variable, but you cannot set a string 'inline' like this.
You have to use:
strcpy(GSM_PASS, "1234"); |
|
|
rudy
Joined: 27 Apr 2008 Posts: 168
|
|
Posted: Mon Sep 18, 2023 3:38 pm |
|
|
Ttelmah, thanks. I will do that. But when I change GSM_PASS on the go, so I have to write '\0' to the last position or not?
Another issue is that when I use the FUSES as this:
Quote: | #fuses INTRC, NOWDT, NOFCMEN, NOIESO, NOCPD, NOPROTECT, NOLVP, NODEBUG, NOPUT, NOBROWNOUT, NOMCLR, STVREN | The processor goes too slow, But when I add PPL5 and CPUDIV1, it runs well.
But Let's focus on the Code: | PCH=strstr(GSM_BFR,GSM_PASS); //CHECK GSM KEY | Why this instruction sometimes works and sometimes not, that is my major issue. Reading the CCS Manual, it says: "s1 and s2 are pointers to an array of characters (or the name of an array). Note that s1 and s2 MAY NOT BE A CONSTANT (like "hi")", and it is not! This problem is really an issue that I cannot solve by myself, need an expert to help me.
Regards; |
|
|
rudy
Joined: 27 Apr 2008 Posts: 168
|
|
Posted: Mon Sep 18, 2023 9:10 pm |
|
|
Well, I take off all NULL terminator insertion in the GSM_PASS string, but not sure this was the problerm, so I make this: (Call it BRUTE FORCE)
Code: | for(D1=0;D1<100;D1++) //DETECT PASSWORD - BRUTE FORCE
{
if((GSM_BFR[D1]==GSM_PASS[0])&&(GSM_BFR[D1+1]==GSM_PASS[1])&&(GSM_BFR[D1+2]==GSM_PASS[2])&&(GSM_BFR[D1+3]==GSM_PASS[3]))
{
GSM_KEY=1;
break;
}
} |
I am testing it, till now, no issues, working smooth and pritty well.
Regards; |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19552
|
|
Posted: Wed Sep 20, 2023 10:59 am |
|
|
On the clock setup, you are missing the second key point, that you have
to change the clock setup:
#use delay(INTERNAL=8MHz)
INTERNAL, not CLOCK
It is this that makes the setting work correctly.
On the string terminators, if you use the string functions, the terminator
is automatically generated and added. You should not be adding one yourself.
It'd cause a problem with your string done using the = allocation, since
the pointer then no longer points to a real string, but instead points to
the virtual buffer created by the compiler. Writing explicitly to this would
cause disaster. |
|
|
rudy
Joined: 27 Apr 2008 Posts: 168
|
|
Posted: Wed Sep 20, 2023 6:43 pm |
|
|
Hum...... Will be that the reason off all problems? Because I was simple running at the wrong clock frequency speed, and the errors I got was totally “random” with no logical explanation.
Thaks for now! I will test it!
Regards; |
|
|
|
|
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
|