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.

help needed on code implementation=)

Status
Not open for further replies.

qtommer

Member
im trying to send the character 'A' from the PIC 16F877A to the Hyper Terminal of a PC asynchronously.
Ive read the 877a datasheet concerning the setting up of transmit and receive registers, baud rates, and TXIE, TXIF, RXIE, RXIF flags..
I also understand how characters are communicated in ASCII between PC and PIC.
I also understand the need of voltage level converters between the PC and PIC and for this im using the Max 232 which i have successfully constructed and tested..

i am now currently developing my code in c and have came up with the following so far:


void serial_setup(void)
{
SPBRG=25; //im using 9600baud
BRGH=1; //data rate for sending
SYNC=0; //asynchronous
SPEN=1; //enable serial port pins
CREN=1; //enable reception
SREN=0; //no effect
TXIE=0; //disable tx interrupts
RCIE=0; //disable rx interrupts
TX9=0; //8-bit transmission
RX9=0; //8-bit reception
TXEN=0; //reset transmitter
TXEN=1; //enable the transmitter

}

void putch(unsigned char a)
{
TXREG=a;

}

void main()
{
TRISB=0xFF;
serial_setup();

if(RB0)
{
putch('A');
}

}

Excerpting from my above code,

void putch(unsigned char a)
{
TXREG=a;

}


I would like to know whether this implementation is the correct way of sending out a string through the Tx Pin. Supposingly I have a long string, should I send out the data byte by byte?

(I am actually trying to send AT commands to a handphone via a serial data cable and as i have no experience implementing serial comm in a pic, im trying to send characters to the hyper terminal first.)

Any opinions on how i should learn to develop my code/online resources are also appreciated=)
 

jimlovell777

New Member
You need to send data byte by byte. Have you tried your code yet? To send a capital A you need to give TXREG a value of 65 Decimal or 41 hex.
 

Pommie

Well-Known Member
Most Helpful Member
If you just place data in txreg you will overwrite the previous data and could get framing errors. The correct way is to first wait for TXIF to be set.
Code:
void SendRS232(unsigned char Dat){
    while(!pir1.TXIF);
    txreg=Dat;
}
The above is in boostC and so the case is probably wrong for your compiler.

Mike.
 

qtommer

Member
thank you for your replies..=)
i have extended my code as follows to send out the string "YO" byte by byte every time i set RC0 to HIGH.

#define Y 0x59
#define O 0x4F


void serial_setup(void)
{
SPBRG=25;
BRGH=1; //data rate for sending
SYNC=0; //asynchronous
SPEN=1; //enable serial port pins
CREN=1; //enable reception
SREN=0; //no effect
TXIE=0; //disable tx interrupts
RCIE=0; //disable rx interrupts
TX9=0; //8-bit transmission
RX9=0; //8-bit reception
TXEN=0; //reset transmitter
TXEN=1; //enable the transmitter

}




void main()
{
unsigned char data[2]="Y","O";
int count;
unsigned char out;

TRISC=0xFF;
serial_setup();


if(RC0)
{
for(count=0;count<2;count++)
{
out=data[count];
if(TXIF)
{
TXREG=out;
}
}

}
}


I measured the output waveform of Pin 25 (TX) of my PIC 16F877A using an oscilloscope and I got a constant waveform (as attached) and not the expected ASCII waveforms of 0x59 and 0x4F [b0101100101001111] for everytime i input a high voltage to RC0

prior to this i just tried outputting 1 data at a time and i still got the same output.

Is there any reason why this is happening?

Thank you..
 

Attachments

  • Untitled picture.png
    Untitled picture.png
    253.4 KB · Views: 118

Pommie

Well-Known Member
Most Helpful Member
Does that even compile. The line
Code:
unsigned char data[2]="Y","O";
is trying to put 4 characters into a 2 byte array.
It should be,
Code:
unsigned char data[2]={'Y','O'};
//or
unsigned char data[3]="YO";  // = 'Y','O',Zero
Also, you are randomly sending 'Y' and zero because you use if instead of while not.

My guess at what is required is,
Code:
void main()
{
unsigned char data[2]={'Y','O'};
int count;
unsigned char out;

    TRISC=0xFF;
    serial_setup();
    if(RC0)
    {
        for(count=0;count<2;count++)
        {
            out=data[count];
            while(!TXIF);
            TXREG=out;
        }    
    }
}

BTW, which compiler are you using?

Mike.
 
Last edited:

qtommer

Member
hey mike thanks for ur reply

this line did compile..hmmm i wonder why...

Does that even compile. The line
Code:

unsigned char data[2]="Y","O";

is trying to put 4 characters into a 2 byte array.

im using the HI-TECH C PRO Compiler for the PIC12/14/16 Family

i modified my code accordingly as u said . This time the output generated a similar waveform to the previous one except that now the square wave is smoother..(view pic)


the expected waveform(in binary) is
0(Start) 01011001(Data) 1(Stop)
0(Start) 01001111(Data) 1(Stop)

TOTAL= 20 bits

however i got the waveform of a continuous square wave exceeding way over 20 bits . I guess there's something wrong in the implementation of my code? this is my code modified.
#include <pic.h>
#include <conio.h>
#include <stdio.h>
#include "always.h"
#include "delay.h"




#if defined (_16F84A)
#warning PIC16F84A selected
__CONFIG(0x3FF1); // PIC16F84A Configuration Fu#ises:
// - XT Oscillator
// - 70 msecs Power Up Timer On
// - Watchdog Timer Off
// - Code Protection Off
#elif defined(_16F877A)
#warning PIC16F877A selected
__CONFIG(0x3FF1); // PIC16F877A Configuration Fuses:
// - External Reset
// - XT Oscillator
// - 70 msecs Power Up Timer On
// - Watchdog Timer Off
// - Code Protection Off
// - BODEN Enabled
#else
#error Unsupported PICmicro MCU selected
#endif


#define Y 0x59 //assign ASCII byte code to Y
#define O 0x4F //assign ASCII byte code to O

void serial_setup(void)
{
SPBRG=25;
BRGH=1; //data rate for sending
SYNC=0; //asynchronous
SPEN=1; //enable serial port pins
CREN=1; //enable reception
SREN=0; //no effect
TXIE=0; //disable tx interrupts
RCIE=0; //disable rx interrupts
TX9=0; //8-bit transmission
RX9=0; //8-bit reception
TXEN=0; //reset transmitter
TXEN=1; //enable the transmitter

}

void main()
{
unsigned char data[3]="YO"; //store bytes in array because bytes are to be sent one by one.
int count;
unsigned char out;


TRISC=0xFF; //Set Port C as Input
serial_setup(); //Set up transmit and receive registers


if(RC0) //execute when RC0 is pressed
{
for(count=0;count<2;count++)
out=data[count]; //send out data byte by byte

while(TXIF) //write bytes to TXREG when TXREG is empty
TXREG=out;
}
}

oh and regarding the code u wrote for me,

for(count=0;count<2;count++)
{
out=data[count];
while(!TXIF);
TXREG=out;
}

why is it that u set the while loop to run when TXIF is 0?
i read the 877a datasheet on page 99 and it said that
Once the TXREG register transfers the data to the TSR register, the TXREG register is empty and flag bit TXIF is set.

therefore shouldnt the while loop be set to run when TXIF=1?

sorry if my understanding of the matter is incorrect.
 

Pommie

Well-Known Member
Most Helpful Member
There is no while loop, just a while statement.
while(...); is an empty loop and will just wait while the condition is true. Note the semi colon on the while line.
while(TXIF) will wait while TXIF is 1. We need the opposite and so use while(!TXIF);

The reason you see a continuous square wave is because the data is being sent repeatedly.

Try,
Code:
void main()
{
unsigned char data[2]={'Y','O'};
int count;
unsigned char out;

    TRISC=0xFF;
    serial_setup();
    if(RC0)
    {
        for(count=0;count<2;count++)
        {
            out=data[count];
            while(!TXIF);
            TXREG=out;
        }
        DelayMs(250);
    }
}
The name of the delay routine is probably wrong but there should be a delay function available.

Mike.
 

qtommer

Member
after inserting the delay, i got a waveform of 3 byte frames as follows:
(UART sending from LSB to MSB)

1011010011 1111110000 1 100110101 0

(The part in bold resembles 0x59 that i assigned for ASCII 'Y')


the other 2 bytes seemed to get muddled up and I only sent 2 bytes out...
however, because i had to keep RC0 "HIGH" for this to happen so im guessing that

1. Im not getting 3 bytes but actually a consecutive repetition of the 2 bytes which results in:
2. the waveform getting muddled up..




referring to this part,

for(count=0;count<2;count++)
{
out=data[count];
while(!TXIF);
TXREG=out;
}
DelayMs(250);


at the point where the delay is executed , im assuming the line be held back to a 'HIGH IDLE' state before the next byte is transmitted?
therefore when observing the output on the scope, i have to take into consideration an additional couple of parts of the waveform where there will be a continuous stream of Logic 1's during the delay?


so i guess the best way to test UART transmissionis by using hyper terminal or to another PIC..

is my understanding of the matter correct?

2ndly,

if i were to use a PIC to receive, and i do not know the amount of bytes that are coming in, is the reception correctly implemented as follows?

while(!RXIF);
rcivdata[]=RCREG;
out=rcivdata;


if 2 bytes are received and i want to store and retrieve these 2 bytes ..how should i do it..


once again ,thank you so much for your help
 

Pommie

Well-Known Member
Most Helpful Member
I think you will get the best results looking in hyperterminal. You'll need to hook it up via a max232 to get the correct levels.

You code to receive is correct but your array would need an index.

Mike.
 

qtommer

Member
sorry for the late reply as i have been extremely busy..

I have interfaced the PIC to Hyper Terminal via MAX 232, I sent out the ASCII character A in an infinite loop from the Tx pin.

I noticed the waveform on the RS-232 output pin of the MAX -232 (PIC ATTACHED)
Logic 1s on the waveform seem to be spiked and do not resemble a perfectly undistorted square wave..Are RS-232 waveforms meant to be like that? Or could it be noise generated by the MAX 232?

However, I managed to get the desired output on Hyper Terminal...Some of the characters got distorted though( PIC ATTACHED) .. Could it be that I have to insert a LONGER delay between the transmission of each byte?
 

Attachments

  • Untitled picture.png
    Untitled picture.png
    440 KB · Views: 124

mneary

New Member
The MAX232 is not providing the current required to drive your PC input. It probably means that the capacitors (on the data sheet page 17, C1 thru C5.) All capacitors must be 1.0µF or greater. I would say anything between 1.0 and 10µF is OK. Polarity is important. To confirm proper operation, make sure the voltages on pin 2 (+10) and pin 6 (-10) are OK. Anything from 8V upwards (during transmission) indicates that it's working.
 

qtommer

Member
the capacitors used are 1.0uF using MAX232 (Not 232A)...anyway ill give pin 2 and 6 a check on the DMM when i get back to the lab..thanks!
 

mneary

New Member
I have seen high ESR capacitors causing problems. The problem was on a MAX202, but the principle is the same as your MAX232. The caps must be low ESR. In that case the designer thought that cheap 10µF electrolytic capacitors would be better than the 0.1µF ceramic in the MAX202 app notes. He was wrong.
 

Sceadwian

Banned
Tantalums might work well.
 

qtommer

Member
using the 1uF caps ,
on pin2 i got around 8.5V which is pretty okay

however pin 6 yielded a value of -0.5V

i tried a variety of different caps. 0.1uF(electrolytic and ceramic) and even 10uF
all yielded the same value of approx -0.5V..

should i increase the value of the capacitor to 100uF?will it spoil the max232?
 

mneary

New Member
If you only get -0.5V then something else is wrong. Check to see if one of the RSS232 outputs is shorted. If that doesn't help, try another MAX232.

10 or 100µF won't hurt anything, but it's not likely to help.
 
Last edited:

qtommer

Member
sorry for the late reply as i have been superbly bz,
ill give the circuit a check soon..

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

I am trying to send out "AT" to the handphone and verify if i have received OK from the handphone in which a LED would turn on.

How should I implement the routine for receiving the OK?

my code is thus far as follows:

#define A 0x41 //assign ASCII byte code to A
#define T 0x54 //assign ASCII byte code to T
#define R 0x0d //assign ASCII byte code for Carriage Return

void serial_setup(void)
{
SPBRG=25;
BRGH=1; //data rate for sending
SYNC=0; //asynchronous
SPEN=1; //enable serial port pins
CREN=1; //enable reception
SREN=0; //no effect
TXIE=0; //disable tx interrupts
RCIE=0; //disable rx interrupts
TX9=0; //8-bit transmission
RX9=0; //8-bit reception
TXEN=0; //reset transmitter
TXEN=1; //enable the transmitter

}

///////////////////////////////////send AT routine//////////////////////////////////

void ATOK(void)
{
unsigned char data[3]="A","T","R"; //store bytes in array because bytes are to be sent one by one.
int count;
unsigned char out;

for(count=0;count<3;count++)
{
out=data[count];
while(!TXIF);
TXREG=out;
__delay_ms(250);
__delay_ms(250);
}
}

///////////////////////////////Main Routine//////////////////////////////

void main()
{
serial_setup(); //Set up transmit and receive registers
ATOK();
}


thanks!
 
Last edited:

Pommie

Well-Known Member
Most Helpful Member
That wont even compile. Can you post code that at least compiles. The first line that gives an error is the line I asked about 1 month ago.
Code:
unsigned char data[3]="A","T","R"; //store bytes in array because bytes are to be sent one by one.

Mike.
 
Status
Not open for further replies.

EE World Online Articles

Loading
Top