varför funkar inte denna nybörjarloop? (ATMEGA16)

PIC, AVR, Arduino, Raspberry Pi, Basic Stamp, PLC mm.
tokfan
Inlägg: 694
Blev medlem: 10 juni 2010, 14:05:13

varför funkar inte denna nybörjarloop? (ATMEGA16)

Inlägg av tokfan »

Tjena!
Tänkte försöka lära mig programera lite.
Plan A är att sätta mig och latja med 8 dioder och programera olika mönster för att få flyt på loopar mm.

Planen med detta lilla program var att låta en diod i taget blinka från bit 0 till bit 7.
När bit 7 är tänd ska den fortsätta vara det medans dioderna bara blinkar upp till bit 6 nästa runda och behåller den tänd osv.
Hoppas ni fattar. Finns det nåt simplare vis att göra detta mönster på?
Är väldigt tacksam för hjälp.

#include <util/delay.h>
#include <stdint.h>
#define LED_PORT PORTA


int main(void)
{
DDRA = 0xFF;

uint8_t i;
uint8_t j;

while(1)
{

for(j=8; j>0; j--)
{

LED_PORT= (1<<0);
_delay_ms(2000);

for(i= 1; i<j; i++)
{
LED_PORT|= (1<<i);

LED_PORT&= ~(1<< (i-1));
_delay_ms(2000);

}
LED_PORT|= (1<<j);
}
}

return(0);
}
datajompa
Inlägg: 232
Blev medlem: 5 november 2010, 10:35:54

Re: varför funkar inte denna nybörjarloop? (ATMEGA16)

Inlägg av datajompa »

Kan inte testa koden och har ingen ATMEGA så jag kanske är ute och cyklar, men när du AND:ar bort bitar så försvinner ju de tidigare dit-OR:ade bitarna. Jag skulle göra typ så här (otestat):

Edit: Det här var ju helt fel, pinsamt! Se senare inlägg.

Kod: Markera allt

    for(j=7; j>0; j--)
    {
      LED_PORT = 1 << j; /* sätt den högsta biten, som ska vara på ett tag */
      
      for(i= 0; i<j; i++)
      {
        LED_PORT|=1<<i; /* OR:a på en låg bit, som kommer att räknas upp */
        _delay_ms(2000);
      }
    }
Nu vet jag ju inte om man kan läsa från PORTA; om man inte kan det så får man göra så här:

Kod: Markera allt

    uint8_t temp;
    for(j=7; j>0; j--)
    {
      temp = 1 << j; /* sätt den högsta biten, som ska vara på ett tag */
      
      for(i= 0; i<j; i++)
      {
        temp|=1<<i; /* OR:a på en låg bit, som kommer att räknas upp */
        LED_PORT = temp;
        _delay_ms(2000);
      }
    }
Senast redigerad av datajompa 9 januari 2017, 12:27:08, redigerad totalt 1 gång.
mAVRick
Inlägg: 319
Blev medlem: 19 mars 2013, 12:43:43
Ort: Östersund

Re: varför funkar inte denna nybörjarloop? (ATMEGA16)

Inlägg av mAVRick »

Fast LED:arna som 'räknas upp' ska väl, släckas också?

Kod: Markera allt

    uint8_t temp = 0;
    for(j=7; j>0; j--)
    {
      for(i=0; i<=j; i++)
      {
        LED_PORT = temp | (1 << i);
        _delay_ms(2000);
      }
      temp |= (1 << j);
    }
datajompa
Inlägg: 232
Blev medlem: 5 november 2010, 10:35:54

Re: varför funkar inte denna nybörjarloop? (ATMEGA16)

Inlägg av datajompa »

Ja, hjärnprutt!

Edit: ännu mera hjärnprutt! Min "fixade" kod hade ju översta dioden tänd från början! mAVRick läste specen till skillnad från mig...
tokfan
Inlägg: 694
Blev medlem: 10 juni 2010, 14:05:13

Re: varför funkar inte denna nybörjarloop? (ATMEGA16)

Inlägg av tokfan »

Tack för svar!
Jag greppar inte temp grejen.
Vad gör den?
Nerre
Inlägg: 26655
Blev medlem: 19 maj 2008, 07:51:04
Ort: Upplands väsby

Re: varför funkar inte denna nybörjarloop? (ATMEGA16)

Inlägg av Nerre »

Den lagrar tillfälligt den gamla "bilden". Jag tror det handlar om att du kan inte ha porten (LED_PORT) både som destination och källa i samma operation, den får bara finnas på ena sidan av likhetstecknet.
datajompa
Inlägg: 232
Blev medlem: 5 november 2010, 10:35:54

Re: varför funkar inte denna nybörjarloop? (ATMEGA16)

Inlägg av datajompa »

På vissa äldre mikrokontrollanter går det inte alltid att läsa från en port bara för att det går att skriva till den. Jag har ingen koll på ATMEGA16 och orkade inte läsa databladet.

Temp-variabeln är då bara för att ha ett temporärt värde att laborera med innan man skriver det till registret som styr portarna med LED.
datajompa
Inlägg: 232
Blev medlem: 5 november 2010, 10:35:54

Re: varför funkar inte denna nybörjarloop? (ATMEGA16)

Inlägg av datajompa »

För att svara på ursprungsfrågan om varför det inte funkar så misstänker jag att problemet är att du räknar fel på shiftarna.

1<<8 blir ju 256 och alltså alla bitarna 0 på en 8-bitarsport. Här antar jag alltså en massa saker som att ATMEGA16 har 8-bitarsportar och att du har kopplat in 8 lysdioder på pinnarna 0 tom 7.

I övrigt tyckte jag att det verkade vara ett lite omständigt sätt att göra det hela på med att AND-maska med ett inverterat värde.

För logiska grindar kan man ju se OR som "plus", så

Kod: Markera allt

(1<<j) | (1<<i)
blir ju då högsta LED:en + den räknande LED:en.

Du skrev bara att det inte funkar, hur yttrar det sig; vad händer med lysdioderna? Funkar våra förslag?
datajompa
Inlägg: 232
Blev medlem: 5 november 2010, 10:35:54

Re: varför funkar inte denna nybörjarloop? (ATMEGA16)

Inlägg av datajompa »

Några kommentarer. Jag räknar bitarna som att bit nr 0 är lägsta biten.

Kod: Markera allt

  for(j=8; j>0; j--)
  {
    LED_PORT= (1<<0); // här sätts LED_PORT till 00000001, varje gång
    _delay_ms(2000);

    for(i= 1; i<j; i++)
    {
      LED_PORT|= (1<<i); // bit 1 tom 7 kommer att sättas

      LED_PORT&= ~(1<< (i-1)); // bit 0 tom 6 kommer att nollas
      _delay_ms(2000);

    }
    LED_PORT|= (1<<j); // bit 8 (finns ej?) ned till 1 kommer att sättas men sedan släckas direkt när det loopar (innan man hinner se den tändas)
  }
tokfan
Inlägg: 694
Blev medlem: 10 juni 2010, 14:05:13

Re: varför funkar inte denna nybörjarloop? (ATMEGA16)

Inlägg av tokfan »

Den här funkar kanon!
Jag klurar nu på var i koden "i" bitarna nollas så att inte alla fortsätter vara tända när de räknar upp?
mAVRick skrev:Fast LED:arna som 'räknas upp' ska väl, släckas också?

Kod: Markera allt

    uint8_t temp = 0;
    for(j=7; j>0; j--)
    {
      for(i=0; i<=j; i++)
      {
        LED_PORT = temp | (1 << i);
        _delay_ms(2000);
      }
      temp |= (1 << j);
    }
datajompa
Inlägg: 232
Blev medlem: 5 november 2010, 10:35:54

Re: varför funkar inte denna nybörjarloop? (ATMEGA16)

Inlägg av datajompa »

Bitarna "nollas" alltså genom att hela värdet hos LED_PORT skrivs över med ett nytt värde.

temp kommer att gå igenom följande värden: 10000000, 11000000, 11100000, 11110000, 11111000, 11111100, 11111110, reperera. Detta på grund av följande rad:
temp|=(1<<j)

LED_PORT sätts dock så här:
LED_PORT = temp | (1 << i)

Så (1 << i) kommer att "adderas" till LED_PORT, tillsammans med temp, vid varje uppdatering av LED_PORT, men (1 << i) kommer inte att "adderas till"/"sparas i" temp.
Mr Andersson
Inlägg: 1394
Blev medlem: 29 januari 2011, 21:06:30
Ort: Lapplandet

Re: varför funkar inte denna nybörjarloop? (ATMEGA16)

Inlägg av Mr Andersson »

Ett tips om du vill se hur logiken fungerar är att köra den i en debugger och stega genom koden rad för rad. Om du inte har en hårdvarudebugger går det lika bra att köra på valfri PC istället. Ersätt bara port-variabeln med en uint8_t.
tokfan
Inlägg: 694
Blev medlem: 10 juni 2010, 14:05:13

Re: varför funkar inte denna nybörjarloop? (ATMEGA16)

Inlägg av tokfan »

datajompa skrev:Bitarna "nollas" alltså genom att hela värdet hos LED_PORT skrivs över med ett nytt värde.

temp kommer att gå igenom följande värden: 10000000, 11000000, 11100000, 11110000, 11111000, 11111100, 11111110, reperera. Detta på grund av följande rad:
temp|=(1<<j)

LED_PORT sätts dock så här:
LED_PORT = temp | (1 << i)

Så (1 << i) kommer att "adderas" till LED_PORT, tillsammans med temp, vid varje uppdatering av LED_PORT, men (1 << i) kommer inte att "adderas till"/"sparas i" temp.
Ruggigt bra förklaring!
Du borde jobba som lärare om du inte redan gör det. Sjukt pedagogiskt!
Jag tror Poletten föll ner nu efter att ha kollat på koden samtidigt som ditt inlägg i en kvart ;)
Fy fasen va skönt!
Nu har jag kommit ett steg framåt igen.
Mr Andersson skrev:Ett tips om du vill se hur logiken fungerar är att köra den i en debugger och stega genom koden rad för rad. Om du inte har en hårdvarudebugger går det lika bra att köra på valfri PC istället. Ersätt bara port-variabeln med en uint8_t.
Bra plan!
Har avr dragon. Krånglade med att koppla in via jtag med massa lösa sladdar när jag skulle komma igång. Funkade aldrig så jag testade isp istället. Insåg då att dragon kortet inte matade atmegan med spänning. Fixade det men har inte testat jtag igen. Får ta tag i det nu.

Tusen tack för hjälpen allihopa!
Sparade mycket tid. Har inte många timmar i veckan till denna nya hobby.
Skriv svar