super_castle
04.02.2006, 17:52
software-serielle übertragung mit winavr-c.
rx über int0 und tx über portb.1 .
kann auch anders gelegt werden.
die zeiten für wtic habe ich mit dem programm avrdelayloop ermittelt (zb. 1/19000bps) und die zeit
mit dem programm in eine zeitschleife umgewandelt.
zur zeit läuft es mit 19200bps und avr16 mit 8mhz.
komischerweise musste ich die zeit wtic_1 in der empfangsroutine um 13 takte verkürzen,
beim reinen asm-programm aber nicht.
die kontrolle mache ich z.z. über dem display, ist nicht der normalfall.
läuft wunderbar, kann daten am pc eintippen und es kommen auch daten an ohne fehler.
wenn einer sich auskennt, kann er mal die xtal-frequez reinbringen in die asm-routine, damit man nicht dauernd
beim ändern der bps die zeiten neu eintragen muss, oder man macht sich für die veschiedenen bps eine tabelle.
für vorschläge wäre ich dankbar.
mfg
castle
#include <inttypes.h>
#include <avr/pgmspace.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/signal.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include "lcd.h"
#include "lcd.c"
#define delay_us(us) _delayFourCycles_( ( ( 1*(F_CPU/4000) )*us)/1500 )
uint8_t x;
volatile uint8_t wert_send;
volatile uint8_t wert_empf;
extern void soft_uart_send(void);
extern void soft_uart_empf(void);
static inline void _delayFourCycles_(uint16_t z)
{
uint16_t i;
for (i=0; i<z; i++)
asm volatile("nop");
}
static inline void delay_ms(uint16_t z)
{
uint16_t i;
for (i=0; i<z; i++)
delay_us(999);
}
SIGNAL(SIG_INTERRUPT0)
{
char buffer[7];
GICR&= ~(1<<INT0);
soft_uart_empf();
x=wert_empf;
itoa( x , buffer, 10);
lcd_clrscr();
lcd_puts(buffer);
GIFR|=(1<<INTF0);
GICR|=(1<<INT0);
}
int main(void)
{
uint8_t i;
DDRB|=(1 << PB1);
DDRD&=~(1 << PD2);
PORTB&=~(1 << PB1);
GICR|=(1<<INT0);
MCUCR|=(1<<ISC01);
sei();
lcd_init(LCD_DISP_ON);
lcd_clrscr();
while(1)
{
for (i = 70; i < 90; i++)
{
delay_ms(200);
wert_send=i;
soft_uart_send();
wert_send=10;
soft_uart_send();
wert_send=13;
soft_uart_send();
}
delay_ms(1);
}
}
die "send_empf_asm.S"
#include <avr/io.h>
.global soft_uart_send
.func soft_uart_send
soft_uart_send:
lds r24,wert_send
__Com1O:
ldi r25,10
Com r24
sec
__C1O0:
brcc __C1O1
ldi r16,0
out _SFR_IO_ADDR(PORTB),r16
rjmp __C1O2
__C1O1:
ldi r16,2
out _SFR_IO_ADDR(PORTB),r16
Nop
__C1O2:
rcall __Wtic
lsr r24
dec r25
brne __C1O0
rjmp __ende
__Wtic:
ldi R17,138
WGLOOP0:
dec R17
brne WGLOOP0
ret
__ende:
.endfunc
.global soft_uart_empf
.func soft_uart_empf
soft_uart_empf:
__Com1I:
ldi r24,0x09
rcall __Wtic_1
__C1I2:
rcall __Wtic_1
clc
in R16, _SFR_IO_ADDR(PIND)
SBRC R16,2
sec
dec r24
breq __ende_1
ror r18
rjmp __C1I2
__Wtic_1:
ldi R17,125
WGLOOP1:
dec R17
brne WGLOOP1
ret
__ende_1:
sts wert_empf,r18
.endfunc
.end
rx über int0 und tx über portb.1 .
kann auch anders gelegt werden.
die zeiten für wtic habe ich mit dem programm avrdelayloop ermittelt (zb. 1/19000bps) und die zeit
mit dem programm in eine zeitschleife umgewandelt.
zur zeit läuft es mit 19200bps und avr16 mit 8mhz.
komischerweise musste ich die zeit wtic_1 in der empfangsroutine um 13 takte verkürzen,
beim reinen asm-programm aber nicht.
die kontrolle mache ich z.z. über dem display, ist nicht der normalfall.
läuft wunderbar, kann daten am pc eintippen und es kommen auch daten an ohne fehler.
wenn einer sich auskennt, kann er mal die xtal-frequez reinbringen in die asm-routine, damit man nicht dauernd
beim ändern der bps die zeiten neu eintragen muss, oder man macht sich für die veschiedenen bps eine tabelle.
für vorschläge wäre ich dankbar.
mfg
castle
#include <inttypes.h>
#include <avr/pgmspace.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/signal.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include "lcd.h"
#include "lcd.c"
#define delay_us(us) _delayFourCycles_( ( ( 1*(F_CPU/4000) )*us)/1500 )
uint8_t x;
volatile uint8_t wert_send;
volatile uint8_t wert_empf;
extern void soft_uart_send(void);
extern void soft_uart_empf(void);
static inline void _delayFourCycles_(uint16_t z)
{
uint16_t i;
for (i=0; i<z; i++)
asm volatile("nop");
}
static inline void delay_ms(uint16_t z)
{
uint16_t i;
for (i=0; i<z; i++)
delay_us(999);
}
SIGNAL(SIG_INTERRUPT0)
{
char buffer[7];
GICR&= ~(1<<INT0);
soft_uart_empf();
x=wert_empf;
itoa( x , buffer, 10);
lcd_clrscr();
lcd_puts(buffer);
GIFR|=(1<<INTF0);
GICR|=(1<<INT0);
}
int main(void)
{
uint8_t i;
DDRB|=(1 << PB1);
DDRD&=~(1 << PD2);
PORTB&=~(1 << PB1);
GICR|=(1<<INT0);
MCUCR|=(1<<ISC01);
sei();
lcd_init(LCD_DISP_ON);
lcd_clrscr();
while(1)
{
for (i = 70; i < 90; i++)
{
delay_ms(200);
wert_send=i;
soft_uart_send();
wert_send=10;
soft_uart_send();
wert_send=13;
soft_uart_send();
}
delay_ms(1);
}
}
die "send_empf_asm.S"
#include <avr/io.h>
.global soft_uart_send
.func soft_uart_send
soft_uart_send:
lds r24,wert_send
__Com1O:
ldi r25,10
Com r24
sec
__C1O0:
brcc __C1O1
ldi r16,0
out _SFR_IO_ADDR(PORTB),r16
rjmp __C1O2
__C1O1:
ldi r16,2
out _SFR_IO_ADDR(PORTB),r16
Nop
__C1O2:
rcall __Wtic
lsr r24
dec r25
brne __C1O0
rjmp __ende
__Wtic:
ldi R17,138
WGLOOP0:
dec R17
brne WGLOOP0
ret
__ende:
.endfunc
.global soft_uart_empf
.func soft_uart_empf
soft_uart_empf:
__Com1I:
ldi r24,0x09
rcall __Wtic_1
__C1I2:
rcall __Wtic_1
clc
in R16, _SFR_IO_ADDR(PIND)
SBRC R16,2
sec
dec r24
breq __ende_1
ror r18
rjmp __C1I2
__Wtic_1:
ldi R17,125
WGLOOP1:
dec R17
brne WGLOOP1
ret
__ende_1:
sts wert_empf,r18
.endfunc
.end