Continue to Site

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.

  • 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.

pic16f886 uart + AT problem

Status
Not open for further replies.
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:
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
 
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:
printf("Apple\r\n");
and the below is what appears at HyperTerminal.
Code:
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:
	#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...
 

Attachments

  • Serial_Port_Adapter_AT_Commands.pdf
    743.2 KB · Views: 441
Last edited:
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:
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
 
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:
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
 
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.
 
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
 
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:
//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.
 
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
 
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?
 
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:
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:
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:
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
 
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.
 

Attachments

  • prb1..JPG
    prb1..JPG
    98.5 KB · Views: 169
Last edited:
Ugh! Sorry I forgot you were using hitech c for some reason!

Try this:
Code:
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
 
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:
 [/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:
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:
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~
 
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:
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
 
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
 
Status
Not open for further replies.

Latest threads

New Articles From Microcontroller Tips

Back
Top