Mikrocontroller und Digitale Elektronik
›
Thread
Atmega8 Timer stoert TWI
Hi,
ich habe einen interrupt gesteuerten TWI Slave. Funktioniert auch.
Auf dem selben uC habe ich nun einen Timer laufen, der eine Software PWM
fuer 6 Servos bedient. Das Funktioniert fuer sich alleine auch.
Wenn ich nun beide Teile zusammen betreibe, kommt ueber TWI nur noch
Muell am Master an. Die Servos funktionieren.
TWI ist Hardware an C4 und C5, mit Pullup-Widerstaenden und die Servos
sind an B0-B5. Also keinerlei Beeinflussung durch Portueberschneidung.
Ich habe keine Ahnung mehr, wieso das nicht klappt.
Gruesse
Dusty
K
Klempner
Gast
08.08.2011 14:45
#2296993
Ja
soll jetzt geraten werden ?
AW
Alex W.
Gast
08.08.2011 14:46
#2296996
Schau Dir den Quellcode nochmals an! In Zeile 42 hast Du misst gebaut!
Ok, hier die Quellen:-)
Der TWI-Teil
1 #include <util/twi.h> // Bezeichnungen f�r Statuscodes in TWSR
2 #include <avr/interrupt.h> // behandlung der Interrupts
3 #include <stdint.h> // definiert Datentyp uint8_t
4 #include "twislave.h"
5 #include "config.h"
6
7 //#################################### Macros
8 //ACK nach empfangenen Daten senden/ ACK nach gesendeten Daten erwarten
9 #define TWCR_ACK TWCR = (1<<TWEN)|(1<<TWIE)|(1<<TWINT)|(1<<TWEA)|(0<<TWSTA)|(0<<TWSTO)|(0<<TWWC);
10
11 //NACK nach empfangenen Daten senden/ NACK nach gesendeten Daten erwarten
12 #define TWCR_NACK TWCR = (1<<TWEN)|(1<<TWIE)|(1<<TWINT)|(0<<TWEA)|(0<<TWSTA)|(0<<TWSTO)|(0<<TWWC);
13
14 //switched to the non adressed slave mode...
15 #define TWCR_RESET TWCR = (1<<TWEN)|(1<<TWIE)|(1<<TWINT)|(1<<TWEA)|(0<<TWSTA)|(0<<TWSTO)|(0<<TWWC);
16
17 //########################################################################################## init_twi_slave
18 void init_twi_slave ( uint8_t adr )
19 {
20 TWAR = ( adr << 1 ); //Adresse setzen
21 TWCR &= ~ ( 1 << TWSTA ) | ( 1 << TWSTO );
22 TWCR |= ( 1 << TWEA ) | ( 1 << TWEN ) | ( 1 << TWIE );
23 buffer_adr = 0 ;
24 }
25
26
27 #define LED0 PB6
28 #define LED1 PB7
29
30
31 //########################################################################################## ISR (TWI_vect)
32 ISR ( TWI_vect )
33 {
34 uint8_t data = 0 ;
35 switch ( TW_STATUS ) // TWI-Statusregister pr�fen und n�tige Aktion bestimmen
36 {
37
38 case TW_SR_SLA_ACK : // 0x60 Slave Receiver, wurde adressiert
39 TWCR_ACK ; // n�chstes Datenbyte empfangen, ACK danach
40 buffer_adr = 0 ; // Bufferposition ist undefiniert
41 break ;
42
43 case TW_SR_DATA_ACK : // 0x80 Slave Receiver,Daten empfangen
44 PORTD |= ( 1 << LED0 );
45 data = TWDR ; // Empfangene Daten auslesen
46 rxbuffer [ buffer_adr ] = data ; // Daten in Buffer schreiben
47 buffer_adr ++ ; // Buffer-Adresse weiterz�hlen f�r n�chsten Schreibzugriff
48 if ( buffer_adr < ( buffer_size - 1 )) // im Buffer ist noch Platz f�r mehr als ein Byte
49 {
50 TWCR_ACK ; // n�chstes Datenbyte empfangen, ACK danach, um n�chstes Byte anzufordern
51 }
52 else // es kann nur noch ein Byte kommen, dann ist der Buffer voll
53 {
54 TWCR_NACK ; // letztes Byte lesen, dann NACK, um vollen Buffer zu signaliseren
55 }
56 break ;
57
58 case TW_ST_SLA_ACK : //
59 case TW_ST_DATA_ACK : // 0xB8 Slave Transmitter, weitere Daten wurden angefordert
60 PORTD |= ( 1 << LED1 );
61 TWDR = txbuffer [ buffer_adr ]; // Datenbyte senden
62 buffer_adr ++ ; // bufferadresse f�r n�chstes Byte weiterz�hlen
63 if ( buffer_adr < ( buffer_size - 1 )) // im Buffer ist mehr als ein Byte, das gesendet werden kann
64 {
65 TWCR_ACK ; // n�chstes Byte senden, danach ACK erwarten
66 }
67 else
68 {
69 TWCR_NACK ; // letztes Byte senden, danach NACK erwarten
70 }
71 break ;
72
73 case TW_ST_DATA_NACK : // 0xC0 Keine Daten mehr gefordert
74 case TW_SR_DATA_NACK : // 0x88
75 case TW_ST_LAST_DATA : // 0xC8 Last data byte in TWDR has been transmitted (TWEA = �0�); ACK has been received
76 case TW_SR_STOP : // 0xA0 STOP empfangen
77 default:
78 TWCR_RESET ; // �bertragung beenden, warten bis zur n�chsten Adressierung
79 buffer_adr = 0 ; // Bufferposition ist undefiniert
80 break ;
81 } //end.switch (TW_STATUS)
82 } //end.ISR(TWI_vect)
Der Servo-Teil
1 #include "config.h"
2 #include "servo-lib.h"
3 #include "io.h"
4
5
6 /* SERVOS */
7
8 #ifdef SERVOS
9 uint16_t servo_pulslength [ 20 ];
10
11 void servo_init ( void )
12 { /* initialize servo control (up to 10 servos)
13 */
14
15 uint8_t i ;
16 uint16_t wert ;
17
18 for ( i = 0 ; i < 10 ; i ++ )
19 {
20 wert = MINPULS + ( MAXPULS - MINPULS ) / 256 * 128 ;
21 // calculate hightime
22 servo_pulslength [ i << 1 ] = ( - 1 ) * wert ;
23 // sum of low and hightime for one servo is 2ms
24 servo_pulslength [( i << 1 ) + 1 ] = ( - 1 ) * ( TIMER_MAXPULS - wert );
25 }
26
27 TCNT1 = 0 ;
28 TCCR1A = 0 ;
29 TCCR1B = 0x01 ;
30 #if defined(__AVR_ATmega168__)
31 // Atmega168
32 TIMSK0 |= _BV ( TOIE2 ) | _BV ( TOIE1 );
33 #endif
34 #if defined(__AVR_ATmega8__)
35 // Atmega8
36 TIMSK |= _BV ( TOIE2 ) | _BV ( TOIE1 );
37 #endif
38 }
39
40 void servo_set ( uint8_t ionr , uint8_t value )
41 { /* set servo speed
42 */
43
44 uint16_t wert ;
45 uint8_t index = io_info ( ionr , 2 );
46
47 if ( index != 255 )
48 {
49 wert = MINPULS + ( MAXPULS - MINPULS ) / 256 * value ;
50 // calculate hightime
51 servo_pulslength [ index << 1 ] = ( - 1 ) * wert ;
52 // sum of low and hightime for one servo is 2ms
53 servo_pulslength [( index << 1 ) + 1 ] = ( - 1 ) * ( TIMER_MAXPULS - wert );
54 }
55 }
56
57 ISR ( SIG_OVERFLOW0 )
58 { /* INTERRUPT: timer for software pwm to control servos
59 */
60
61 static uint8_t servo_indexhalf = 0 ;
62
63 switch ( servo_indexhalf )
64 {
65
66 case 0 : set_io ( SERVO0 , 1 ); break ;
67 case 1 : set_io ( SERVO0 , 0 ); break ;
68 case 2 : set_io ( SERVO1 , 1 ); break ;
69 case 3 : set_io ( SERVO1 , 0 ); break ;
70 case 4 : set_io ( SERVO2 , 1 ); break ;
71 case 5 : set_io ( SERVO2 , 0 ); break ;
72 case 6 : set_io ( SERVO3 , 1 ); break ;
73 case 7 : set_io ( SERVO3 , 0 ); break ;
74 case 8 : set_io ( SERVO4 , 1 ); break ;
75 case 9 : set_io ( SERVO4 , 0 ); break ;
76 case 10 : set_io ( SERVO5 , 1 ); break ;
77 case 11 : set_io ( SERVO5 , 0 ); break ;
78
79 }
80 TCNT1 = servo_pulslength [ servo_indexhalf ]; // set time for next interrupt
81
82 servo_indexhalf ++ ;
83 if ( servo_indexhalf == SERVOS * 2 ) servo_indexhalf = 0 ; // VALUE LOWER THAN 20 CAN DAMAGE SERVO!
84
85 }
86 #endif
Der IO-Teil (fuer die Servos gebraucht
1 #include <avr/io.h>
2 #include "config.h"
3 #include "io.h"
4
5 uint8_t io_info ( uint8_t ionr , uint8_t var )
6 { /* returns the requested variable for the pin io_nr;
7 * io_nr: pin
8 * var: 0 <portnumber>
9 * 1 returns number of ADC-port, if it isn't an ADC-port, 255 is returned
10 * 2 returns number of servo, if it isn't a defined servo, 255 is returned
11 */
12
13 switch ( var )
14 {
15 case 0 :
16 switch ( ionr )
17 {
18 case 1 : case 9 : case 12 : return 6 ;
19 case 2 : case 14 : case 23 : return 0 ;
20 case 3 : case 15 : case 24 : return 1 ;
21 case 4 : case 16 : case 25 : return 2 ;
22 case 5 : case 17 : case 26 : return 3 ;
23 case 6 : case 18 : case 27 : return 4 ;
24 case 11 : case 19 : case 28 : return 5 ;
25 case 10 : case 13 : return 7 ;
26 }
27 break ;
28 case 1 :
29 if ( ionr >= 23 && ionr <= 28 )
30 return ionr - 23 ;
31 break ;
32 case 2 :
33 if ( ionr == 255 ) return 255 ;
34 else if ( ionr == SERVO0 ) return 0 ;
35 else if ( ionr == SERVO1 ) return 1 ;
36 else if ( ionr == SERVO2 ) return 2 ;
37 else if ( ionr == SERVO3 ) return 3 ;
38 else if ( ionr == SERVO4 ) return 4 ;
39 else if ( ionr == SERVO5 ) return 5 ;
40 }
41 return 255 ;
42 }
43
44 /*******************************************************************
45 * io_set_
46 *
47 * Wird intern verwendet
48 *******************************************************************/
49 inline void io_set_ ( volatile uint8_t * ddr , volatile uint8_t * port , uint8_t pinnr , uint8_t status )
50 {
51 switch ( status )
52 {
53 case 0 :
54 * ddr |= ( 1 << pinnr );
55 * port &= ~ ( 1 << pinnr );
56 break ;
57 case 1 :
58 default:
59 * ddr |= ( 1 << pinnr );
60 * port |= ( 1 << pinnr );
61 break ;
62 case 2 :
63 * ddr |= ( 1 << pinnr );
64 break ;
65 case 3 :
66 * ddr &= ~ ( 1 << pinnr );
67 * port |= ( 1 << pinnr );
68 break ;
69 case 4 :
70 * ddr &= ~ ( 1 << pinnr );
71 * port &= ~ ( 1 << pinnr );
72 }
73 }
74
75 /*******************************************************************
76 * set_io
77 *
78 * Setzen eines Pins in einen bestimmten Status
79 * status = 0 Ausgang deaktivieren
80 * 1 Ausgang aktivieren
81 * 2 Ausgang
82 * 3 Eingang aktivieren mit internem Pullup
83 * 4 Eingang aktivieren ohne internem Pullup
84 *******************************************************************/
85 void set_io ( uint8_t pin , uint8_t status )
86 {
87 switch ( pin )
88 {
89 case 1 : case 23 : case 24 : case 25 : case 26 : case 27 : case 28 :
90 io_set_ ( & DDRC , & PORTC , io_info ( pin , 0 ), status );
91 break ;
92 case 2 : case 3 : case 4 : case 5 : case 6 : case 11 : case 12 : case 13 :
93 io_set_ ( & DDRD , & PORTD , io_info ( pin , 0 ), status );
94 break ;
95 case 9 : case 10 : case 14 : case 15 : case 16 : case 17 : case 18 : case 19 :
96 io_set_ ( & DDRB , & PORTB , io_info ( pin , 0 ), status );
97 break ;
98 }
99 }
100
101 /*******************************************************************
102 * io_get_
103 *
104 * Wird intern verwendet
105 *******************************************************************/
106 inline uint8_t io_get_ ( volatile uint8_t * pin , uint8_t pinnr )
107 {
108 if ( * pin & ( 1 << pinnr )) return 0 ;
109 return 1 ;
110 }
111
112 /*******************************************************************
113 * get_io
114 *
115 * Auslesen eines Pins
116 * Rueckgabe 0 = low
117 * 1 = high
118 *******************************************************************/
119 uint8_t get_io ( uint8_t pin )
120 {
121 switch ( pin )
122 {
123 case 1 : case 23 : case 24 : case 25 : case 26 : case 27 : case 28 :
124 return io_get_ ( & PINC , io_info ( pin , 0 ));
125 break ;
126 case 2 : case 3 : case 4 : case 5 : case 6 : case 11 : case 12 : case 13 :
127 return io_get_ ( & PIND , io_info ( pin , 0 ));
128 break ;
129 case 9 : case 10 : case 14 : case 15 : case 16 : case 17 : case 18 : case 19 :
130 return io_get_ ( & PINB , io_info ( pin , 0 ));
131 break ;
132 }
133 return 255 ;
134 }
Und weil's so schoen ist, der Config-Teil 1 #define SERVOS 6
2 /* 255 means servo is deactivated, otherwise you've to fill in a port number (every io can be used) */
3 #define SERVO0 14
4 #define SERVO1 15
5 #define SERVO2 16
6 #define SERVO3 17
7 #define SERVO4 18
8 #define SERVO5 19
9
10 /// TWI Slave
11 #define SLAVE_ADRESSE 100
12 #define BOARD_TYPE 0 // Servo
13 #define VERSION_MAJOR 1
14 #define VERSION_MINOR 2
15 #define VERSION_REVISION 3
16 #define TWI_Maxdata 32
Und noch mal Alles zusammen :-)
SG
S. G.
(goeck)
07.06.2012 15:56
#2706858
Hey Stephan,
was war die Lösung, wenn es denn gelöst worden ist, das Problem?
Habe gerade selbiges.
Grüße
Stefan
↑ Nach oben
← Zurück zu Mikrocontroller und Digitale Elektronik
Antwort schreiben
Eine eigene Frage?
Dieser Thread ist über 15 Jahre alt.
Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.
Neuen Thread starten
Eine Lösung, Ergänzung oder Rückmeldung zu diesem Thread? Dann antworte hier.