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.

UARTt 16f887 configuration reception and transmission

Status
Not open for further replies.

lotfibedui

Junior Member level 2
Junior Member level 2
Joined
Mar 12, 2013
Messages
20
Helped
0
Reputation
0
Reaction score
0
Trophy points
1,281
Activity points
1,448
hi
I work on a project to realize a temperature acquisition card based in a 16F887 microcontroller,and controlled by computer, so I tried to configure the UART module in C (with pic C compiler) to be able to exchange data between my card and the PC via the rS 232 connection, but I can not succeed in this task as I am new in this field.
then I will be grateful if someone can give me a C program that allows me to achieve this task.
 

Code:
// This program will send 0-99 with a delay of 1s between the data



#BYTE TXSTA=0x98
#BYTE SPBRG=0x99
#BYTE RCSTA=0x18
#BYTE TXREG=0x19
#BYTE TRISB=0x86
#BYTE TRISA=0x85
#BYTE PCON=0x8E
#BYTE PIE1=0x8C
#BYTE PORTA=0x05
#BIT  RCIE=PIE1.5
#BIT  TXIF=PIE1.4
#BIT  RA1=PORTA.0
#BIT  RA2=PORTA.1
#BIT  TRMT=TXSTA.1


int i=0;



void send_data(int x){
TXREG=x;
while(TRMT==1){};
delay_ms(50);
}
void enable_serial(){
   SPBRG=0x19;        //0x19 = 9600 Baud -  4MHz
   TXSTA=0x24;
   RCSTA=0x80;

}
void disable_serial(){
   TXSTA=0x00;
   RCSTA=0x00;

}


void main()
{

   setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
   setup_timer_1(T1_DISABLED);
   setup_timer_2(T2_DISABLED,0,1);
   setup_comparator(NC_NC_NC_NC);
   setup_vref(FALSE);
//Setup_Oscillator parameter not selected from Intr Oscillator Config tab

enable_serial();
TRISB=0x00;
bit_set(PCON,3);



   // TODO: USER CODE!!
while(1)
    {
      enable_serial();
     
      for(i=0;i<100;i++)
          {
          send_data(i);
          delay_ms(1000);
          }
     
     
      
      
    }





}

This is the simplest program of communication via RS-232 that I know, i made this with the PIC16F627A.
 
It can be simpler!

You only have to set up the UART registers once so you can put the "enable_serial()" code at the beginning of main(), thereis no need to put it in a loop. You can also remove the delay in the "send_data()" routine as it does nothing except add to the delay between sending each character in the main program.

Also note that you are only sending numbers with this program, not receiving anything and the numbers will be 0 to 99 in binary, not printable characters.

Brian.
 

It can be simpler!

You only have to set up the UART registers once so you can put the "enable_serial()" code at the beginning of main(), thereis no need to put it in a loop. You can also remove the delay in the "send_data()" routine as it does nothing except add to the delay between sending each character in the main program.

Also note that you are only sending numbers with this program, not receiving anything and the numbers will be 0 to 99 in binary, not printable characters.

Brian.
thnx a lot man
i'll just publish my code and i ask you if you can tell me what's missing in it and what's wrong in it, and thnk's in advance :grin:

this is my code :

#include <16F887.h>
#DEVICE ADC=10
#use delay(clock=4000000)
#use rs232(Baud=9600,Xmit=pin_C6,rcv=pin_C7,parity=N,BITS=8)

#byte PORTA= 0x05
#byte PORTB= 0x06
#byte PORTC= 0x07
#byte PORTD= 0x08
#byte TRISA= 0x85
#byte TRISB= 0x86
#byte TRISC= 0x87
#byte TRISD= 0x89
#byte TXSTA= 0X98
#byte RCSTA= 0X18
#byte ADRESL=0x9E
#BYTE TXREG= 0x19
#byte ADCON1=0x9F
#byte ADCON0=0x1F
#byte RCSTA= 0x18
#byte ANSEL= 0x188
#byte PIE1 = 0x8c
#byte PIR1 = 0x0c
#bit GODONE= ADCON0.1
#bit ADFM = ADCON1.7
#bit VCFG0=ADCON1.4
#bit VCFG1=ADCON1.5
#bit adcs1=ADCON0.7
#bit adcs0=ADCON0.6
#bit ADON=ADCON0.0
#bit ADIE=PIE1.6
#bit ADIF=PIR1.6
int temp;

/////////////// Initialisation des ports ///////////////

void pic_init()
{

set_tris_A(0XAF);
set_tris_B(0X3F);
set_tris_C(0X81);
set_tris_D(0X80);
set_tris_E(0X07);

}



/////////////// Configuration du CAN ////////////////

void config_adc()
{
setup_adc(ADC_clock_internal);
setup_adc_ports(ALL_ANALOG);
set_adc_channel(0);
delay_ms(500);
set_adc_channel(1);
delay_ms(500);
set_adc_channel(2);
delay_ms(500);
set_adc_channel(3);
delay_ms(500);
set_adc_channel(4);
delay_ms(500);
set_adc_channel(5);
delay_ms(500);
set_adc_channel(6);
delay_ms(500);
set_adc_channel(7);
delay_ms(500);
set_adc_channel(8);
delay_ms(500);
set_adc_channel(9);
delay_ms(500);
set_adc_channel(10);
delay_ms(500);
set_adc_channel(11);
delay_ms(500);
set_adc_channel(12);
delay_ms(500);
set_adc_channel(13);
delay_ms(500);

}

//////// lecture et conversion de la température capté par les sondes ///////

void lect_temp()
{
int v,R,t;
ADON=1;
GODONE=1;
ADIF=0;
ADIE=1;
while(GODONE)
{

v=read_adc()/205.7;
R=v/0.001;
t=(R-1)/25974.025;
delay_us(1000);
ADON=0;

}

}

void config_UART( )
{
TXSTA=0X24;
RCSTA=0X90;
}



////////////////////// programme principal //////////////////////

void main()
{

float temp;
pic_init();
ADRESL=0;
ADFM=1;
ANSEL=0XFF;

config_adc();
temp=lect_temp();
config_uart();
puts(temp);
delay_us(500);
}
 

note that when i try to sumilate my card with ISIS the resualt is always 00
 

I'm not familiar with that 'dialect' of C but I cannot understand what the config_adc() routine does and why it needs so many delays. I think you will also have problems with the math calculations because you are mixing integers with floating point values.

Doesn't "#include <16F887.h>" tell the program the PICs register and bit addresses? Is it necessary to include them twice?
I'm asuming statements like "#bit GODONE= ADCON0.1" is the same as normal C would write as "#define GODONE ADCON0.1" but again that should already be defined in the header file.

Brian.
 

Are you using CCS C Compiler? Is read_adc() a library function? If yes, how does it know which adc channel to read? You are using many ADC channels and I think you have to configute ANSELH = )FF for some channels you have used.

The below code is wrong.

Code C - [expand]
1
2
3
4
5
6
7
8
9
10
while(GODONE)
{
 
v=read_adc()/205.7;
R=v/0.001;
t=(R-1)/25974.025;
delay_us(1000);
ADON=0;
 
}


It should be

Code C - [expand]
1
2
3
4
5
6
while(GODONE)  //loop until GODONE is true
v=read_adc()/205.7;
R=v/0.001;
t=(R-1)/25974.025;
delay_us(1000);
ADON=0;


but if read_adc() is a library function then you don't need all those codes. The whole process of reading and returning adc value is done by read_adc() function.
 

I'm not familiar with that 'dialect' of C but I cannot understand what the config_adc() routine does and why it needs so many delays. I think you will also have problems with the math calculations because you are mixing integers with floating point values.

Doesn't "#include <16F887.h>" tell the program the PICs register and bit addresses? Is it necessary to include them twice?
I'm asuming statements like "#bit GODONE= ADCON0.1" is the same as normal C would write as "#define GODONE ADCON0.1" but again that should already be defined in the header file.

Brian.

config adc () routine allows me to set the clock to the ADC and to choose the analog inputs to be used
# include <16F887.h> allows the compiler to find the location of the project file
 

Are you using CCS C Compiler? Is read_adc() a library function? If yes, how does it know which adc channel to read? You are using many ADC channels and I think you have to configute ANSELH = )FF for some channels you have used.

The below code is wrong.

Code C - [expand]
1
2
3
4
5
6
7
8
9
10
while(GODONE)
{
 
v=read_adc()/205.7;
R=v/0.001;
t=(R-1)/25974.025;
delay_us(1000);
ADON=0;
 
}


It should be

Code C - [expand]
1
2
3
4
5
6
while(GODONE)  //loop until GODONE is true
v=read_adc()/205.7;
R=v/0.001;
t=(R-1)/25974.025;
delay_us(1000);
ADON=0;


but if read_adc() is a library function then you don't need all those codes. The whole process of reading and returning adc value is done by read_adc() function.

yes i use CCS C compiler
read_adc() is a library function

I tried with one chanel in first time but there is always the same problem,when I compile it works without error, but when i sumilate with ISIS that gives a wrong result( always zero) :(

regarding the "while", you must use the { } ,this is a syntax that must be respected
 

egarding the "while", you must use the { } ,this is a syntax that must be respected

I don't like such syntax's if it exists. If you use those braces for the while loop then all the instructions in the block are executed while GODONE is 1. That is not the way. When there is an adc conversion or reading you wait till GODONE is 1 then as soon as it becomes 0, while loop exits and then adc value is returned. But you have to put a ; after the while loop not braces in your example.

See example EX_AD12.C in CCS C examples folder

https://www.ccsinfo.com/forum/viewtopic.php?t=44115&highlight=adc+example
https://www.ccsinfo.com/forum/viewtopic.php?t=44201&highlight=adc+example
 
Last edited:

config adc () routine allows me to set the clock to the ADC and to choose the analog inputs to be used
# include <16F887.h> allows the compiler to find the location of the project file

All channels of the ADC use the same clock settings and there is no need to use a delay so you can remove all that code completely.

I write lots of 'C' code so I know what the #include directive does! What I was pointing out is that inside 16F887.h is all the names or registers and their addresses and also all the bit names and numbers so there is no need to use any of the #byte and #bit lines. If you open 16F887.h in an editor you will see they are defined inside that file. When you use "#include" it tells the compiler to include all the contents of the file at that point in the program so from there on it knows the names of all the registers and bits without you having to tell it again.

jayanth.devarayanadurga is correct, when you start the ADC it takes a short time for it to return it's result so you have to wait for it to finish. The line "while(GODONE);" is saying "do nothing while the GODONE bit is 1" so the program does not continue until the bit returns to zero which means the conversion is finished. Obviously, you can't do the calculation until you know the ADC value it is to use. Note that some compilers will give an error unless you add { } after the while().

I am still suspicious that the calculation will not work though. You are mixing float and int data types. Maybe CCS lets you do this but you should really use float variables or a castes or you will lose precision, possibly completely!

Brian.
 

thank's alot friends
I tried everything you advised me but it did not work :-(
any other solution ?
 

If you are using library functions of CCS C Compiler then you don't have to write all those extra adc codes you have written. Post your latest code. When I have some time I will look into CCS C manual and see what adc library functions you need to use for adc and write a working code.
 

If you are using library functions of CCS C Compiler then you don't have to write all those extra adc codes you have written. Post your latest code. When I have some time I will look into CCS C manual and see what adc library functions you need to use for adc and write a working code.

okey thnx man
this is my latest code :
Code:
#include <16F887.h>
#DEVICE ADC=10
#use delay(clock=4000000)
#use rs232(Baud=9600,Xmit=pin_C6,rcv=pin_C7,parity=N,BITS=8)


#byte PORTA= 0x05
#byte PORTB= 0x06
#byte PORTC= 0x07
#byte PORTD= 0x08
#byte TRISA= 0x85
#byte TRISB= 0x86
#byte TRISC= 0x87
#byte TRISD= 0x89
#byte TXSTA= 0X98
#byte RCSTA= 0X18
#BYTE SPBRG= 0x99
#byte ADRESL=0x9E
#BYTE TXREG= 0x19
#byte ADCON1=0x9F
#byte ADCON0=0x1F
#byte RCSTA= 0x18
#byte ANSEL= 0x188
#byte PIE1 = 0x8c
#byte PIR1 = 0x0c

#BYTE SPBRG=0x99
#BYTE TRISB=0x86
#BYTE TRISA=0x85
#BYTE PCON= 0x8E
#BYTE PORTA=0x05

#bit GODONE= ADCON0.1
#bit ADFM = ADCON1.7
#bit VCFG0=ADCON1.4
#bit VCFG1=ADCON1.5
#bit adcs1=ADCON0.7
#bit adcs0=ADCON0.6
#bit ADON=ADCON0.0
#bit ADIE=PIE1.6
#bit ADIF=PIR1.6
///////////////////////
#BIT  RCIE=PIE1.5
#BIT  TXIF=PIE1.4
#BIT  RA1=PORTA.0
#BIT  RA2=PORTA.1
#BIT  TRMT=TXSTA.1


int i=0;
float v,R,T;
/////////////// Initialisation des ports ///////////////

void pic_init()
{

set_tris_A(0XAF);
set_tris_B(0X3F);
set_tris_C(0X81);
set_tris_D(0X80);
set_tris_E(0X07);

}



/////////////// Configuration du CAN ////////////////

void config_adc()
{


setup_adc(ADC_clock_internal);
setup_adc_ports(ALL_ANALOG);
set_adc_channel(0);


}

//////// lecture et conversion de la température capté par les sondes ///////



void lect_temp()
{

///int R;
ADON=1;
GODONE=1;
ADIF=0;
ADIE=1;
while(GODONE)
{


v=read_adc();
delay_us(1000);


}

ADON=0;
R=v/0.2057;  //0.001;
T=(R-1)/25974.025;


}

///////////////////////////// configuration du USART ///////////////////////////

void config_UART( )
{
TXSTA=0X24;
RCSTA=0X90;
}


///////////////////  Configuration du rs232  /////////////////////



void send_data(int x)
{

x=T;
TXREG=x;
while(TRMT==1);
{
delay_ms(50);
}

}

void enable_serial()
{
   SPBRG=0x19;        //0x19 = 9600 Baud -  4MHz
   TXSTA=0x24;
   RCSTA=0x80;

}

void disable_serial()
{

   TXSTA=0x00;
   RCSTA=0x00;

}


 ////////////////////// programme principal //////////////////////

void main()
{


float temp;
pic_init();
ADRESL=0;
ADFM=1;
ANSEL=0XFF;


   setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
   setup_timer_1(T1_DISABLED);
   setup_timer_2(T2_DISABLED,0,1);
   setup_comparator(NC_NC_NC_NC);
   setup_vref(FALSE);



config_adc();
temp=lect_temp();
config_uart();
TXREG=temp;


//Setup_Oscillator parameter not selected from Intr Oscillator Config tab

enable_serial();
bit_set(PCON,3);

   // TODO: USER CODE!!

      enable_serial();

          send_data(i);
          delay_ms(1000);




}

i'm tryed to write this code for 1 input chanel and when it work i'll do it for my 14 input chanel
please try to write a code for me and compile it with CCS C compiler
thnx in advence for your time :)
 
Last edited by a moderator:

Is your LCD code working?

no i'm not using an LCD
my card is contolled by computer (graphical interface with visual basic studio 2010),but in simulation i use an isis component telled "Virtual Terminal" because my graphical interface is not ready yet !!
 

It's getting better and shorter as well but please remove all the lines starting with #byte and #bit, they should not be necessary. They are already declared in the ".h" file so you don't need to declare them again.

Also, you probably want to use the value 0x90 instead of 0x80 in RCSTA inside your enable_serial() routine.

Brian.
 

It's getting better and shorter as well but please remove all the lines starting with #byte and #bit, they should not be necessary. They are already declared in the ".h" file so you don't need to declare them again.

Also, you probably want to use the value 0x90 instead of 0x80 in RCSTA inside your enable_serial() routine.

Brian.

thnx betwix
i tryed to remove the #byte and # bit as you said but it's give a lot of error when i compile the program without them !!!
 

Status
Not open for further replies.

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top