- data ist IN *und* out
- RET ist nicht in Ordnung, weil du nicht wissen kannst, wie der Epilog der Funktion aussieht (hier besteht er wirklich nur aus einem RET, aber was, wenn es einen Framepointer gibt oder Register vom Stack gepoppt werden müssen?)
- In deinem Code steht 0x1b, das ist DDRB !?. Treibst du den Ausgang als Open Collector? Falls nicht (push-pull), muss da PORTB hin.
Code:
#include <avr/io.h>
#include <avr/interrupt.h>
#define CR_TAB "\n\t"
#define STOP_BITS 1
void txd (uint8_t data)
{
uint8_t bitcnt = 1+8+STOP_BITS;
uint8_t delay = 19;
data = ~data;
cli();
__asm__ __volatile__(
" sec ; Start bit " CR_TAB
"0: brcc 1f ; If carry set " CR_TAB
" sbi %[port],%[pad] ; send a '0' " CR_TAB
" rjmp 2f ; else " CR_TAB
"1: cbi %[port],%[pad] ; send a '1' " CR_TAB
" nop" CR_TAB
"2: %~call bit_delay_%= ; One bit delay " CR_TAB
" %~call bit_delay_%=" CR_TAB
" lsr %[data] ; Get next bit " CR_TAB
" dec %[bitcnt] ; If not all bit sent " CR_TAB
" brne 0b ; send next " CR_TAB
" rjmp 5f ; else: done " CR_TAB
CR_TAB
"bit_delay_%=:" CR_TAB
" mov __zero_reg__, %[delay]" CR_TAB
"4: dec __zero_reg__" CR_TAB
" brne 4b" CR_TAB
" ret" CR_TAB
"5:" CR_TAB
: [bitcnt] "=r" (bitcnt), [data] "=r" (data)
: "1" (data), "0" (bitcnt), [delay] "r" (delay), [port] "M" (_SFR_IO_ADDR(PORTB)), [pad] "M" (6)
);
sei();
}
Lesezeichen