|
|
View previous topic :: View next topic |
Author |
Message |
doryme
Joined: 16 Oct 2010 Posts: 20
|
problem with 16f877a and RS232 |
Posted: Sat Nov 27, 2010 6:14 am |
|
|
Hello
This is my code to convert analog voltage to digital and send it via RS232 cable
Code: |
#INCLUDE <16F877A.h>
#device adc=10
#fuses HS,NOWDT,NOPROTECT,NOLVP
#USE DELAY (CLOCK=10000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7)
void main()
{
unsigned int16 adc_value;
setup_adc(ADC_CLOCK_DIV_16);
setup_adc_ports(ANALOG_RA3_REF);
set_adc_channel(0);
delay_us(20);
while(1)
{
adc_value=read_adc();
printf("%lu",adc_value);
delay_ms(500);
output_d(adc_value);
}
}
|
As you see, I output 8 bits of the converted 10 bits on PORTD to check the it converts correctly.
When I ran simulation and input was 3V I get this:
3V should be converted to 1001100110
and that's correct on Leds connected to PORTD (first 8 bits are correct)
The problem is on printf function. I don't get the expected value on the oscilloscope.
What is the problem here?!
Can someone tell me how printf works? It send extra bits or flags?
I should get 16 bits as follow: 000000 1001100110
or: 1001100110 000000
Another question, how can i make pin RA0 only analog and RA3 as VREF?
I tried setup_adc_ports(AN0_RA3_REF); but it didn't work
last question, Is there a method to send only 10 bits of adc_value and not to send all the 16 bits?
Thanks in advance |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9225 Location: Greensville,Ontario
|
|
Posted: Sat Nov 27, 2010 6:40 am |
|
|
Hmm..
last question first.
Yes, you can send only the 10 bits of the ADC result , if you want.
Simply create a bit-banged (software) UART.Old school, yet I do it all the time,it's a great security feature! .Be aware that while you're bit-banging, that all else stops(except any enabled interrupts, which will kill your SW UART!)Sending 10 bits is faster than sending 16 bits ....
...However, if you're sending this data to a PC or other 'standard RS-232' device, you'll want to send both bytes.The 'other' end won't understand your 10 bit RS-232 datastream and you'll get errors.
So unless you're designing the other end, stick with the 'standard' of sending regular 8bit data.
second question second.
Consult the PIC datasheet and the PICdotH file from CCS for the different modes that the pins can be configured for Analog inputs . It varys between PICs.Both places will tell you what you need to know.
first question last.
'Normal' UART / RS-232 communication is 8 bits.The USE RS232(..) you have is set for this by default.When you try to send 10 bits, the top 2 or bottom 2 bits will be 'lost' either by the printf(...) or use rs232(...) functions.Not sure which, dump a listing to follow the code.
hope this helps. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19504
|
|
Posted: Sat Nov 27, 2010 7:58 am |
|
|
As setup, printf, is sending the value as _text_. So your ten bit value, represents a number from 0 to 1023. So for 1001100110, which is 266 in decimal, the printf will send the text character '2', followed by '6', and '6'.
Now, as explained, if is very hard to handle word lengths when talking to other 'kit', outside the range typically of 5 to 9 bits. Also remember that standard 'async serial' (which is what the UART sends), has a leading '0' bit, and a trailing '1' bit added.
You have three basic choices:
1) Define your own protocol, bit bang the data - only useable if you are also in complete control of the hardware at the other end.
2) Send just the bit patterns as two bytes with start and stop bits, without changing the data to ASCII:
Code: |
printf("%c%c", make8(adc_value,1), make8(adc_value,0));
|
3) Best way possibly is to send the value as hex, since this then involves transmitting just three bytes, and wil not use any of the ASCII control characters, allowing you to use CR or LF to mark the 'end' of the data.
Code: |
printf("%03lx", adc_value);
|
Best Wishes |
|
|
doryme
Joined: 16 Oct 2010 Posts: 20
|
|
Posted: Sat Nov 27, 2010 10:51 am |
|
|
Hello
Thank you for your help.
I tried the 3rd choice and got this..I expect to get 101110000
what are CR and LF that i use to mark data? and can I make them anything I want?
I see 3 ones on oscilloscope and some zeros but still can't define my 101110000
Thanks |
|
|
doryme
Joined: 16 Oct 2010 Posts: 20
|
|
Posted: Sat Nov 27, 2010 10:54 am |
|
|
temtronic wrote: | Hmm..
last question first.
Yes, you can send only the 10 bits of the ADC result , if you want.
Simply create a bit-banged (software) UART.Old school, yet I do it all the time,it's a great security feature! .Be aware that while you're bit-banging, that all else stops(except any enabled interrupts, which will kill your SW UART!)Sending 10 bits is faster than sending 16 bits ....
...However, if you're sending this data to a PC or other 'standard RS-232' device, you'll want to send both bytes.The 'other' end won't understand your 10 bit RS-232 datastream and you'll get errors.
So unless you're designing the other end, stick with the 'standard' of sending regular 8bit data.
second question second.
Consult the PIC datasheet and the PICdotH file from CCS for the different modes that the pins can be configured for Analog inputs . It varys between PICs.Both places will tell you what you need to know.
first question last.
'Normal' UART / RS-232 communication is 8 bits.The USE RS232(..) you have is set for this by default.When you try to send 10 bits, the top 2 or bottom 2 bits will be 'lost' either by the printf(...) or use rs232(...) functions.Not sure which, dump a listing to follow the code.
hope this helps. |
Yes I will send these bits to PC so I have to send the 16 bits:S
Thanks alot for your help |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|