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
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
|
Hey Stephan, was war die Lösung, wenn es denn gelöst worden ist, das Problem? Habe gerade selbiges. Grüße Stefan
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.