Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

Sample HiTech PIC C Bit-bang program doesnt work!

Status
Not open for further replies.

ericmar

Full Member level 5
Joined
Apr 14, 2004
Messages
278
Helped
3
Reputation
6
Reaction score
4
Trophy points
1,298
Location
Singapore
Activity points
2,928
pic bitbang

Hi guys,

I'hv a serious problem which I hv to solve it within 1 week so can everyone help me? I'm writing program for my PIC using Hitech PIC C and I cant get it work with the sample bit-bang coding provided. I'hv already used my USART interface for some operation and thus, need to emulate another USART interface for accepting GPS data from my GPS receiver. However, I keep getting junk messages even though I'hv set the baud rate correctly. I couldnt figure out wats the problem since I dont really understand the coding! My PIC is 16F877 and my GPS receiver is Garmin GPS 18LVC. I noticed that the junk messages that I got is somehow repeating with slightly defferent which should be the time and checksum that keep changing every second in the GPS message. The pattern seems right but then I just couldnt get the correct data. I wonder which part in the coding has gone wrong! I did try to receive the GPS data directly though serial COM port and it works correctly though. So I think it should be my GPS receiver problem but the PIC program.

I appreciate for any help provided! Thanks a lot!

Regards,
Eric
 

bit banging

Hi,

bitbanged receiving is almost always a problem ...

In case of your GPS you could try to switch the GPS to a lower baudrate (1200 baud for example) bitbanging might be easier then because the timing is less critical.

What is the clock frequency of your pic and which code do you use for bitbanged receiving?

For which other task do you need the built in USART?
If it is for transmitting only or if it runs on a low baudrate you could use bitbanging for this task and use the built in USART for your GPS.

If your bitbanging code is not too big post it and I will take a look at it :)

best regards
 

    ericmar

    Points: 2
    Helpful Answer Positive Rating
pic.h sample program

C-Man said:
Hi,

bitbanged receiving is almost always a problem ...

In case of your GPS you could try to switch the GPS to a lower baudrate (1200 baud for example) bitbanging might be easier then because the timing is less critical.

What is the clock frequency of your pic and which code do you use for bitbanged receiving?

For which other task do you need the built in USART?
If it is for transmitting only or if it runs on a low baudrate you could use bitbanging for this task and use the built in USART for your GPS.

If your bitbanging code is not too big post it and I will take a look at it :)

best regards

Basically, I did think abt swapping for using the normal USART but then I'll need to manufacture another PCB then which I probably dont hv time to do it. My clock frequency is 4MHz.

Thanks a lot!

Here is the code that I used.
Code:
/*
 *	Serial port driver (uses bit-banging)
 *	for 16Cxx series parts.
 *
 * 	IMPORTANT: Compile this file with FULL optimization
 *
 *	Copyright (C)1996 HI-TECH Software.
 *	Freely distributable.
 */
#include	<pic.h>
/*
 *	Tunable parameters
 */

/*	Transmit and Receive port bits */
#define SERIAL_PORT	PORTB
#define SERIAL_TRIS	TRISB
#define	TX_PIN		2
#define RX_PIN		3

/*	Xtal frequency */
#define	XTAL	4000000

/*	Baud rate	*/
#define	BRATE	4800

/*	Don't change anything else */
#define SCALER		10000000
#define ITIME		4*SCALER/XTAL	/* Instruction cycle time */
#if BRATE > 1200
 #define	DLY		3		/* cycles per null loop */
 #define	TX_OHEAD 13		/* overhead cycles per loop */
#else
 #define	DLY		9		/* cycles per null loop */
 #define TX_OHEAD  14
#endif
#define	RX_OHEAD	12		/* receiver overhead per loop */

#define	DELAY(ohead)	(((SCALER/BRATE)-(ohead*ITIME))/(DLY*ITIME))

static bit	TxData @ (unsigned)&SERIAL_PORT*8+TX_PIN;	/* Map TxData to pin */
static bit	RxData @ (unsigned)&SERIAL_PORT*8+RX_PIN;	/* Map RxData to pin */
#define	INIT_PORT	SERIAL_TRIS = 1<<RX_PIN				/* set up I/O direction */

void
putch(char c)
{
	unsigned char	bitno;
#if BRATE > 1200
	unsigned char	dly;
#else
	unsigned int	dly;
#endif

	INIT_PORT;
	TxData = 0;			/* start bit */
	bitno = 12;
	do {
		dly = DELAY(TX_OHEAD);	/* wait one bit time */
		do
			/* waiting in delay loop */ ;
		while(--dly);
		if(c & 1)
			TxData = 1;
		if(!(c & 1))
			TxData = 0;
		c = (c >> 1) | 0x80;
	} while(--bitno);
NOP();
}

char
getch(void)
{
	unsigned char	c, bitno;
#if BRATE > 1200
	unsigned char	dly;
#else
	unsigned int	dly;
#endif

	for(;;) {
		while(RxData)
			continue;	/* wait for start bit */
		dly = DELAY(3)/2;
		do
			/* waiting in delay loop */ ;
		while(--dly);
		if(RxData)
			continue;	/* twas just noise */
		bitno = 8;
		c = 0;
		do {
			dly = DELAY(RX_OHEAD);
			do
			/* waiting in delay loop */ ;
			while(--dly);
			c = (c >> 1) | (RxData << 7);
		} while(--bitno);
		return c;
	}
}

char
getche(void)
{
	char c;

	putch(c = getch());
	return c;
}
 

hitech c serial communication code

Any good optimizing C compiler will remove this do-nothing statement:
Code:
while(--dly);
 

hi tech c examples

echo47 said:
Any good optimizing C compiler will remove this do-nothing statement:
Code:
while(--dly);
Which one do u mean?

The one inside the putch or getch or both?
 

hi-tech c example

Hi ericmar,

took a look at your code, sorry but this is very primitive.

I thought it would be interrupt driven, when you sit waiting for a character to be received your MCU can do nothing else this is unuseable for your project ...

You should also overthink the 4 MHz crystal, I would use at least 8 or even better 16MHz because when using a software RS232 the CPU can only do 208 commands in the time required to receive a single bit.

My advice would be: use a 16MHz crystal (most 16F877 are specified for 20MHz) and also use an interrupt driven soft RS232 so that the CPU does not hang while receiving over the soft RS232.

If you do not find an interrupt driven approach for soft RS232 PM me and I will try to help you.

best regards
 

hitech software uart

I had the same problem when using the Hitech sample serial bitbanging routine on a PIC16F84. It was clearly a timing issue, so it takes a little tweaking for the TX_overhead and RX_overhead values.

Trial and error
 

    ericmar

    Points: 2
    Helpful Answer Positive Rating
hi-tech picc serial

Which one do u mean?

The one inside the putch or getch or both?
A smart optimizer will notice that the value of dly doesn't matter to the rest of your program, so it will simply delete both loops and the storage space for dly.

A weak optimzier may generate real loops.
 

bitbang uart

I found an interrupt driven bitbang routine (sorry for the AVR) in C here:
https://www.hpinfotech.ro/softuart.zip

Maybe you can adopt it to your needs, looks OK to me ...

best regards
 

    ericmar

    Points: 2
    Helpful Answer Positive Rating
hitech example

I keep trying the HiTech bit-bang sample code and now I can get it work partially at 9600bps with 4MHz crystal. But I keep losing the second subsequent character. For example, if I send ABCDEFG, when it gets echo back I can only get ACEG! Wat could be the problem? Is that the code cant be used to receive a series of continuous characters?
 

c compiler hi-tech example

Hi ericmar,

For example, if I send ABCDEFG, when it gets echo back I can only get ACEG! Wat could be the problem?

It seems that you are loosing a char after you receive one because some overhead during
getchar(). Post the routine you are using to enable us to help you. You can get running the
PIC16F877 @4Mhz at 9600 Baud but you must be carefull regarding the sampling rate to
detect the Start bit.
As C-Man told you, it would be less time critical if you use a 16Mhz crystal.

best wishes,

humber555
 

    ericmar

    Points: 2
    Helpful Answer Positive Rating
pic interrupt driven serial routine

Humber555 said:
Hi ericmar,

For example, if I send ABCDEFG, when it gets echo back I can only get ACEG! Wat could be the problem?

It seems that you are loosing a char after you receive one because some overhead during
getchar(). Post the routine you are using to enable us to help you. You can get running the
PIC16F877 @4Mhz at 9600 Baud but you must be carefull regarding the sampling rate to
detect the Start bit.
As C-Man told you, it would be less time critical if you use a 16Mhz crystal.

best wishes,

humber555

Thanks humber555!
This is my current code! It's similar to the one I posted above! I didn't change anything except the baudrate. I did try to play around the RX_OHEAD but still cant get it work correctly. Changing crystal from 4MHz to 8MHz makes it worse! I didnt even get 1 correct character. I dont hv 16MHz crystal so cant try out now.

Code:
/* main.c */
#include <stdio.h>
#include <pic.h>

void main(void){
	unsigned char input;

	INTCON=0;	// purpose of disabling the interrupts.

	printf("\rPress a key and I will echo it back:\n");
	while(1){
		input = getch();	// read a response from the user
		putch(input);	// echo it back
	}
}


Code:
/* bitbang.c */

#include   <pic.h>
/*
 *   Tunable parameters
 */

/*   Transmit and Receive port bits */
#define SERIAL_PORT   PORTB
#define SERIAL_TRIS   TRISB
#define   TX_PIN      3
#define RX_PIN      4

/*   Xtal frequency */
#define   XTAL   4000000

/*   Baud rate   */
#define   BRATE   9600

/*   Don't change anything else */
#define SCALER      10000000
#define ITIME      4*SCALER/XTAL   /* Instruction cycle time */
#define   DLY      3      /* cycles per null loop */
#define   TX_OHEAD 13      /* overhead cycles per loop */
#define   RX_OHEAD   12      /* receiver overhead per loop */

#define   DELAY(ohead)   (((SCALER/BRATE)-(ohead*ITIME))/(DLY*ITIME))

static bit   TxData @ (unsigned)&SERIAL_PORT*8+TX_PIN;   /* Map TxData to pin */
static bit   RxData @ (unsigned)&SERIAL_PORT*8+RX_PIN;   /* Map RxData to pin */
#define   INIT_PORT   SERIAL_TRIS = 1<<RX_PIN            /* set up I/O direction */

void
putch(char c)
{
   unsigned char   bitno;
   unsigned char   dly;

   INIT_PORT;
   TxData = 0;         /* start bit */
   bitno = 12;
   do {
      dly = DELAY(TX_OHEAD);   /* wait one bit time */
      do
         /* waiting in delay loop */ ;
      while(--dly);
      if(c & 1)
         TxData = 1;
      if(!(c & 1))
         TxData = 0;
      c = (c >> 1) | 0x80;
   } while(--bitno);
NOP();
}

char
getch(void)
{
   unsigned char   c, bitno;
   unsigned char   dly;

   for(;;) {
      while(RxData)
         continue;   /* wait for start bit */
      dly = DELAY(3)/2;
      do
         /* waiting in delay loop */ ;
      while(--dly);
      if(RxData)
         continue;   /* twas just noise */
      bitno = 8;
      c = 0;
      do {
         dly = DELAY(RX_OHEAD);
         do
         /* waiting in delay loop */ ;
         while(--dly);
         c = (c >> 1) | (RxData << 7);
      } while(--bitno);
      return c;
   }
}
 

picc rx read getch

ericmar said:
I keep trying the HiTech bit-bang sample code and now I can get it work partially at 9600bps with 4MHz crystal. But I keep losing the second subsequent character. For example, if I send ABCDEFG, when it gets echo back I can only get ACEG! Wat could be the problem? Is that the code cant be used to receive a series of continuous characters?

I wonder how this can be.

When you look at the code putch is using all time it can get until one character is sent out including the time for 2 stopbits.

The same is true for getch it also uses up all time until it has received a character except that it does not wait for the stopbit(s) but needs to wait for the startbit.

So in theory (as I see it) when you connect TX and RX of your "softusart" and you send out one character using putch and next try to call getch to receive this character getch will sit and wait for a startbit forever because the character has been sent out completly before getch even had a chance to receive something.

Now using your GPS module connected to your "softuart" if you try to call getch you will receive a character but while your mainprogram is processing the received char the next char is already being sent out by the GPS module so you have no chance to receive everything except your mainprogram does not need longer than the time for the stopbit(s) to process the received data!!

Thats why I told you either use an interrupt controlled bitbang routine (with a buffer receiving in the background) or use the hardware USART ...

hope this helps and best regards
 

    ericmar

    Points: 2
    Helpful Answer Positive Rating
hi tech c buffer

Hi ericmar,

Bit-banging soft handler to receive a long data string is not the best way to start with
if your final target is to receive the full GPS packet. I strongly recommend to use
the hardware UART of the 16F877, AND a circular buffer.

best wishes,

humber555
 

    ericmar

    Points: 2
    Helpful Answer Positive Rating
bit banging scaler

C-Man said:
ericmar said:
I keep trying the HiTech bit-bang sample code and now I can get it work partially at 9600bps with 4MHz crystal. But I keep losing the second subsequent character. For example, if I send ABCDEFG, when it gets echo back I can only get ACEG! Wat could be the problem? Is that the code cant be used to receive a series of continuous characters?

I wonder how this can be.

When you look at the code putch is using all time it can get until one character is sent out including the time for 2 stopbits.

The same is true for getch it also uses up all time until it has received a character except that it does not wait for the stopbit(s) but needs to wait for the startbit.

So in theory (as I see it) when you connect TX and RX of your "softusart" and you send out one character using putch and next try to call getch to receive this character getch will sit and wait for a startbit forever because the character has been sent out completly before getch even had a chance to receive something.

Now using your GPS module connected to your "softuart" if you try to call getch you will receive a character but while your mainprogram is processing the received char the next char is already being sent out by the GPS module so you have no chance to receive everything except your mainprogram does not need longer than the time for the stopbit(s) to process the received data!!

Thats why I told you either use an interrupt controlled bitbang routine (with a buffer receiving in the background) or use the hardware USART ...

hope this helps and best regards
hi C-Man,

I mean I sent the data from computer to PIC and then PIC tried to echo back the data. I have no problem in sending the whole predefined string from PIC to computer. Instead of receiving GPS message, I'm using a serial communication program to send and receive data atm for trying to get the code working correctly 1st. Could u pls show me example of an interrupt controlled bitbang routine?

Thanks a lot!

Regards,
Eric
 

theorie bitbanging

ericmar said:
hi C-Man,

I mean I sent the data from computer to PIC and then PIC tried to echo back the data. I have no problem in sending the whole predefined string from PIC to computer. Instead of receiving GPS message, I'm using a serial communication program to send and receive data atm for trying to get the code working correctly 1st. Could u pls show me example of an interrupt controlled bitbang routine?

Thanks a lot!

Regards,
Eric

Yes as I already wrote you will not have any problem sending something except that your PIC ist 100% busy during this time and you will receive nothing on your softusart during this time ...

I have posted a link above but it is a routine for the atmel AVR in C so a little bit of work has to be done, just wanted to give you a starter:
https://www.hpinfotech.ro/softuart.zip

best regards
 

    ericmar

    Points: 2
    Helpful Answer Positive Rating
pic hitech

C-Man said:
ericmar said:
hi C-Man,

I mean I sent the data from computer to PIC and then PIC tried to echo back the data. I have no problem in sending the whole predefined string from PIC to computer. Instead of receiving GPS message, I'm using a serial communication program to send and receive data atm for trying to get the code working correctly 1st. Could u pls show me example of an interrupt controlled bitbang routine?

Thanks a lot!

Regards,
Eric

Yes as I already wrote you will not have any problem sending something except that your PIC ist 100% busy during this time and you will receive nothing on your softusart during this time ...

I have posted a link above but it is a routine for the atmel AVR in C so a little bit of work has to be done, just wanted to give you a starter:
h**p://www.hpinfotech.ro/softuart.zip

best regards
Hi C-Man,

I understand wat u mean now. In theory, I should get wat I want if I buffer the incoming data up, right? And of coz, it would be better to use interrupt to find out when to buffer the incoming data. So how do I write an interrupt for the softuart to determine when the data is coming in? I never use Atmega and CCS so hardly catch wat the code is trying to do.

I hv another idea. If let say I only want to receive 1 whole sentence like "$GMRMC,000.000,123.456", is it possible for it to be working correctly if I modify the getch() so that it skips all character until it receive the "$" character and then start buffering characters till "\n" or "\CRLF"? I tried to buffer up the characters before I printf the whole message but I still couldnt get it right. I wonder if this could be due to the reason of keep calling the getch() inside a while loop.

Thanks!

Regards,
Eric
 

bit bang rs232 timing

ericmar,

I have not enough spare time in the moment but will try to help you as soon as possible.

In the meantime I would be interested why you can not use the hardware USART what is connected to it?

Where is your software usart connected and is it necessary to send and receive?

best regards
 

    ericmar

    Points: 2
    Helpful Answer Positive Rating
bitbang.c

Unbelievable! I got it working correctly now by changing the delay for receiving each bit after start bit from RX_OHEAD=12 to RX_OHEAD=3. I think with RX_OHEAD=3 would then only equal to 1 bit time. And of coz I did buffer up the whole message before I print it!

However, the code doesnt work correctly when I changed my PIC from 16F877 to 18F452. For some reasons, I couldnt even get the first character correctly.

I couldnt use the hardware uart becoz I hv no time to manufacture another PCB so I hv to emulate a software uart on the current PCB I have with some spare ports available.
 

usart bit bang c code

Excuse my ignorance you compiled your code with PICC18?

Did you have a look at how things are defined differently for PIC16 and PIC18?

PIC16:
static volatile unsigned char PORTB @ 0x06;

static volatile unsigned char bank1 TRISB @ 0x86;

/* PORTB bits */
static volatile bit RB7 @ (unsigned)&PORTB*8+7;

PIC18:
static volatile near unsigned char PORTB @ 0xF81;

static volatile near unsigned char TRISB @ 0xF93;

//PortB
static volatile near bit RB0 @ ((unsigned)&PORTB*8)+0;

So you should at least use the "near" keyword in the definitions for PIC18.

You might also take a look at the compilers assembler list output there is a big difference between PIC16 and PIC18 architecture and you might need to tweak your parameters again for an equal delay.

best regards
 

Status
Not open for further replies.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top