Leggere una stringa da uart (AVR assembly)

Sezione dedicata ai Microcontrollori e ai Sistemi Embedded

Leggere una stringa da uart (AVR assembly)

Postby mr.flower » 12 Oct 2012, 17:39

Salve a tutto il forum :)
il problema in cui mi sto imbattendo è quello di leggere (e memorizzare) una stringa in ingresso via UART.

Vi spiego meglio il mio intento:
ho un modulo GPS sul quale posso ricevere sms e chiamate e attuare di conseguenza determinate operazioni (il mio è un progetto di domotica remota). Non ho problemi a interfacciare micro (ATMEGA8535) e modulo GSM (SIMCOM SIM900), riesco ad inviare delle stringhe con successo. Il problema sta nella ricezione.
Quello che mi serve è verificare il numero di telefono del chiamante (o di chi invia l'sms) per controllare se sia tra la listi dei numeri consentiti.

Prendo l'esempio della chiamata perché più semplice ma per gli sms il procedimento è del tutto simile.
Tramite chiamata ho pensato di implementare un "apricancello": dunque io chiamo il numero della scheda inserita nel modulo e si attiva l'apricancello (che per ora sto simulando con l'accensione di un LED direttamente sull'STK500 ma questo non ha importanza).

L'algoritmo è questo:
1. Ricevo la chiamata;
2. Rifiuto dopo uno squillo;
3. Controllo il numero;
4. Decido di conseguenza cosa fare.

Come avrete capito, il problema lo incontro al punto 3. Nel momento in cui rifiuto la chiamata, il modulo invia una stringa molto lunga contenente tanti parametri, tra i quali il numero chiamante. Il mio proposito è quello di memorizzare tale stringa nella RAM per poi filtrare solo i caratteri relativi al numero e quindi confrontarlo.

Ecco il codice assembly che ho provato ad implementare senza successo:

Code: Select all
ExtInt1_call:           ; Handles voice calls
ldi Delay1, 0x80        ; Sets up registers for 3s delay routine
ldi Delay2, 0x4F        ;
ldi Delay3, 0x12        ;

Wait_time_to_reject:
subi Delay1, 1          ;
sbci Delay2, 0          ;
sbci Delay3, 0          ;
brcc Wait_time_to_reject;


rcall Send_A            ; Reject the incoming call
rcall Send_T            ;
rcall Send_H            ;
rcall Send_CR           ;

;================================
; CODICE DI PROVA SU 3 CARATTERI
;================================
; Y inizializzato a 0x060, prima locazione della RAM

ldi WaitCounter, 3       ;
Get_character:
sbis UCSRA, RXC            ; Wait for character
rjmp Get_character       ;
in temp, UDR             ; Read Character
st Y+, temp              ;
dec WaitCounter          ;
brne Get_character       ;

ldi YL, 0x60             ;
ld temp, Y+              ;
ld temp2, Y+              ;
ld temp3, Y              ;

out PortB, temp2        ; stampa di prova


Ciò che ottengo stampando temp, temp2 o temp3 è sempre il codice ascii relativo al LINE FEED (0A) o al FORM FEED (0C).
Non riesco a capire dove sbaglio, l'indirizzamento alle posizioni in RAM dovrebbe essere corretto. Escluderei lo stack overflow poiché lo stack pointer è inizializzato a RAMEND e l'indirizzamento che faccio io a RAMSTART. Ho pensato ad un certo punto fossero problemi di tempistica ma neanche quello perché ho fatto dei calcoli e tramite UART ricevo 1Byte ogni 830us e il ciclo di polling che ho creato controlla l'arrivo di un nuovo Byte ogni 4us.

Non riesco ad uscirne, qualsiasi aiuto è sinceramente gradito, anche un codice prefatto per la generica ricezione di una stringa da UART in assembly, anche se mi piacerebbe capire dove sbaglio col mio codice. A tal proposito non sono riuscito a trovare nulla, solo C, assembly pare parecchio snobbato.
mr.flower
 
Posts: 3
Joined: 12 Oct 2012, 17:15

Re: Leggere una stringa da uart (AVR assembly)

Postby filosofo » 12 Oct 2012, 21:03

salve mr.flower e benvenuto al forum,

potresti mostrare la stringa di caratteri che proviene dal modulo gsm?

inoltre posso chiederti come mai la scelta di AVR-assembly, visti tutti i compilatori che attualmente ci vengono in aiuto?

ciao
filosofo
 
Posts: 74
Joined: 23 Oct 2011, 09:52
Location: Dintorni di Roma

Re: Leggere una stringa da uart (AVR assembly)

Postby deluca » 12 Oct 2012, 22:37

da chi sarebbe snobbato? ;)
è vero che oggi quasi tutti ci dilettiamo con il C, con C++, il Bascom e altri sistemi ad alto livello ma ancora oggi
per me è un vero divertimento e mi affasciana molto scrivere in assembly-avr dopo almeno 23 anni (adesso non ricordo con esattezza)
mi ricordo che nei primi anni 90 al laboratorio prog. elett. dell'istituto nazionale di fisica nucleare mi arrivò uno dei primi sample di RISC AVR at90s8515 pin-to-pin compatibile con l'8051-CISC che usavo in quasi tutti i miei progetti,
così dovetti cambiare metodo di programmazione e linguaggio passando all'assembly-avr visto che non esisteva ancora nessun compilatore ne C, ne Bas, ne Pas, ne altro.

per questo motivo stasera mi sono rimesso al lavoro e ho preparato questo semplice codice assembly per atmega8 così configurato:
clock = 16Mhz
baud = 19200
interrupt uart

cosa fa?
-legge dati dalla uart ... la stringa deve terminare con LF CR , non so se nel tuo gsm la stringa è terminata così
-confronta il numero in ingresso con numeri in formato "alpha" che ho memorizzato in db, e assegna un codice da 1 a 3 se il numero in ingresso è uguale ad uno dei tre memorizzati,
-alla fine il controllo ritorna al main.

chiaramente si tratta di una bozza di codice che dovrebbe essere ottimizzato e di sicuro aricchito.....

Code: Select all
;**************************************************
; questo programma legge dalla seriale un numero
; e lo confronta con tre numeri memorizzati sul DB
; se è uguale ad uno di essi assegna a "b" il codice
; oppure si può gestire una uscita
; autore: Giovanni De Luca
; Data: 12-10-2012
;**************************************************
.include   "C:\avrasm\inc\m8def.inc"
;
      .DSEG
      
      .CSEG
.ORG   0
      rjmp   _Reset
.ORG      INT0addr
      reti
.ORG      INT1addr
      reti
.ORG      OC2addr
      reti
.ORG      OVF2addr
      reti
.ORG      ICP1addr
      reti
.ORG      OC1Aaddr
      reti
.ORG      OC1Baddr
      reti
.ORG      OVF1addr
      reti
.ORG      OVF0addr
      reti
.ORG      SPIaddr
      reti
.ORG      URXCaddr
      rjmp   IntN11

_Reset:
      ldi      yl,Low(RAMEND)
      out      SPL,yl
      ldi      yh,high(RAMEND)
      out      SPL+1,yh
      sbiw   yl,32
      ldi      zl,0x18
      out      UCSRB,zl
      ldi      zh,high(51)
      ldi      zl,Low(51)
      out      UBRRL,zl
      out      UBRRH,zh

      sei

      sbi      UCSRB,7

      .DSEG
a:      .Byte    21
      .CSEG

      .DSEG
b:      .Byte    1
      .CSEG
      
;--------- qui inizia il ciclo main
L0000:
      Nop
      rjmp   L0000
L0001:

;--------- Interrupt della seriale
IntN11:
      in      r2,SREG
      push   zl
      push   zh
      push   r0
      push   r1
      push   r2
      push   r24
      push   r25
      push   xl
      push   xh
      push   r19
      push   r20
      push   r21
      push   r22
      push   r23
      ldi      r25,20
      ldi      xl,Low(a)
      ldi      xh,high(a)
      call   _InSt9
      
;------- controlla il primo numero memorizzato
      ldi      zl,Low(a)
      ldi      zh,high(a)
      mov      xl,zl
      mov      xh,zh
      ldi      zl,Low(S000*2)
      ldi      zh,high(S000*2)
      call   _StCCp
      breq   PC+0x02
      rjmp   L0003
L0004:
      ldi      zl,Low(1)
      sts      b,zl
L0003:

;------- controlla il secondo numero memorizzato
      ldi      zl,Low(a)
      ldi      zh,high(a)
      mov      xl,zl
      mov      xh,zh
      ldi      zl,Low(S001*2)
      ldi      zh,high(S001*2)
      call   _StCCp
      breq   PC+0x02
      rjmp   L0006
L0007:
      ldi      zl,Low(2)
      sts      b,zl
L0006:

;------- controlla il terzo numero memorizzato
      ldi      zl,Low(a)
      ldi      zh,high(a)
      mov      xl,zl
      mov      xh,zh
      ldi      zl,Low(S002*2)
      ldi      zh,high(S002*2)
      call   _StCCp
      breq   PC+0x02
      rjmp   L0009
L0010:
      ldi      zl,Low(3)
      sts      b,zl
L0009:

;----- Fine Interrupt
      pop      r23
      pop      r22
      pop      r21
      pop      r20
      pop      r19
      pop      xh
      pop      xl
      pop      r25
      pop      r24
      pop      r2
      pop      r1
      pop      r0
      pop      zh
      pop      zl
      out      SREG,r2
      reti

;------ i numeri memorizzati in String constants:
S000:   .db   "348000000", 0
S001:   .db   "095000000", 0
S002:   .db   "396111111", 0


;------- GetChar
_GetCh:   sbis   UCSRA,0x07
      rjmp   _GetCh
      in      zl,UDR
      ret

;------- StringConstCompare
_StCCp:   push   xl
      push   xh
_StCC2:   ld      r24,X+
      lpm
      adiw   zl,1
      cp      r24,r0
      brne   _StCC1
      tst      r24
      brne   _StCC2
_StCC1:   pop      xh
      pop      xl
      ret

;-------- Input stringa numerica
_Input:   ldi      xl,Low(RAMEND - 32)
      ldi      xh,high(RAMEND - 32)
      ldi      r25,0x06
_InSt9:   rcall   _GetCh
      cpi      zl,0x0a
      breq   _InEnd
      cpi      zl,0x0d
      breq   _InSt9
      cpi      zl,0x08
      breq   _InBck
      tst      r25
      breq   _InSt9
      st      X+,zl
      dec      r25
      rjmp   _InSt9
_InEnd:   clr      zl
      st      X,zl
      ret
_InBck:   inc      r25
      sbiw   xl,0x01
      rjmp   _InSt9




non l'ho potuto testare ..... e quindi non posso assicurartelo
ma di certo potresti prendere spunto per scrivere o aggiustare il tuo.

buona serata
Ciao
Il mio sito: http://www.delucagiovanni.com ......e la chat: chat/
User avatar
deluca
Site Admin
 
Posts: 1104
Joined: 19 Jun 2011, 10:44
Location: 95123 - Catania (Italy)

Re: Leggere una stringa da uart (AVR assembly)

Postby mr.flower » 12 Oct 2012, 23:00

SEI UN GRANDE! :D

Grazie mille per l'impegno che ci hai messo a scrivere il codice!

Mi sento un po' stupido ma...il mio codice era giusto XD ...in pratica ciò che sbagliavo era aspettarmi di trovare il numero di telefono in una posizione in cui non ci poteva essere. Avevo calcolato male i caratteri da scartare, in pratica non avevo tenuto conto dei caratteri "nascosti" tipo carriage return, form feed e line feed ed in effetti il numero lo trovavo a partire dalla posizione 30 e non 22 come mi aspettavo!

Tuttavia credo proprio che prenderò spunto dal codice che hai scritto tu che è sicuramente più elegante del mio :)

Grazie ancora!
mr.flower
 
Posts: 3
Joined: 12 Oct 2012, 17:15

Re: Leggere una stringa da uart (AVR assembly)

Postby mr.flower » 12 Oct 2012, 23:06

filosofo wrote:salve mr.flower e benvenuto al forum,

potresti mostrare la stringa di caratteri che proviene dal modulo gsm?

inoltre posso chiederti come mai la scelta di AVR-assembly, visti tutti i compilatori che attualmente ci vengono in aiuto?

ciao



filosofo grazie del benvenutoe scusami, mi ero perso la tua risposta XD

La stringa che dovrei ricevere è qualcosa del tipo

Code: Select all
OK
+CLCC:1,0,0,0,0,”numero di telefono”,129


Come detto comunque ho risolto. Sbagliavo il punto dove andare a cercare l'inizio del numero di telefono ed ignoravo la presenza di alcuni caratteri ma sostanzialmente il mio codice era giusto :)

Per quanto riguarda la scelta di assembly...non è una vera e propria scelta! Questo progetto è per un esame universitario i cui vincoli sono appunto assembly e l'uso di un ATMEGA8535.
mr.flower
 
Posts: 3
Joined: 12 Oct 2012, 17:15

Re: Leggere una stringa da uart (AVR assembly)

Postby legacy » 13 Oct 2012, 11:42

pare essere molto gettonato ultimamente in italia l'asm AVR
sei il secondo in questo forum che deve fare progettino x uni in asm =P

molto molto bene, cosi' potremo gasarci anche noi quando andiamo in erasmus
tipo in USA o in UK, dove ah voi fate asm in uni ? beh, anche noi :mrgreen:

e che cavolo, mica sempre noi a pagare loro le birre, eh, sta volta ce la offrono
legacy
 
Posts: 862
Joined: 12 Mar 2012, 11:30


Return to Microcontrollori e microprocessori

Who is online

Users browsing this forum: No registered users and 13 guests