uart/rs232 implementation (7e1)
Discussion in "8051 Discussion Forum" started by Suilied Apr 18, 2014.
Fri Apr 18 2014, 08:45 pm
Hello,
I'm having trouble getting rs232 communication working with my AT89C51cc03.
The baudrate seems to be working just fine because I can see the rx LEDs light up whenever I send something. However I need to send the data as follows: 1 start bit, 7 data bits, 1 even parity bit and 1 stop bit.
Here is a small snippet that shows part of the implementation I copied from a colleague, it shows the tx function with uneven parity.
<cant seem to format the code in a readable fassion so here's a screenshot instead>
I'm having trouble getting rs232 communication working with my AT89C51cc03.
The baudrate seems to be working just fine because I can see the rx LEDs light up whenever I send something. However I need to send the data as follows: 1 start bit, 7 data bits, 1 even parity bit and 1 stop bit.
Here is a small snippet that shows part of the implementation I copied from a colleague, it shows the tx function with uneven parity.
<cant seem to format the code in a readable fassion so here's a screenshot instead>
Wed Apr 23 2014, 10:28 am
the RX LED will lit up even if you have wrong baudrate setup. I would prefer to see the uart initialization code instead as I do not see any issue in this sending loop.
Wed Apr 23 2014, 04:12 pm
the RX LED will lit up even if you have wrong baudrate setup. I would prefer to see the uart initialization code instead as I do not see any issue in this sending loop. - See more at: http://www.8051projects.net/plugins/forum/forum_post.php?rp.63403#sthash.3I6QE0pe.dpuf
This code sits in a big assembly initialisation routine, and it works, because I managed to get sending messages in 7e1 format working!
Turns out that all I had to do was "format" my output stream.
Normally I'd send my data like this:
void ReadParameter() { uint i=0; com_buf[i++] = 0x04; // end of text com_buf[i++] = 0x30; // node address hi com_buf[i++] = 0x30; // node address lo com_buf[i++] = 0x30; // parameter address 0 com_buf[i++] = 0x32; // parameter address 1 com_buf[i++] = 0x30; // parameter address 2 com_buf[i++] = 0x30; // parameter address 3 com_buf[i++] = 0x05; // enquiry com_tx_start(i); }
( "com_buf" is a global variable. )
I was thinking I'd need to do something low level in assembly in order to get communication working. When monitoring my outgoing data stream with "Realterm" ( highly recommend this program to debug any rs232 applications ) I found out that only some data would be received if I set it to 7e1 mode. Turns out that only the data with even parity got accepted. (duh)
So I made a little subroutine to parse my "com_buf" to be even parity.
void TxCalcParity( uint aSize ) { bit parity; uint i; for( i=0; i < aSize; i++ ) { parity = 0; // start out even parity = com_buf[i] & 0x40 ? !parity: parity; parity = com_buf[i] & 0x20 ? !parity: parity; parity = com_buf[i] & 0x10 ? !parity: parity; parity = com_buf[i] & 0x08 ? !parity: parity; parity = com_buf[i] & 0x04 ? !parity: parity; parity = com_buf[i] & 0x02 ? !parity: parity; parity = com_buf[i] & 0x01 ? !parity: parity; if( parity ) { com_buf[i] += 0x80; } } }
Parity is checked on the MSB, so if it is uneven we add 0x80 ( 0b10000000 ) in order to make it's parity even.
Because you are now getting data back from the other machine you must not forget to also parse the incomming messages in order to filter out the parity bit. Luckily this is much easier to do:
void RxCalcParity( uint aSize ) { uint i; for( i=0; i < aSize; i++ ) { com_buf[i] = com_buf[i] & 0x7f; //remove parity bit } }
I'm sure there is some sort of way to do this in the assembly part that I posted originally, but for now this yields statisfying results.
<edit: fixed image.>
[ Edited Wed Apr 23 2014, 04:16 pm ]
Fri Apr 25 2014, 09:52 am
Now I understand the problem, Usually when you configure your UART to enable parity (even or odd) Uart controller generates parity bit according to data being sent. You do not have manually add parity bit to your data. But in case of 8051 as 7-bit mode is not there so you need to add the parity bit in your last bit to be sent.
To generate even parity, you need to count number of 1 bits in 7-bit data. if count is even, partiy is 1 else parity is 0.
To generate even parity, you need to count number of 1 bits in 7-bit data. if count is even, partiy is 1 else parity is 0.
clr c ;we will check for bits in here mov r0, #0 ;store 1 bits count mov r1, #8 ;Loop for only 7 bits mov r2, #data ;keep copy of data Loop: DJNZ r1, end_loop mov A, r2 ;move data to acc RRC A ;shift LSB to carry JNC Loop ;skip if bit is not 1 inc r0 ;found 1, increment bit counter sjmp Loop end_loop: ; Now check for even or odd mov A, r0 anl A, #1 ;if LSB is 1 then its an odd number JNZ finish mov A, r2 ;store parity anl A, #80H finish: ;end of parity calculate
Powered by e107 Forum System