Desperate: Need to implement software UART on ATmega16L

Go To Last Post
7 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

:cry:
Hi,
We desparately need help in implementing a software UART. Any suggestions or comments much appreciated.

Thanks

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

If you are using a MEGA16, then why don't you use the hardware USART onboard ? Do you have more than one asynchronous channel to implement ?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

If you are using a MEGA16, then why don't you use the hardware USART onboard ? Do you have more than one asynchronous channel to implement ?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

yes... we need 2 uarts...

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I have attached a document which should get you started in the right direction. A software UART is all about timing and state detection. Here are some states and conditions that you will have to detect.

1. Idle state (idle line longer than stop bit time).
2. Start Bit detection.
3. Delay 1/2 bit time
4. Start bit verification
5. Delay 1 bit between bit samples in middle of bit cells. (more samples may improve performance in high noise environments - majority voting)
6. Stop Bit detection (if stop bits not in correct place, framing error)

Attachment(s): 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Tell me your frequency, speed, # of bits (8 or 9) and I'll code one up for you.

Regards

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Here is a receiver. Change the .EQU and you should be set.

I used tricks of the trade to slim the code down like shifting a bit across the byte
being built to determine when we are finished shifting in bits.

Also, instead of delaying additional time in the end since we are in the middle of bit 8,
I exit immediately if the io line is already high, else we wait till it becomes one.

this saves code and can save time if bit 7 was a 0.

I dont have time to write a transmitter right now but can if you still need it.

.include "2313def.inc"

	  .equ	mhz		= 4000000	; 4 mhz = 250ns
	  .equ	baud	= 9600		; 9600 baud = 104.166us

	  .equ	etu		= (mhz/baud) ; 416 * 250e-9 = 104.0us


	  .equ	halfetu = (etu-1) / 6	; 69 @ 9600 (*3 = 207= 51.75us)
	  .equ	fulletu	= (etu-5) / 3	; 137   (*3 = 411= 102.75us)
	  								; 154.75us initial bit. (156.249 official)
	  

	; 620 clocks into first bit once startbit detected = 155.00 us


	  .equ	RxIO	= 0	; PortD.0
	  .equ	TxIO	= 1	; PortD.1

	  .equ	RxPin	= pind		; Rx uses pind.RxIO
	  .equ	TxPort	= portd		; Tx uses portd.TxIO



	  .def	a		= r16
	  .def	b		= r17


			; Routine exits with a byte in A (r16)
			; requires 1 extra byte of stack space for b (r17)
			;
Rx:			push	b	
	  		;- - - - - - - - - - - -;
RxStLp:		sbic	RxPin, RxIO		;2 wait on start bit (io = 0)
	     	 rjmp   RxStLp			;2
	    	;- - - - - - - - - - - -;	
			; 620 clocks initial	; 155.00uS
			; timing on start bit	;
			;- - - - - - - - - - - -;
			ldi		b, halfetu		;\
RxSDel:		dec		b				; + 3 clk * halfetu
			 brne   RxSDel			;/
			;- - - - - - - - - - - -;
			ldi		a, 0x80			;1 shift 8 bits right
			;- - - - - - - - - - - -;
			; 416 clocks per bit    ;		
			; 104.00uS @ 4 mhz		;
			;- - - - - - - - - - - -;
RxBitLp:	ldi		b, fulletu		;\		
RxDelLp:	dec		b				; + 3 clk * fulletu
	   		 brne	RxDelLp			;/ 
			;- - - - - - - - - - - -;
	  		in		b, RxPin	   	;1 Pull Rx pin value
	  		lsr		b		       	;1 Bit.0 -> Carry 
	  		;- - - - - - - - - - - -;
	  		ror		a            	;1 CY -> Bit.76543210
	  		;- - - - - - - - - - - -;
			 brcc	RxBitLp			;2 if cy = 0, get another bit  		  		
			;- - - - - - - - - - - -;
			; we are in middle of   ;
			; wait till we see io   ;
			; line to high to exit  ;
			;- - - - - - - - - - - -;
RxWEnd:		sbis	RxPin, RxIO		;2 wait on stop bit (io = 1)
			 rjmp	RxWEnd
pop    b		
	;
			ret						;4 done
			

			.exit	  

Regards