1. Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.
    Dismiss Notice

pic16f886 uart + AT problem

Discussion in 'Microcontrollers' started by micheadache, Jan 28, 2010.

  1. Wilksey

    Wilksey Member

    Joined:
    Aug 16, 2009
    Messages:
    553
    Likes:
    20
    Location:
    Somerset, UK
    You can use the "Go Advanced" and then add an attachment to the reply.

    The physical connection, if it is an RS232 interface then it will need to go through a level shift such as a MAX232 IC.

    The delays are needed for the example, it isn't that inefficient, there are routines to "putstring" but they work using an interrupt flags, as for delays, it's called an inter character delay, all serial comms have them, I have been programming serial ports for years now, otherwise you will get garbled message or characters missing as the UART transmit buffer cant send before requesting an outgoing transmission, as you saw last time.

    You can, however, wait for the transmit interrupt flag to clear before sending a new char, which will make sure the previous char has either gone through or timed out.

    This is how HI TECH does it, and it is part of their example.

    Code (text):

    putch(unsigned char byte)
    {
        /* output one byte */
        while(!TXIF)    /* set when register is empty */
            continue;
        TXREG = byte;
    }
     
    Now you understand, or are trying to understand how the UART works etc, you can start using the efficient code to construct your firmware.

    The example above, introduces a new "flag" called TXIF, or "Transmission (TX) Interrupt Flag" what this does is SET when the transmission is complete.
    So in our case, if it is still UNSET (or is 0) then it will just "continue" the rest of the application, otherwise it will set TXREG to our next character.

    You could expand on this function by returning a bool if successful, and if it is still trying to transmit the last char, retry until successful or a timeout.

    I trust your Bluetooth module is RS232 and NOT USB?

    Wilksey
     
  2. micheadache

    micheadache New Member

    Joined:
    Jan 28, 2010
    Messages:
    54
    Likes:
    0
    Location:
    singapore
    yes, my bluetooth is rs232.

    Hmm, if i did not interpret it wrongly, i sort of understand the TRMT, TXIF. its something like, we need to wait for the whole chunk of characters to be sent out before sending the next. but its sent serially in rs232, therefore, delays were used to allow some buffer time?

    i discovered 3 ways of writing a string of words: putch & printf and the previous conventional way of putting a char into TXREG and including delay.

    i tried writing
    Code (text):
    printf("Apple\r\n");
    and the below is what appears at HyperTerminal.
    Code (text):

    Apple
    Apple
    111111
    but how different is this from the putch?
    and does it also means that the "Apple" is sent to the TXREG by using printf?
    if it is, it would be efficient if i use printf all the way, isnt it?


    i tried
    Code (text):

        #include<pic.h>
        #include<htc.h>
        #include<conio.h>
        #include<stdio.h>
        __CONFIG(WDTDIS & INTIO & MCLRDIS);
        #define XTAL_FREQ 8MHZ

    void init_rs232();

    #define MHZ *1000L
    #define XTAL_FREQ 8MHZ
    #define DelayUs(x) { unsigned char _dcnt; \
    _dcnt = (x)/((12MHZ)/(XTAL_FREQ))|1; \
    while(--_dcnt != 0) \
    continue; }


    void main()
    {
        OSCCON= 0x75; //8Mhz High Freq Clock, can be fine tuned using OSCTUNE
        TRISE = 0x08;
        TRISB = 0x00;
        init_rs232();

            while(1){
                if(RE3==0){
                    RB0=1;
                                                                  //printf("Apple\r\n");
                                                                    putch('A');
                                                                    putch('p');
                                                                    putch('p');
                                                                    putch('l');
                                                                    putch('e');
                         }
                else{
                    RB0=0;
                        if(TRMT){
                        TXREG = 49; // switch NOT pressed, 0x31/49 = 1
                            }      
                    }
                }
    }

    void init_rs232()
    {
        BRGH = 1;  
        BRG16 = 0;
        SPBRG = 8;      // Fosc=8Mhz, ,16, BR=57600

        TX9  = 0;   // 9bits=1: 8-bit=0
        SYNC = 0;   // asynchronous
        SPEN = 1;   // enable serial port pins
        TXEN = 1;   // enable the transmitter & (automatically)TXIF=1
        CREN = 1;   // enable reception
        SREN = 0;   /// no effect
        TXIE = 0;   // disable tx interrupts
        RCIE = 0;   // disable rx interrupts
        RX9  = 0;   // ninebits?1:0,,,8- or 9-bit reception
    }

    void putch(unsigned char byte)
    {
        /* output one byte */
        while(!TXIF)    /* set when register is empty */
            continue;
        TXREG = byte;
    }
     
    and Apple came out too!! =D
    however, in this case, why is it " output one byte"? as in why is it set to byte?
    In this case, is it stil a serial transmission or the word Apple is inserted into the buffer in one chunk (as in in String)?

    and if i dont want a continuous Apple and 1, can i just delete away the while(1)? cos i dont think it can be done that way?



    guess the journey from now on will be more complicated with the AT mode...
     

    Attached Files:

    Last edited: Feb 9, 2010
  3. Wilksey

    Wilksey Member

    Joined:
    Aug 16, 2009
    Messages:
    553
    Likes:
    20
    Location:
    Somerset, UK
    Ok,
    Where to start...

    putch is the same as what I posted, as it was taken from the hi tech c code anyway.

    Putch stands for Put Character, which puts a character out to the UART, you can have this sending as you have with Apple but it will transmit one char(byte) a time, and wait for it to be sent before allowing another one to be sent.

    printf means print formatted, and this prints a formatted STRING (array of chars) to the UART.

    So the main difference here is putch transmits just one character (byte) and printf can transmit a string.
    dont forget to add a \r\n to the end of your printf code to include the CRLF code.

    You can also either remove the while loop or add it below to transmit just one "Apple".

    Also, with putch you can probably remove the delay routine if you want to.
    I will show you an example of this:

    Code (text):

    putch('A');  //Put A out to the UART buffer.
    printf("%s\r\n", "Apple");   //Print "Apple" followed by CRLF out to the UART buffer.
    while(1)
    {
       //Main loop
    }
     
    I will have a look at the document for the bluetooth commands later on and make some suggestions.

    You now have to decide / create your main code framework based upon the method you decide, because you need to read from the UART also and use a state machine or somthing to initialise / control the bluetooth module.

    Wilksey
     
  4. dave

    Dave New Member

    Joined:
    Jan 12, 1997
    Messages:
    -
    Likes:
    0


     
  5. Wilksey

    Wilksey Member

    Joined:
    Aug 16, 2009
    Messages:
    553
    Likes:
    20
    Location:
    Somerset, UK

    Ok, turns out you do need a delay after all to be within the specification of the AT command reference.
    You need a function to delay for 1 second, this can be from the source in:
    Microchip PIC micros and C - source and sample code
    The function is called DelayS, and is needed to delay 1 second before and after sending the escape seqence.
    It also appears that your escape squence should be 3 CHARACTERS within 200ms.
    I assume no response is given for this sequence?
    You can wrap this up into a function of its own.
    Code (text):

    void Initialise_Bluetooth_Module()
    {
        DelayS(1);
        putch('/');
        putch('/');
        putch('/');
        DelayS(1);
    }
     
    After this, I am not sure which commands from the AT manual you will be needing or what their responses will be.

    Wilksey
     
  6. micheadache

    micheadache New Member

    Joined:
    Jan 28, 2010
    Messages:
    54
    Likes:
    0
    Location:
    singapore
    hmm i'm trying if there's any effects the putch and printf above the while(1).
    (havent been able to get it tho)

    hmm for ur guidance on the AT commands, i do not actually need a delay for the "///" cos this 3 slashes have to be sent at one go, and not one by one. can i actually use printf for this?

    hmm where do u see that the "escape squence should be 3 CHARACTERS within 200ms"?
    Nope, no response is given for this sequence, except for a change in the led colour (already done up at the hardware side).

    i have actually came up with the list of AT commands that am gonna use, but will check it through with my supervisor first, in case there'r some mistakes.

    sigh, getting tough.
     
  7. Wilksey

    Wilksey Member

    Joined:
    Aug 16, 2009
    Messages:
    553
    Likes:
    20
    Location:
    Somerset, UK
    No, there shouldn't be any side effects.
    You can use printf as it says 3 consecutive characters.

    It says they should be within 200ms in chapter 2.

    Must have been late when I read the data sheet :)

    You will need to wait 1 second after you issue the "///" escape sequence before you issue AT commands.

    Well, I say you WILL NEED TO, if it works without then it should be ok, you may find that if you dont use the delays that the datasheet recommends then it may once every now and then not read the next command properly.

    You will need a list of the commands to issue and the expected responses. Standard AT responses are "OK" and "ERROR".

    Wilksey
     
  8. micheadache

    micheadache New Member

    Joined:
    Jan 28, 2010
    Messages:
    54
    Likes:
    0
    Location:
    singapore
    arghhh, i am still unable to just allow one Apple to appear...!
    i want one Apple to appear (Apple illustrating the ///) at the Hyperterminal when the switch button is pressed.
    i tried commenting the while loop but to no avail. i was wondering is it because Apple appears continously when i am pressing the switch. but how do i stop this?


    i guess i would need some initialization commands of the AT such as
    Code (text):

    //Master & Slave not set
    AT*AGLN=TidyBluetooth,1
     putchar(0x0D);
    ATS2=47
    ATS2=47
    ATS2=47
     putchar(0x0D);
    ATE1
     putchar(0x0D);
    AT*AGDM=3,1
     putchar(0x0D);
    AT*AGCM=2,1
     putchar(0x0D);
    AT*AGPM=2,1
     putchar(0x0D);
    AT*AGB=bd_addr of the bt device to be bonded with
     putchar(0x0D);
    AT*AGND=bd_addr of the bt device to be retrieved from
     putchar(0x0D);
    AT*AGDD=1,(8*1.28)10.24
     putchar(0x0D);
    AT*AGI=2,2.56,5
     putchar(0x0D);
    AT*AGBD?
     putchar(0x0D);
    AT*AGFP=12te34ba,1
     putchar(0x0D);

    AT*ADDM
    AT*ADDCP
    AT*ADDSP
    AT*ADNRP
    AT*
     
    and a small application such as lighting up a LED thru the bluetooth.
     
  9. Wilksey

    Wilksey Member

    Joined:
    Aug 16, 2009
    Messages:
    553
    Likes:
    20
    Location:
    Somerset, UK
    When you say it continuously transmits "Apple", is it because RE3 is still 1? or is it a momentary push switch pulling it back to 0?

    Wilksey
     
  10. micheadache

    micheadache New Member

    Joined:
    Jan 28, 2010
    Messages:
    54
    Likes:
    0
    Location:
    singapore
    hey Wilksey, so sorry for my absence as it was a week of hols for us here last week due to Lunar New Year. and reality of the projects are back =( haha

    Hmm yes, i guess RE3 would always be at 1 when i am pressing the switch? how do i make it momentarily push switch or something?
     
  11. Wilksey

    Wilksey Member

    Joined:
    Aug 16, 2009
    Messages:
    553
    Likes:
    20
    Location:
    Somerset, UK
    Hello there, Happy New Year to you!

    You can either replace the switch with a momentary push switch, or you can do a software momentary action.

    So what you would do is have a variable to tell you if the switch has already been pressed.
    Code (text):

    bool m_Switched = false;  //Global or main function variable.
    if((RE3) && (!m_Switched))
    {
       m_Switched = true;
       printf("Apple\r\n");
    }
    else if(!RE3)
    {
       m_Switched = false;
    }
     
    The code above should guide you to what you need to do, I wont state that is the EXACT code to do the job, but give it a try.

    Wilksey
     
    Last edited: Feb 22, 2010
  12. micheadache

    micheadache New Member

    Joined:
    Jan 28, 2010
    Messages:
    54
    Likes:
    0
    Location:
    singapore
    hey wilksey,

    Thanks! Happy New Year to you too! guess it must be crowded too in UK.

    i checked up and the bool means boolean?
    guess it cant be understood by MpLab? as i am unable to use ur codes above...

    \trying to see if there's any simliar way
     
    Last edited: Feb 22, 2010
  13. Wilksey

    Wilksey Member

    Joined:
    Aug 16, 2009
    Messages:
    553
    Likes:
    20
    Location:
    Somerset, UK
    Hmm, the formatting messed up for some reason, I just edited and saved the post, see if you can copy + paste that, seems to have fixed it.

    Wilksey
     
  14. micheadache

    micheadache New Member

    Joined:
    Jan 28, 2010
    Messages:
    54
    Likes:
    0
    Location:
    singapore
    Hmm, the following showed up when i editter the code.
    Think its the same errors shown

    Hmm, i just tried it out again and it can be compiled this time round. However, nothing was produced. the led doesnt light up anymore too when i pressed the switch.
     

    Attached Files:

    Last edited: Feb 22, 2010
  15. Wilksey

    Wilksey Member

    Joined:
    Aug 16, 2009
    Messages:
    553
    Likes:
    20
    Location:
    Somerset, UK
    Ugh! Sorry I forgot you were using hitech c for some reason!

    Try this:
    Code (text):

    void init_rs232();
    #define true 1
    #define false 0

        static bit m_Switched = false;  //Global or main function variable.
        if((RE3) && (!m_Switched))
        {
            m_Switched = true;
            printf("Apple\r\n");
        }
        else if(!RE3)
        {
            m_Switched = false;
        }
     
    Note: the #defines go AFTER the function prototype, but BEFORE the main function.

    Give that a try.

    Wilksey
     
  16. Wilksey

    Wilksey Member

    Joined:
    Aug 16, 2009
    Messages:
    553
    Likes:
    20
    Location:
    Somerset, UK
    You will have to excuse the formatting, the code tags appear to be broken!

    Wilksey
     
  17. micheadache

    micheadache New Member

    Joined:
    Jan 28, 2010
    Messages:
    54
    Likes:
    0
    Location:
    singapore
    haha we do make mistakes, and am really really appreciative of ur help, no apologies bro. really learnt alot from u.
    oh so the
    Code (text):
     [/C0de] rly does help in the formatting? hmm, interesting...

    anyways, this is the portion that i changed and the codes now look like,
    [code]
        #include<pic.h>
        #include<htc.h>
        #include<conio.h>
        #include<stdio.h>
    //  __CONFIG(WDTDIS & INTIO & MCLRDIS);
        #define XTAL_FREQ 8MHZ

    void init_rs232();
    void putChar( unsigned char ch);

    #define MHZ *1000L
    #define XTAL_FREQ 8MHZ
    #define DelayUs(x) { unsigned char _dcnt; \
    _dcnt = (x)/((12MHZ)/(XTAL_FREQ))|1; \
    while(--_dcnt != 0) \
    continue; }

    #define true 1
    #define false 0

    void main()
    {
        //TRISC = 0b10000000; no need to set TRISC as its the lowest priority if we've already set the TXEN, etc
        OSCCON= 0x75; //8Mhz High Freq Clock, can be fine tuned using OSCTUNE
        TRISE = 0x08;
        TRISB = 0x00;
        init_rs232();
    //putch('B');
    //printf("%s\r\n","Apple");
            //while(1){
    /*          if(RE3==0){
                    RB0=1;
                   
    //printf("///  \r\n");
    printf("%s\r\n","Apple");
        putch('A');
        putch('p');
        putch('p');
        putch('l');
        putch('e');
    //  putStr("Apple");
    //  TXREG = 0x0D; carriage reutrn (\r)
    //  TXREG = 0x0A; new line feed (\n)
                //  if(TRMT){
                        TXREG = 0x41; //swtich pressed, send 0X41 = A
                        DelayUs(255);
                        TXREG = 0x70; //'p'
                        DelayUs(255);
                        TXREG = 0x70; //p
                        DelayUs(255);
                        TXREG = 0x6C; //l
                        DelayUs(255);              
                        TXREG = 0x65; //e
                        DelayUs(255);  
                            }       // 
                        }
                else{
                    RB0=0;
                        if(TRMT){
                            TXREG = 49; // switch NOT pressed, 0x31/49 = 1
                        //  while(TXIF==0); //wait until all bits are transmitted
                                }      
                    }*/

    static bit m_Switched = false;  //Global or main function variable.  
    if((RE3) && (!m_Switched))  {  
        m_Switched = true;  
        printf("Apple\r\n");  
    }  else if(!RE3)  {  
        m_Switched = false;  }
     
                //}
    }

    void init_rs232()
    {
        BRGH = 1;   // high baud rate to avoid baud rate error & bcos 16bit achieve slow baud rates fr fast osc freq
        BRG16 = 0;
       
        SPBRG = 8;      // Fosc=8Mhz, ,16, BR=57600

        TX9  = 0;   // 9bits=1: 8-bit=0
        SYNC = 0;   // asynchronous
        SPEN = 1;   // enable serial port pins
        TXEN = 1;   // enable the transmitter & (automatically)TXIF=1
        CREN = 1;   // enable reception
        SREN = 0;   /// no effect
        TXIE = 0;   // disable tx interrupts
        RCIE = 0;   // disable rx interrupts
        RX9  = 0;   // ninebits?1:0,,,8- or 9-bit reception
    }

    void putch(unsigned char byte)
    {
        /* output one byte */
        while(!TXIF)    /* set when register is empty */
            continue;
        TXREG = byte;
    }
     


    oh my. i see that sometimes the codes here appear to be continous and i guess that's a result of what u meant by "the code tags appear to be broken"..it's so messy now
     
    Last edited: Feb 24, 2010
  18. micheadache

    micheadache New Member

    Joined:
    Jan 28, 2010
    Messages:
    54
    Likes:
    0
    Location:
    singapore
    as RE3 switch is 0 when it is pressed, i changed ur codes to the following (only a change in the !RE3 and RE3)

    Code (text):

    static bit m_Switched = false;  //Global or main function variable.  
    if((!RE3)  && (!m_Switched))  {  
        m_Switched = true;  
        printf("Apple \r\n");
    }  else if(RE3)  {  
        m_Switched = false;  }
     
    when i tried this out, nothing came out when i didnt press the switch (which is somewhat what i eventually desire), but it still gave me continous Apple on consecutive new lines when i pressed the switch. Hmmm~
     
  19. Wilksey

    Wilksey Member

    Joined:
    Aug 16, 2009
    Messages:
    553
    Likes:
    20
    Location:
    Somerset, UK
    It should work, hmm, I cant get the simulation to read the inputs, going to try and find out why, until then, I have used RA0 as the input, see what this does:
    Code (text):

    void init_rs232();
    #define true 1
    #define false 0

    void main()
    {
        OSCCON = 0x75;
        TRISA0 = 1;
        TRISB = 0x00;
        init_rs232();
        static bit m_Switched = false;  //Global or main function variable.

            while(1)
            {
                if (RA0) //&& (!m_Switched))
                {
                    m_Switched = true;
                    RB0 = 1;
                    printf("Apple\r\n");
                }
                else if(!RA0)
                {
                    m_Switched = false;
                }
            }
    }
     
    Wilksey
     
  20. micheadache

    micheadache New Member

    Joined:
    Jan 28, 2010
    Messages:
    54
    Likes:
    0
    Location:
    singapore
    hmm u commented away the "&& (!m_Switched))"? how does that part works anyways...
     
    Last edited: Feb 23, 2010
  21. Wilksey

    Wilksey Member

    Joined:
    Aug 16, 2009
    Messages:
    553
    Likes:
    20
    Location:
    Somerset, UK
    Yes, it should transmit "Apple" until the switch is depressed / off
    It acts as a second trigger, a software switch if you will, once it is triggered it will remain set until the switch is 0 then it will reset itself.

    Wilksey
     

Share This Page