Pulspakete mit Timer 0 für C

OP #426163
Lesenswert?
• ▲
▼
Hallo zusammen,

versuche auf einem Atmega 128 eine variable Pulspaketbreite für eine 
eigene, definierte Codesequenz zu einem TSOP-Baustein im Polling zu 
erstellen.

Erste Versuche mit 2 Timern führten zu einem gegenseitigen stören beider 
eingesetzten ISRs mit CTC oder Overflow Routinen.

Nun habe ich einen einfachen C-Code für den Timer 0 geschrieben der 
allerdings noch im Timing und der Ausführung von Low un High 
"zickt"...*grübel*

Hat jemand eine Idee wo drann es liegt bzw. gibt es eine noch einfachere 
Alternative solche Burst-Pakete mit der Nutzung von möglichst wenig 
Systemresourcen herzustellen?!

Anbei der Code (Bild siehe Anhang):
------------------------------------------------------------------
#include <stdlib.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/signal.h>

volatile unsigned char code [6] = {1,200,100,300,100,400,100000}; 
//Array with 7 Values
volatile unsigned char compare = 0;                  //Counter for Array 
place
volatile unsigned char set= 0;                  //Setting high or Low 
Phase
volatile unsigned char i= 0;                  //Counter for Compare to 
array value

int boot_periphericals()          // I/O and basic settings
{
  SREG |= (1<<SREG_I);            // Global Interrupts aktivieren
}


void boot_timer0 ()              // Timer 0 (8Bit)
{
  DDRA  = 0xFF;               // PA0, PA1, PA2  selected as output
  PORTA = 0x00;               // PA0, PA1, PA2  outputs on low (0)
  TCNT0 = 0x00;                // Timer Start value
  OCR0  = 255;                // Timer CTC value (0-255)
  TIMSK |=(1<<OCIE0);                    // Timer 0 CTC Match Interrupt 
enable
}

void boot_watchdog()            // Watchdog for reseting in case of 
global corruption
{
  WDTCR  |= (1<<WDE);            // Enable Watchdog with Timeout after 
14.0 ms (Datasheet page 56)
}

//---------------------------------------------------------------------- 
----------------
int main (void)
{
  boot_periphericals();
  boot_timer0();                  // Loading Timer 0 settings
  boot_watchdog();                // Loading Watchdog settings
  while(1)
  {
  i++;
    if(i==code[compare])
    {
      if (set ==0)
      {
        TCCR0 |=(1<<WGM01)|(1<<CS00);      // Timer 1 on CTC Mode, MCU 
clockspeed
        compare++;
        i=0;
        set=1;
          if(compare ==6)
          compare=0;
      }
      else
      {
         TCCR0 = 0x00;              // Timer 0 off
         PORTA = 0x00;
         compare++;
         i=0;
         set=0;
          if(compare ==6)
          compare=0;
      }
    }
  }
  return 0;
}

//---------------------------------------------------------------------- 
----------------

ISR (SIG_OUTPUT_COMPARE0)         //Interrupt Handling Routine 
/(automat. Aufruf vom Timer)
{
  PORTA =~ PORTA;            // invert PORTA
}


//delay_us(13)
Angehängte Dateien:
Gast #426428
Lesenswert?
• ▲
▼
Hallo Dirk,

vielen Dank für den Link, hab' ich mir angeschaut und ein Programm in 
ähnlichem Stile erstellt.Ich bekomme meinen generierten Code und meine 
Anfangs- und Endsignale, allerdings noch zusätzlich eine Totzeit die ich 
mir nicht erkären kann  (siehe Bild blauer Abschnitt)....!?
Woher kommt das bzw. wie kann ich dies unterdrücken/entfernen?

Abgesehen davon habe ich eine generelle Frage. Gibt es nicht die 
Möglichkeit so eine Sequenz über Timer oder ähnliches ablaufen zu 
lassen, damit die Main für andere Aufgaben frei bleibt.
 Denn im Moment brauche ich ja einen ganzen Proz nur für's senden.

Ich wollte eigentlich von einem Proz, dass Senden und Empfangen 
gleichzeitig steuern und die Bitkombi vergleichen.

Vielen dank im Vorraus

Grüße Maddin

Anbei das Programm:
------------------------------------------
#include <inttypes.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <stdio.h>
#include <avr/signal.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include <avr/io.h>

//---------------------------------------------------------------------- 
--------------------
// Variablen Declaration
//---------------------------------------------------------------------- 
--------------------
#define pulses_amount (uint8_t)(20)                  //Enter here amount 
of pulses per high cycle
#define cycle_ratio (uint8_t)(9)                  //Enter here Half 
dutycycle for Freq

#define IR_PORT  PORTA
#define IR_PIN   PA0
#define IR_ON  IR_PORT |=  (1<<IR_PIN)
#define IR_OFF IR_PORT &= ~(1<<IR_PIN)

//volatile unsigned char code [6] = 
{100000,65535,100000,65535,100000,655350};   //Array with 7 Values
//volatile unsigned int compare = 0;                    //Counter for 
Array place
uint8_t i=0,set=0;                              // integer value I with 
32 bit declared
uint16_t a=0,b=0,x=0,y=0,z=0;

//---------------------------------------------------------------------- 
--------------------
// Prototypen Declaration
//---------------------------------------------------------------------- 
--------------------
void boot_periphericals ();
void boot_watchdog();
void set_high();
void set_low();
void initbit();
void endpeak();
void bit0();
void bit1();
void freq_toggle();

//---------------------------------------------------------------------- 
--------------------
// Main- Function
//---------------------------------------------------------------------- 
--------------------
void main ()
{
  boot_periphericals();
  boot_watchdog();                // Loading Watchdog settings
  while (1)
  {
      initbit();
    bit1();
    bit0();
    bit0();
    bit1();
    bit1();
    endpeak();
  }
}

//---------------------------------------------------------------------- 
--------------------
// Subfunctions
//---------------------------------------------------------------------- 
--------------------
void boot_periphericals ()          // I/O and basic settings
{
  DDRA  = 0x01;               // PA0, selected as output
  PORTA = 0x00;               // PA0, outputs on low (0)
}

void boot_watchdog()            // Watchdog for reseting in case of 
global corruption
{
  WDTCR  |= (1<<WDE);            // Enable Watchdog with Timeout after 
14.0 ms (Datasheet page 56)
}

void initbit()
{
  set_low();
  set_low();
  set_low();
  set_high();
  set_high();
  set_high();
  set_low();
  set_low();
  set_low();
}

void endpeak()
{
IR_ON;
  for (b=0; b<1; b++)
      asm volatile("nop");
  IR_OFF;
  for (b=0; b<1; b++)
      asm volatile("nop");
}


void bit0()
{
  set_low();
  set_high();
}

void bit1()
{
  set_high();
  set_low();
}

void set_high()
{
 for(a=0; a<pulses_amount; a++)
  {
  freq_toggle();
  }
}

void set_low()
{
  IR_OFF;
  for (x=0; x<30; x++)
     {
    for (y=0; y<18; y++)
        asm volatile("nop");
  }
}

void freq_toggle ()
{
  IR_ON;
  for (b=0; b<cycle_ratio; b++)
      asm volatile("nop");
  IR_OFF;
  for (b=0; b<cycle_ratio; b++)
      asm volatile("nop");
}
Angehängte Dateien:
Gast #426472
Lesenswert?
• ▲
▼
Hallo,

ich habe mal die Bitfolge im main verlängert und dabei festgestllt, dass 
der MCU die hälfte meiner Bits gar nicht mehr bearbeitet und zusätzlich 
immer noch die Totzeit bringt.

Bin echt am verzweifeln... hat da jemand ne Ahnung?

Bitfolge in der Main Vorgabe :
bit1();  bit0();  bit0();  bit1();  bit1();  bit0();  bit1();  bit0(); 
bit1();bit1()

Grüße Maddin
Angehängte Dateien:
Gast #426568
Lesenswert?
• ▲
▼
Die Codesequenz bricht nach 11 Stellen (von 20 ) nun doch wieder ab...

Hat jemand eine Idee....??

Mittlerweile ist der Sendecode in einem Array und wird im über die main 
schrittweise eingelesen und in Sendebits umgewandelt:

volatile unsigned char code [19] = 
{0,1,1,1,0,1,1,0,0,0,0,1,0,0,0,1,0,0,0,0};

Vielen Dank im Vorraus
Angehängte Dateien:
Gast #426577
Lesenswert?
• ▲
▼
Ah yeah...vielen Dank für den Hinweise Dirk.

Es war der Watchdog...

Aber abweichend nochmal die Frage ob man das nicht auch anders machen 
kann als einen Proz nur mit dem Senden über die Main auszulasten.
Denn dann müsste ich ja einen ATTini dafür abstellen und meinen ATmega 
mit dem Dekodieren des Empfangssignal "beauftragen".

Gruss Maddin

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren