ATtiny13 in one of my eeZee Tiny boards |
Receive is harder. I didn't do that because I don't really need it right now. If you dare me I might do it. But for now the communication is in one direction.
TTL Serial Protocol
Most typically, serial communication involves 8 data bits, no parity, and one stop bit (8N1). When sending TTL level (5V and 0V) serial, the idle state of the line is 5V. A start bit, 0V, is sent as the first bit, followed by the LSB of the data byte up through the MSB. After this, the stop bit is sent, a 5V signal.I started with the code that would send the data byte. I planned to use a timer interrupt handler for timing the bits, but as an initial baby step, I just created a loop that would shift bits out one at a time.
I used r16 as the 1-byte buffer. The data placed in here is shifted out. A counter register, r17, counts the number of bits to send. It's set to 8 to begin with
.include "tn13Adef.inc" ; definitions for ATtiny13A
.def txreg = r16 ; transmit 'buffer'
.def bitcnt = r17 ; bit counter
.equ TXPIN = PB0 ; TX pin is PB0
.cseg
.org 0x00
rjmp start ; executed after reset
start:
ldi r16, 0x6D ; 'm'
ldi r17, 8 ; put 8 in counter register
txloop:
lsr r16 ; shift off the next bit, LSB first
brcs Send1 ; if it is 1 (C=1) then send 1
Send0:
cbi PORTB, TXPIN ; send a 0=low
rjmp BitDone
Send1:
sbi PORTB, TXPIN ; send a 1=high
BitDone:
dec bitcnt ; bitcnt--
breq start ; if bitcnt == 0, start over
rjmp txloop ; else do the next bit
Next I added the logic to send the start bit. Instead of setting r17 to 8 I set it to 9 and then added special logic to send the start bit as the first bit.
start:
ldi r16, 0x6D ; 'm'
ldi r17, 9 ; put 9 in counter register
txloop:
cpi r17, 9 ; if r17 == 9 (first bit)
breq Send0 ; send start bit (low)
lsr r16 ; shift off the next bit, LSB first
brcs Send1 ; if it is 1 (C=1) then send 1
Send0:
cbi PORTB, TXPIN ; send a 0=low
rjmp BitDone
Send1:
sbi PORTB, TXPIN ; send a 1=high
BitDone:
dec bitcnt ; bitcnt--
breq start ; if bitcnt == 0, start over
rjmp txloop ; else do the next bit
Finally I added logic to send the stop bit after the last data bit is sent or when bitcnt == 0. The stop bit is a high signal. Then, I reworked the code to run within an interrupt service routine.
- The routine sends a stop bit (high/idle) whenever bitcnt == 0 or on bitcnt == 1
- To send data, load the character into txreg then set bitcnt to 10: 8 data bits, 1 start bit, 1 stop bit
- The routine will send a start bit then shift out 8 bits of data, then a stop bit
Timing
Tuned Delay Loop
A simple way to deal with timing is to implement precision delay loops. Here's a link to my latest version that simply pauses after setting a bit and pauses in between bytes. Works great.
I used this delay calculator. In this tool under Wine I could not generate a loop based on time input, but I could generate a loop by calculating cycles. A delay of 1000 cycles at 9.6MHz will give a 9600bps output assuming the chip's internal oscillator is correct. After tuning the loop, my Saleae Logic analyzer tells me the bitstream was clocking in at 4800.77Hz while sending out "U" (binary: 01010101) repeatedly. That's plenty close.
Timing With Timer
In the original version which I can't find now, the transmit routine runs off a timer interrupt handler. The ATtiny13 has one timer and you can set up an interrupt to occur on compare match.
In other words, you put the timer in Clear on Timer Compare (CTC) mode and then set the compare register OCR0A to some number, and when the timer counter TCNT0 reaches that number, it fires an interrupt and then resets the counter. This is the method to schedule interrupts to occur at fixed intervals.
- Divide the clock by some value, 1, 8, 64, 256 or 1024 to prescale the timer
- Select CTC mode and set OCR0A as a second divider
- For a 4800Hz interrupt frequency from a 4.8MHz clock use /8 and /125
4347 baud is nowhere close! No wonder this didn't work. |
Close enough for the PC serial terminal to get the right data |
Time Delay
Here's a nice tool for calculating and creating a fixed time delay routinehttp://bretm.home.comcast.net/~bretm/avrdelay.html
That's it for now. I'll post more about the sensor project as I progress.
No comments:
Post a Comment
Note: Only a member of this blog may post a comment.