Cos'è ElectroYou | Login Iscriviti

ElectroYou - la comunità dei professionisti del mondo elettrico

Ordinamento di 10 valori atmega 8535

Raccolta di codici sorgenti

Moderatore: Foto UtentePaolino

0
voti

[1] Ordinamento di 10 valori atmega 8535

Messaggioda Foto Utentepeppe1992 » 29 mag 2018, 14:23

Salve a tutti, sto cercando di fare un esercizio che legge dalle porte A e B dell'8535 10 valori con una frequenza di campionamento di circa 15Hz, deve poi ordinare questi 10 valori in modo crescente e darli in uscita alle porte C e D sempre con una frequenza di circa 15 Hz.
Per la lettura dei valori dall'esterno non ho avuto alcun problema, ho utilizzato l'overflow del timer0 per la lettura. Per quanto riguarda l'immagazzinamento dei valori ho provato in due differenti modi.
Il primo che ho utilizzato fa uso dello stack, quindi attraverso push immagazzino i 10 valori, ma poi ho avuto difficoltà con l'ordinamento.
Il secondo metodo che ho utilizzato va a memorizzare direttamente nella ram i valori utilizzando l'istruzione "st", ma anche in questo caso ho problemi nell'implementare l'ordinamento.
Studiando il C ho fatto diversi algoritmi di ordinamento, ma in assembly non riesco ad implementarlo facilmente, vorrei qualche consiglio su come fare a risolvere questo problema e vorrei sapere quale dei due metodi secondo voi è più appropriato.

Grazie in anticipo :ok:
Avatar utente
Foto Utentepeppe1992
45 1 4
New entry
New entry
 
Messaggi: 64
Iscritto il: 17 mag 2011, 22:54

3
voti

[2] Re: Ordinamento di 10 valori atmega 8535

Messaggioda Foto Utentexyz » 29 mag 2018, 15:15

Io userei un semplice buffer di 10 elementi e quando pieno utilizzerei un semplice algoritmo di riordino senza l'utilizzo di una copia (in place), del tipo insertion sort o equivalente.

Sicuramente non userei una struttura dati di tipo stack, per ovvi motivi.

Gli algoritmi sono indipendenti dal linguaggio di programmazione utilizzato, l'importante è saper programmare nel linguaggio di programmazione scelto per implementare l'algoritmo.
Avatar utente
Foto Utentexyz
5.195 2 4 5
Master EY
Master EY
 
Messaggi: 1366
Iscritto il: 5 dic 2009, 18:37
Località: Italy Turin

0
voti

[3] Re: Ordinamento di 10 valori atmega 8535

Messaggioda Foto Utentepeppe1992 » 29 mag 2018, 15:55

xyz ha scritto:Io userei un semplice buffer di 10 elementi e quando pieno utilizzerei un semplice algoritmo di riordino senza l'utilizzo di una copia (in place), del tipo insertion sort o equivalente.


Non ho capito bene cosa intendi per buffer di 10 elementi, potresti farmi un esempio anche in pseudocodice?
Avatar utente
Foto Utentepeppe1992
45 1 4
New entry
New entry
 
Messaggi: 64
Iscritto il: 17 mag 2011, 22:54

2
voti

[4] Re: Ordinamento di 10 valori atmega 8535

Messaggioda Foto Utentexyz » 29 mag 2018, 17:17

E' una zona di memoria che contiene 10 elementi contigui, per accedere si una un indice che va da 0 a 9 che si somma all'indirizzo base zona di memoria per ottenere l'indirizzo della cella su cui si vuole scrivere o leggere. In altre parole è un array di 10 elementi :D

In pseudocodice dipende dalla notazione del pseudocodice, faccio prima in C (ogni elemento è un intero non segnato di 8 bit):

Codice: Seleziona tutto
uint8_t buffer[10];


o assembler per il portable GNU assembler:

Codice: Seleziona tutto
.comm   buffer,10,1
Avatar utente
Foto Utentexyz
5.195 2 4 5
Master EY
Master EY
 
Messaggi: 1366
Iscritto il: 5 dic 2009, 18:37
Località: Italy Turin

0
voti

[5] Re: Ordinamento di 10 valori atmega 8535

Messaggioda Foto Utentepeppe1992 » 29 mag 2018, 17:31

Quindi praticamente per l'8535 potrei per esempio scrivere:
.dseg
.org 0x60

vett: .byte 10
in questo modo vado ad allocare 10 byte contigui per esempio a partire da 0x60
Avatar utente
Foto Utentepeppe1992
45 1 4
New entry
New entry
 
Messaggi: 64
Iscritto il: 17 mag 2011, 22:54

1
voti

[6] Re: Ordinamento di 10 valori atmega 8535

Messaggioda Foto Utentexyz » 29 mag 2018, 18:24

Si da quello che hai scritto, dipende dalle direttive dell'assembler utilizzato (io uso l'assembler delle GNU binutils), crei un array di 10 byte all'indirizzo "vett", nel tuo caso parte all'indirizzo 0x60 (allineamento al byte).
Avatar utente
Foto Utentexyz
5.195 2 4 5
Master EY
Master EY
 
Messaggi: 1366
Iscritto il: 5 dic 2009, 18:37
Località: Italy Turin

0
voti

[7] Re: Ordinamento di 10 valori atmega 8535

Messaggioda Foto Utentepeppe1992 » 30 mag 2018, 16:33

Grazie tante. Prima di fare quel programma sto cercando di ordinare 5 elementi qualsiasi inseriti da me, solo che mi blocco e non so come continuare. Potresti darmi una mano gentilmente? Posto il codice che ho scritto e spero potrai darmi una mano.
Codice: Seleziona tutto
.include "8535def.inc"
;================================================


;==============
;definizione delle variabili. La Memoria Ram
; inizia dall'indirizzo esadecimale 60

.DSEG
.ORG 0x60

vett: .byte 5

;=============

;=================================================
;Interrupt jump table;
;questa sezione di codice deve essere
;caricata in memoria programma a partire dall'indirizzo $000

.CSEG
.ORG 0x000
   rjmp   RESET      ;Reset        Handle $000
   reti         ;INT0         Handle $001
   reti         ;INT1         Handle $002
   reti         ;TIMER2 COMP  Handle $003
   reti         ;TIMER2 OVF   Handle $004
   reti         ;TIMER1 CAPT  Handle $005
   reti         ;TIMER1 COMPA Handle $006
   reti         ;TIMER1 COMPB Handle $007
   reti         ;TIMER1 OVF   Handle $008
   reti         ;TIMER0 OVF   Handle $009
   reti         ;SPI STC      Handle $00A
   reti         ;UART RX      Handle $00B
   reti         ;UART UDRE    Handle $00C
   reti         ;UART TX      Handle $00D
   reti         ;ADC         Handle $00E
   reti         ;EE_RDY       Handle $00F
   reti         ;ANA_COMP     Handle $010
;==========================================================
;
;   
; Here main program starts

RESET:
;===========================
; la prima operazione da compiere in ogni caso e'
; l'inizializzazione dello Stack pointer

;Setting Stack Pointer

   ldi r16, low(RAMEND)
   out SPL, r16
   ldi r16, high(RAMEND)
   out SPH, r16
; done
;===========================



;========Inizio programma principale================

ldi r26, low(vett)
mov r0, r26 ; salvo per precauzione r26
ldi r21, 5
ldi r22, 7
ldi r23, 3
ldi r24, 0
ldi r25, 1

sts vett, r21
sts vett+1, r22
sts vett+2, r23
sts vett+3, r24
sts vett+4, r25


ldi r18, 5
ld r16, x+

compara:
dec r18
breq salva_minore
ld r17, x+
cp r17, r16
brlo scambia ; in modo tale che r16 contenga il valore attuale di r17
rjmp compara

scambia:
mov r19, r17
mov r17, r16
mov r16, r19
rjmp compara

salva_minore:
push r16

rjmp compara




Spiegazione:
1)Alloco 5 byte all'indirizzo 0x60
2)Carico in r26 (che sarebbe la parte bassa del registro X) la parte bassa dell'indirizzo dell'etichetta vett.
So che dovrei caricare anche la parte alta ma in questo caso so di aver messo l'etichetta all'indirizzo 0x60 quindi la parte alta è nulla.
3)Carico quei valori nei registri attraverso ldi
4) copio i dati dai registri ai 5 byte allocati, quindi riempo il vettore
5) Carico il valore 5 in un registro che andrò a decrementare ogni volta che faccio la comparazione
6)Carico in R16 il valore contenuto nel primo byte allocato quindi vett[0]
7) (Dentro l'etichetta compara) carico in R17, vett[1] e lo confronto con vett[0], se vett[1] è più piccolo
scambio R16 con R17 in modo tale che in R16 ci sia il valore più piccolo, altrimenti salto nuovamente all'etichetta compara, leggo vett[2] e faccio il confronto con vett[0].

Questa procedura mi dovrebbe portare a trovare il valore più piccolo, il problema è che il passaggio successivo che dovrei fare è trovare il valore più piccolo fra i rimanenti ma senza includere questo, quindi in qualche modo dovrei estrarre questo valore e fare in modo che la ricerca avvenga per tutti i valori tranne che per questo.
Non so se sono stato abbastanza chiaro. Sicuramente il mio codice non sarà perfetto e potrà essere fatto in modo molto più semplice. Potrei avere una mano?
Grazie per la disponibilità e la pazienza. O_/ O_/
Avatar utente
Foto Utentepeppe1992
45 1 4
New entry
New entry
 
Messaggi: 64
Iscritto il: 17 mag 2011, 22:54

1
voti

[8] Re: Ordinamento di 10 valori atmega 8535

Messaggioda Foto Utentexyz » 30 mag 2018, 17:15

Uno dei più semplici algoritmi di riordino è insertion sort, la sua implementazione è molto semplice si basa su 2 loop annidati, il primo loop seleziona l'elemento da confrontare il secondo loop lo scambia se necessario con gli altri elementi.

La rete è piena di codice che lo implementano nei vari linguaggi, ad esempio in C:

https://it.wikiversity.org/wiki/Ordinam ... odice_in_C

devi solo traslarlo in assembler per gli AVR, stando molto attento ai registri utilizzati come indice e ai loro limiti.
Avatar utente
Foto Utentexyz
5.195 2 4 5
Master EY
Master EY
 
Messaggi: 1366
Iscritto il: 5 dic 2009, 18:37
Località: Italy Turin

0
voti

[9] Re: Ordinamento di 10 valori atmega 8535

Messaggioda Foto Utentepeppe1992 » 31 mag 2018, 11:14

Ho provato a traslarlo dal codice C che utilizzo solitamente ad assembly avr, ma con scarsi risultati.

In C solitamente faccio:
Codice: Seleziona tutto
insertion_sort(int v[], int dim)
{
int i, j, elem;
    for(i=1; i<dim; i++)
    {
    elem = v[i];
          for(j=i-1; (j>=0) && (elem<v[j]; j--)
          {
          v[j+1] = v[j]
          }
     v[j+1] = elem;
     }
}

}




il codice assembly avr che ho scritto, ma sicuramente con tanti errori che non riesco a risolvere è quello sotto.
Ho dato dei nomi più semplici ai registri, per esempio:
R17 = i
R18 = dim
R16 = elem
R19 = v[j]

l'array che ho considerato ha il primo elemento puntato da X quindi R26

Codice: Seleziona tutto
FOR_ 0:
cp i, dim
brge esci
ld elem, +X
    FOR_1:
      ld v[j], -X
      cp elem, v[j]
      brge fine_for_0
      st +X, v[j]
      rjmp FOR_1

fine_for_0:
dec X ; non so se è un'istruzione valida
st X, elem
inc i
rjmp FOR_0

ESCI:
nop



Sicuramente ci saranno parecchi errori. Il problema principale è che non so come gestire facilmente gli indici,
dato che in C se l'indice per esempio è 5, scrivendo v[5] stiamo considerando il sesto elemento dell'array, in assembly non riesco a capire come fare. Ovviamente so che qualunque cosa fatta in C si può convertire in assembly dato che questo passaggio viene fatto dall'assemblatore di C, però sto avendo molte difficoltà.
Avatar utente
Foto Utentepeppe1992
45 1 4
New entry
New entry
 
Messaggi: 64
Iscritto il: 17 mag 2011, 22:54

2
voti

[10] Re: Ordinamento di 10 valori atmega 8535

Messaggioda Foto Utentexyz » 31 mag 2018, 12:59

Prima di tutto se programmi in assembler, devi conoscere l'assembler della CPU che utilizzi. Se hai problemi a trascrivere un algoritmo in assembler significa che non conosci bene assembler, un mio consiglio è studiarlo in modo più approfondito altrimenti difficilmente riuscirai a scrivere del codice funzionante.

Una analisi prima di scrivere del codice riguarda la grandezza degli indirizzi, la memoria RAM del ATmega8535 è di 544 byte quindi utilizzare un registro a 8 bit per contenere un qualsiasi indirizzo RAM non va bene, devi usare una coppia di registri a 8 bit. Gli indici, al massimo devono indirizzare 10 elementi, quindi un registro a 8 bit va bene ma quando viene sommato ad un indirizzo RAM bisogna eseguire una somma a 16 bit, altrimenti si commette un errore.

In C (come tutti i linguaggi seri) l'indice del primo elemento è uguale a zero, quindi quando vedi scritto in C "v[5]" viene tradotto in assembler (salvo ottimizzazioni) in questo modo usando l'algebra dei puntatori in C: "((uint8_t *)v) + 5 * sizeof(*v)". Cosa significa che viene preso l'indirizzo di base dell'arrray "v" e viene sommato il valore dell'indice moltiplicato per la grandezza di un elemento dell'array in byte. Nel tuo caso la grandezza degli elementi è pari a 1, quindi per tradurre in assembler istruzione in C "v[5]" devi prendere indirizzo di "v" a 16 bit e sommare a 16 bit il valore 5, se usi un registro a 8 bit per contenere l'indice la somma viene fatta estendendo a zero il valore dell'indice.
Avatar utente
Foto Utentexyz
5.195 2 4 5
Master EY
Master EY
 
Messaggi: 1366
Iscritto il: 5 dic 2009, 18:37
Località: Italy Turin

Prossimo

Torna a Firmware e programmazione

Chi c’è in linea

Visitano il forum: Nessuno e 1 ospite