Connect with us

help over microcontroller code

Discussion in 'Microcontrollers, Programming and IoT' started by aditya bhandari, Jun 16, 2014.

Scroll to continue with content
  1. aditya bhandari

    aditya bhandari

    5
    0
    Jun 10, 2014
    Hello,
    i am facing problems understanding the following C code for microcontroller. Actually the task is to configure an external GSM modem via serial microcontroller port but i am not able to get the coding exactly. can someone please help me understand it. also it would be nice if some one can give me the assemble code for same.


    void gsmcmdsend(unsigned char *cmd);

    unsigned char gsm_cmd3[]="AT&W";
    unsigned char gsm_cmd4[]="AT+CMGF";
    void gsmcmdsend(unsigned char *cmd)
    {
    unsigned char i;
    for(i=0;*cmd!='\0';i++)
    {
    SBUF=*cmd;
    while(TI==0);
    TI=0;
    cmd++;
    }
    SBUF=0x0A;
    while(TI==0);
    TI=0;
    SBUF=0x0D;
    while(TI==0);
    TI=0;
    while(RI==0);
    RI=0;
    }

    void main()
    {
    gsmcmdsend(gsm_cmd3);
    gsmcmdsend(gsm_cmd4);
    }
     
  2. kpatz

    kpatz

    247
    52
    Feb 24, 2014
    Here's a commented version of the above program:

    Code:
    void gsmcmdsend(unsigned char *cmd);
    
    unsigned char gsm_cmd3[]="AT&W";     // GSM modem commands
    unsigned char gsm_cmd4[]="AT+CMGF";
    void gsmcmdsend(unsigned char *cmd)
    {
      unsigned char i;
      for(i=0;*cmd!='\0';i++)  // Loop through command one character at a time
      {
        SBUF=*cmd;              // Put character in UART output buffer (start transmit)
        while(TI==0);          // Loop until transmit complete
        TI=0;                  // Clear transmit flag
        cmd++;                  // Increment pointer to next character
      }
    // This really should send 0D followed by 0A, it's backwards
      SBUF=0x0A;               // Send 0x0A (linefeed) to output buffer
      while(TI==0);              // Loop until transmit complete
      TI=0;                      // Clear transmit flag
      SBUF=0x0D;               // Send 0x0D (carriage return) to output buffer
      while(TI==0);              // Loop until transmit complete
      TI=0;                      // Clear transmit flag
      while(RI==0);            // Loop until receive complete
      RI=0;                    // clear receive flag
    }
    
    // This is executed first
    void main()
    {
      // Initialization of controller, peripherals needs to go here
      gsmcmdsend(gsm_cmd3);  // Send AT&W to GSM modem
      gsmcmdsend(gsm_cmd4);  // Send AT+CMGF to GSM modem
    }
    
    It has some flaws. main() needs to initialize things, such as peripherals (especially the UART used to send data to the modem), setting I/O pins to inputs or outputs, etc.

    Also, 0D usually is sent ahead of 0A (carriage return/line feed, not the opposite).

    At the end of gsmcmdsend(), there's a loop waiting for RI to be set. I don't know what micro is being used or how its UART works, but if data is being received, there is probably an RBUF register that needs to be read to prevent an overrun condition. Also, if the receiver is disabled, or the modem doesn't echo or respond, it's possible that RI will never get set, and your code will get stuck in a loop here.
     
    Harald Kapp, KrisBlueNZ and Ian like this.
  3. KrisBlueNZ

    KrisBlueNZ Sadly passed away in 2015

    8,393
    1,268
    Nov 28, 2011
    Good analysis kpatz!

    It's not usual to send the 0x0A at all; just the 0x0D is normally used on command strings. If the device has local echo enabled, it will echo a 0x0A along with the 0x0D, but modems do not normally expect to receive a 0x0A character.

    Also it's normal to have a separate function to send a character out the UART, which is called as necessary by higher-level functions. This function normally checks for UART transmit ready first, then sends the character and returns.

    Also, in the send-character loop, there is no need for the 'i' variable. The loop is normally written as a while() loop that just tests the character at the pointer for zero/non-zero.
     
  4. kpatz

    kpatz

    247
    52
    Feb 24, 2014
    I was going to point that out, but I figured I'd leave it out for simplicity's sake for now. It could have been done with: "for(;*cmd!='\0';cmd++)" as well.

    Also, depending on the micro, pointers may be less efficient than using arrays (lower-end PICs come to mind). Using "
    for(i=0; cmd[ i ]; i++)" may be more efficient. (I added spaces around "i" so the brackets aren't interpreted as BB code)
     
  5. KrisBlueNZ

    KrisBlueNZ Sadly passed away in 2015

    8,393
    1,268
    Nov 28, 2011
    He wasn't using an array. He was using a separate variable that would be incremented each time through the loop but never used!

    I think the most efficient loop (including on baseline PICs) would be
    Code:
    byte c;
    while ((c = *cmd++) != '\0')
      uart_tx(c);
     
  6. kpatz

    kpatz

    247
    52
    Feb 24, 2014
    Strings are arrays of chars, so that's what I was referring to. But in the original code, i wasn't used for anything so initializing and incrementing it would have been a waste.

    In XC8 for PIC at least, pointers add overhead since they could point to any number of things: variables in memory, registers, constants in flash ROM, data EEPROM, etc. The optimizer helps if you pay for it and make your pointer strongly typed enough (i.e. use a const char * to point to a const char array, for example).

    Without optimization the array method is more efficient, at least that's what I've seen with the limited C work I've done on PICs, and since the free version of XC8 has optimization disabled.

    I don't know what micro the OP is using. The optimization rules may be different on whatever it is (AVR perhaps?)
     
  7. aditya bhandari

    aditya bhandari

    5
    0
    Jun 10, 2014
    this is the entire program of my project. The project is SMS based homeautomation which activates or deactivates the home appliance connected to a relay when a particulat text is sent. also there is a LCD connected to see the process. I am getting all the portion of LCD interface but am unknown to the serial interface part. All i want to do is convert the code below to "assembly"

    #include<reg51.h>
    sbit rs=P3^7;
    sbit rw=P3^6;
    sbit e=P3^5;
    sbit fan=P1^0;
    sbit lgt=P1^1;
    void gsmcmdsend(unsigned char *cmd);
    void cmm(char value);
    void dat(char value);
    void compare();
    unsigned char card_id[96];
    unsigned char header[]="EFY";
    unsigned char gsm_cmd3[]="AT&W";
    unsigned char gsm_cmd4[]="AT+CMGF";
    void gsmcmdsend(unsigned char *cmd)
    {
    unsigned char i;
    for(i=0;*cmd!='\0';i++)
    {
    SBUF=*cmd;
    while(TI==0);
    TI=0;
    cmd++;
    }
    SBUF=0x0A;
    while(TI==0);
    TI=0;
    SBUF=0x0D;
    while(TI==0);
    TI=0;
    while(RI==0);
    RI=0;
    }
    void delay(int count) //Function to provide delay
    {
    int i,j;
    for(i=0;i<count;i++)
    for(j=0;j<1275;j++);
    }
    void cmm(char value)
    {
    P2 = value;
    rs=0;
    rw=0;
    e=1;
    delay(1);
    e=0;
    delay(1);
    return;
    }
    void dat(char value)
    {
    P2 =value;
    rs=1;
    rw=0;
    e=1;
    delay(1);
    e=0;
    delay(1);
    return;
    }
    void lcdin()
    { cmm(0x38);
    cmm(0x0e);
    cmm(0x01);
    cmm(0x06);
    cmm(0x85);
    return;
    }
    void recieve() //Function to recieve data serialy from RS232
    {
    unsigned char k;
    for(k=0;k<=87;k++)
    {
    while(RI==0);
    card_id[k]=SBUF;
    RI=0;
    }
    }
    void main()
    {
    int l,i;
    P1=0x00;
    lcdin();
    TMOD=0x20; //Enable Timer 1
    TH1=0XFD;
    SCON=0x50;
    TR1=1;
    gsmcmdsend(gsm_cmd3);
    cmm(0x01);
    gsmcmdsend(gsm_cmd4);
    cmm(0x01);
    cmm(0x85);
    for(i=0;i<3;i++)
    {dat(header);}
    cmm(0xc0);
    while(1)
    {
    recieve();
    for(l=83;l<=87;l++)
    {
    dat(card_id[l]);
    }
    compare();
    }
    }
    void compare()
    {
    if ((card_id[83]=='f')&&(card_id[84]=='a') && (card_id[85]=='n') && (card_id[86]=='o') && (card_id[87]=='n'))
    fan=1;
    else if((card_id[83]=='f')&&(card_id[84]=='a') && (card_id[85]=='n') && (card_id[86]=='o') && (card_id[87]=='f'))
    fan=0;
    else if((card_id[83]=='l')&&(card_id[84]=='g') && (card_id[85]=='t') && (card_id[86]=='o') && (card_id[87]=='n'))
    lgt=1;
    else if((card_id[83]=='l')&&(card_id[84]=='g') && (card_id[85]=='t') && (card_id[86]=='o') && (card_id[87]=='f'))
    lgt=0;
    }

    end; //end of program
     
  8. Harald Kapp

    Harald Kapp Moderator Moderator

    10,025
    2,138
    Nov 17, 2011
    Run it through your compiler and tell the compiler to generate an assembly listing.
     
Ask a Question
Want to reply to this thread or ask your own question?
You'll need to choose a username for the site, which only take a couple of moments (here). After that, you can post your question and our members will help you out.
Electronics Point Logo
Continue to site
Quote of the day

-