Forum: Mikrocontroller und Digitale Elektronik Pulspakete mit Timer 0 für C


von Martin G. (halama)


Angehängte Dateien:

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)

von Dirk (Gast)


Lesenswert?

Koenntest du nicht einfach ein Byte seriell über ein I/O Pin 
rausschieben?

Gruß,
Dirk

von Maddin (Gast)


Lesenswert?

Naja, Ziel ist nicht nur einfach einen I/O Pin für 1 u 0 zu toggeln 
sondern gezielt Pakete a la

http://www.mikrocontroller.net/attachment/89/irp-ojojo.jpg

mit einer selbstdefinierten High & Low Länge zu generieren um einen 
eigen Codesequenz zu erstellen.

Grüße  Maddin

von Dirk (Gast)


Lesenswert?

Beitrag "rc5-code senden mit winavr-c"

Der Thread sollte Dir weiterhelfen.

von Maddin (Gast)


Angehängte Dateien:

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");
}

von Maddin (Gast)


Angehängte Dateien:

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

von Maddin (Gast)


Angehängte Dateien:

Lesenswert?

Oh, hab's jetzt hinbekommen die ganze Codesequenz laufen zulassen, aber 
die Totzeit ist immer noch da.....hmmm?!

Anbei ein Bild

Im Code wurden die ganzen "volatile unsigned char" als "uint8_t" 
geschrieben und schon ging die gesamte Sequenz

Maddin

von Dirk (Gast)


Lesenswert?

Ich glaube der Watchdog schlaegt zu. Nimm mal zum testen den Watchdog 
raus.

Dirk

von Maddin (Gast)


Angehängte Dateien:

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

von Maddin (Gast)


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

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.