Forum: Mikrocontroller und Digitale Elektronik Atmega8 Timer stoert TWI


von Stephan K. (dustpuppy)


Lesenswert?

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

von Klempner (Gast)


Lesenswert?

Ja
soll jetzt geraten werden ?

von Alex W. (Gast)


Lesenswert?

Schau Dir den Quellcode nochmals an! In Zeile 42 hast Du misst gebaut!

von Stephan K. (dustpuppy)


Lesenswert?

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

von Stephan K. (dustpuppy)


Angehängte Dateien:

Lesenswert?

Und noch mal Alles zusammen :-)

von S. G. (goeck)


Lesenswert?

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
Noch kein Account? Hier anmelden.