"För alltid" är en liten överdrift. Den kan inte fixas via ISP utan man måste
ha en högvolts parallell programmerare. Man har man inte det så är det
kanske "för alltid"...

Kod: Markera allt
//---------------- standardbibliotek ------------------
// #define F_CPU 8000000 för att använda intern 8 MHz osilator, men använder utomstående 16MHz
#include <avr/io.h>
#include <util/delay.h>
#include <util/delay_basic.h>
#define CLOCK (1<<PB1)
#define ROW PORTF
#define RED PORTA
#define GREEN PORTC
#define BLUE PORTD
char ROWNR;
char x = 1;
char xway = 1;
char y = 1;
char yway = 1;
void skicka_data(char red, char green, char blue) { // SKRIV ALGORITM HÄR
if (ROWNR != 0){ //Kan användas vid vissa mönster, om man t.ex. vill stega i raderna med en repetitionssats. Då bestämmer man ROWNR innan man skickar färgerna.
if(ROWNR == 1){
ROW = 0b00100000;
}
if(ROWNR == 2){
ROW = 0b00010000;
}
if(ROWNR == 3){
ROW = 0b00001000;
}
if(ROWNR == 4){
ROW = 0b00000100;
}
if(ROWNR == 5){
ROW = 0b00000010;
}
if(ROWNR == 6){
ROW = 0b00000001;
}
ROWNR = 0;
}
RED = red; //Röda portarna tilldelas
GREEN = green; //Gröna portarna tilldelas
BLUE = blue; //Blåa portarna tilldelas
}
/**** huvudprogrammet ****/
int main(void) {
// initiering av portar (se kapitel 12 i databladet - särskilt 12.2.1)
DDRF = 0b00000000; // alla pinnar på port F ska vara utgångar rad
DDRA = 0b11111111; // alla pinnar på port A ska vara utgångar röd
DDRC = 0b11111111; // alla pinnar på port C ska vara utgångar grön
DDRD = 0b11111111; // alla pinnar på port D ska vara utgångar blå
PORTF = 0b11111111; //aktiverar alla rader
while(1) { // ...loopa för evigt...
ROW = 0b00111111; //Ställer in vilka rader som ska aktiveras
skicka_data(0b11111111, 0b00000000, 0b00000000 );// red, green, blue //Skickar data om vilka kolumner (3x8, tre färger) som ska aktiveras
}
Kod: Markera allt
if(ROWNR == 1){
ROW = 0b00100000;
}
if(ROWNR == 2){
ROW = 0b00010000;
... osv...
Kod: Markera allt
ROW = (1<<(6-ROW));
Kod: Markera allt
for(int i = 1; i < 7; i++){ //En prick som går pixel för pixel, rad 1 sedan 2 osv...
ROWNR = i;
skicka_data(0b00000001, 0b00000000, 0b00000001 );// red, green, blue
_delay_ms(400);
skicka_data(0b00000010, 0b00000000, 0b00000010 );// red, green, blue
_delay_ms(400);
skicka_data(0b00000100, 0b00000000, 0b00000100 );// red, green, blue
_delay_ms(400);
skicka_data(0b00001000, 0b00000000, 0b00001000 );// red, green, blue
_delay_ms(400);
skicka_data(0b00010000, 0b00000000, 0b00010000 );// red, green, blue
_delay_ms(400);
skicka_data(0b00100000, 0b00000000, 0b00100000 );// red, green, blue
_delay_ms(400);
skicka_data(0b01000000, 0b00000000, 0b01000000 );// red, green, blue
_delay_ms(400);
skicka_data(0b10000000, 0b00000000, 0b10000000 );// red, green, blue
_delay_ms(400);
}
Kod: Markera allt
for(int i = 1; i < 7; i++){ //En prick som går pixel för pixel, rad 1 sedan 2 osv...
ROWNR = i;
uint8_t red=0b00000001;
uint8_t green=0b00000000;
uint8_t blue=0b00000001;
for (int j=0; j<8; j++) {
skicka_data(red, green, blue );// red, green, blue
red = (red << 1);
green = (green << 1);
blue = (blue << 1);
_delay_ms(400);
}
}
Kod: Markera allt
dimma_rad(uint8_r rader, uint dimm) {
RAD = rader;
_delay_us(dimm); // dimm värde mellan 0 och 999
RAD = 0;
_delay_us(1000-dimm);
}
B:Skicka array (=fält) som argument i en funktion:
man brukar inte göra så att man anger alla variabler i fältet en och en i funktionsanropet, utan man skickar bara arrayens namn, så kan du använda den i funktionen sedan. Om du inte redan har en bok om C-programmering bör du skaffa en. Jag har en bra bok hemma som heter "Vägen till C" av Ulf Bitling och Jan Skansholm. Den innehåller bra förklaringar på sådana här saker. Kolla om du kan låna den på biblioteket.
exempel:Men nu är det speciellt med just microcontrollers att de har olika minnen för program (=flashminne) och för data (RAM-minne) , och de brukar inte ha så mycket RAM-minne. Därför behöver man ofta spara på utrymmet i RAM (Alla variabler ligger i RAM-minnet). Du får du inte plats med så många mönster i minnet om du ska lagra allt i varabler). Därför brukar man lagra data som är statisk (= behöver aldrig ändras) i flashminnet. Där finns gott om utrymme, vanligtvis.Kod: Markera allt
// definierar ett fält med 100 st (nr 0-99) 8-bitars positiva heltal uint8_t monster[100] = { 3,8,7,4,4,23,65,67,4,23,2,1,45,7,7 .......... }; // (mönster) ... längre ner i koden... skicka_data(monster); // "monster" pekar nu på den första av de 100 heltalen ... funktionen: void skicka_data(uint8_t data[]) { uint8_t a; a = data[0]; // läs av data från fält }
Då måste man göra på ett annat vis:ovanstående exempel kan du nästan sätta in direkt i ditt program bara för att testa hur det fungerar att läsa data från programminnet. I det här fallet är den tvådimensionella arrayen en global variabel och de två dimensionerna är (1) vilket mönster (2) siffrorna i mönstret.Kod: Markera allt
#include <avr/io.h> #include <avr/pgmspace.h> // definierar tre mönster med 10 heltal i varje... siffrorna lagras i programminnet (PROGMEM) uint8_t PROGMEM monster[3,10] = { { 0,1,2,3,4,5,6,7,8,9 } , // mönster nr 0 { 4,7,8,3,2,9,8,7,0,1,6 } , // mönster nr 1 { 0,1,2,7,4,5,6,3,8,9 } // mönster nr 2 }; int main() { visa_monster(2); // visa mönster nummer två visa_monster(1); // visa mönster nummer ett } void visa_monster(int nummer) { for (i=0; i<10; i++) { // loopa igenom alla element i mönstret // läs data från programminnet och skicka ut till PORTB: PORTB = pgm_read_byte(monster[nummer,i]); _delay_ms(400); } }
C:Dimning:
Det kan vara väldigt svårt att kunna dimma varje LED för sig. Det kan vara enklare till en början om du försöker dimma hela mönstret. Har du räknat på hur fort det måste gå om varje lysdiod ska dimmas för sig och om det är möjligt? Du tänder ju inte lysdioderna en och en (då blir det lite mycket ljus), utan du tänder en rad åt gången. Om du då ska dimma enskilda lysdioder får du först tända alla dioder i raden för att sedan släcka dem med olika tidsfördröjning. Ganska avancerat!
Ett annat problem med att du bestämmer i själva mönstret hur mycket en diod ska lysa är att då måste du sedan multiplicera den ljusnivån för varje diod med den globala dimningsnivån. För tanken är väl att du ska kunna dimma ett helt mönster från mörkt till ljust och sedan mörkt igen?
Så för enkelhetens skull borde du inte ha med siffror om dimning för varje enskild diod i dina data (det får i så fall bli en specialöverkurs sen när allt annat fungerar)
D:Fundera på hur data är organiserat.
Det finns tre saker att tänka på när man bestämmer hur data ska lagras:
1) effektivitet: är det enkelt att få fram den "rådata" som behövs för att kunna visa mönstret, eller krävs det matematiska beräkningar eller krånglig omsortering av data för det? Försök få datan i din array att likna så mycket som möjligt den utdata du ska skicka, och att data kommer i den ordning som den ska användas.
2) begriplighet / lätthet att skapa mönstren: organisera data så att du kan förstå vad innehållet betyder. (det verkar vara denna punkt du har
3) Minnesutrymme: försök packa data om det inte blir för krångligt, för att spara minnesutrymme. T.ex. istället för att ha åtta 16-bitars heltal som innehåller en bit var, så använd ett 8-bitars heltal som innehåller alla åtta bitarna. Exempel:Punkt (1) är nog det viktigaste här - annars kan man köra fast helt sen när man ska försöka skriva rutinen som visar mönstret.Kod: Markera allt
int array [3,10] { {0,0,0,0,1,0,1,0}, {1,0,0,0,1,0,0,1}, {0,0,1,1,0,1,0,0} ; // inte smart! uint8_t array[3] = {0b00001010,0b10001001,0b00110100} // smart!
Punkt (3) kanske inte är lika viktig om du har gott om programminne över. Men det är bra att tänka på om man vill kunna utöka programmet/antal mönster senare.
Punkt (2) kanske man inte alltid kan göra så mycket åt eftersom man måste kompromissa med de andra punkterna.
Så innan du bestämmer hur du ska lagra din data får du försöka tänka igenom om din "visa_mönster"-rutin verkligen kan hantera siffrorna i den ordning de kommer. Gör gärna ett flödesschema på visa-mönster-rutinen så du har koll på exakt vad du ska göra.
PS: decimaltal skrivs med decimalpunkt, inte med komma. Och argumenten i ett funktionsanrop separeras med komma, inte med semikolon, därför skulle ditt exempel skicka_data(100 ; 1,2 ; 2,4 ; X,X ; X,X ; X,X ; X,X ; X,X ; X,X egentligen skrivas som skicka_data(100 , 1.2 , 2.4 , X.X, X.X , X.X ..., men nu ska man ju inte använda decimaltal. Om du använder flera heltal istället blir det skicka_data(100 , 1,2 , 2,4 , X,X , X,X , X,X , X,X , X,X , X,X men det är inte bra med så många argument till en funktion!ALDRIG, ALDRIG använda decimaltal i sådana här sammanhang (och helst aldrig annars heller). Använd heltal! Hellre flera heltal än ett decimaltal!