SPI och DAC from the very början... *FUNGERAR*

PIC, AVR, Arduino, Raspberry Pi, Basic Stamp, PLC mm.
sodjan
EF Sponsor
Inlägg: 43251
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Inlägg av sodjan »

Verkar vara något skumt med hur asm koden accessar Basic variabler.
Här finns ett exemepl :

http://www.mikroe.com/forum/viewtopic.p ... hlight=asm
sodjan
EF Sponsor
Inlägg: 43251
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Inlägg av sodjan »

Jag var bara tvungen att slänga upp en 18F2220 och en TLV5618 på en labbplatta... :-)
Koden nedan fungerar. Den ger en sågtandsspänning på kanal A med en period på ca 0.5 sek. Spännings ref är en LM385BZ-1.2, alltså 1.2 V och topspännngen på utsignalen blir alltså ca 2.4 V. CS sitter på PORTB.0 och SDO, SCK är de vanliga. Om jag ändrar till "OSC = HSPLL", blir perioden ca 0.12 sek som förväntat. Obs, det är ätt "ful-hack" bara för att få igång något med mer hårdkodade sakar än vad man normalt vill ha...

Kod: Markera allt

;**********************************************************
      list p=18f2220
      include "p18f2220.inc"
;**********************************************************
;     CONFIG settings
;
      config OSC = HS, FSCM=OFF, IESO=OFF, PWRT = ON, BOR = OFF
      config WDT = OFF, MCLRE=OFF, STVR = OFF, LVP = OFF
      config DEBUG = OFF, CP0 = OFF, CP1 = OFF
      config CPB = OFF, CPD = OFF, WRT0 = OFF
      config WRT1 = OFF, WRTB = OFF
      config WRTC = OFF, WRTD = OFF, EBTR0 = OFF, EBTR1 = OFF
      config EBTRB = OFF
;
;**********************************************************
;     Variables. We put them in the access bank...
;
vars       UDATA_ACS
dac_h      RES   1
dac_l      RES   1

;**********************************************************
      
Boot      CODE      h'0000'
          goto      Start
;**********************************************************

Main      CODE

Start
    bcf       trisc, 3      ; Quick-n-dirty TRIS bits...
    bcf       trisc, 5
    bcf       trisb, 0
    bcf       trisb, 1
    
    clrf      dac_l            ; Init DAC value.
    clrf      dac_h
    bsf       dac_h, 7         ; Update DAC cannel A.
    
    movlw     b'00000000'      ; Setup of MSSP/SPI
    movwf     SSPSTAT
    movlw     b'00100010'
    movwf     SSPCON1

loop
    clrf      wreg            ; Increment DAC value.
    incf      dac_l, f
    addwfc    dac_h, f

    btfss     dac_h,4         ; Over max value ?
    bra       send2spi        ; No, go update DAC
    clrf      dac_l           ; Yes, re-init value.
    clrf      dac_h
    bsf       dac_h, 7
      
send2spi

    bcf       portb,0         ; Enable CS

    movff     dac_h, SSPBUF   ; First byte
      
first_byte_wait
    btfss     SSPSTAT, BF     ; Wait for BF flag.
    bra       first_byte_wait
    movf      SSPBUF, W       ; Dummy read...

    movff   dac_l, SSPBUF     ; Second byte
      
sec_byte_wait
    btfss     SSPSTAT, BF     ; Wait for BF flag.
    bra       sec_byte_wait
    movf      SSPBUF, W       ; Dummy read...

    bsf       portb,0         ; Disable CS

    goto      loop            ; Once again...
      
    end
Användarvisningsbild
JimmyAndersson
Inlägg: 26578
Blev medlem: 6 augusti 2005, 21:23:33
Ort: Oskarshamn (En bit utanför)
Kontakt:

Inlägg av JimmyAndersson »

Tack för koden!!

Jag har haft mycket att göra, men nu är jag tillbaka. :)

Hm, fick några felmeddelande när jag körde 'build'.
Error[113] DACTEST11.ASM 32 : Symbol not previously defined (trisc)
Error[113] DACTEST11.ASM 33 : Symbol not previously defined (trisc)
Error[113] DACTEST11.ASM 34 : Symbol not previously defined (trisb)
Error[113] DACTEST11.ASM 35 : Symbol not previously defined (trisb)
Error[113] DACTEST11.ASM 47 : Symbol not previously defined (wreg)
Error[113] DACTEST11.ASM 59 : Symbol not previously defined (portb)
Error[113] DACTEST11.ASM 75 : Symbol not previously defined (portb)

Jag har säkert bara glömt något, frågan är vad...

TRIS-felen försvinner om jag kör
movlw h'00' och movwf TRISC
movlw h'00' och movwf TRISB

Liknande grejj går att göra med PORTB, men rad47 (wreg) vet jag inte hur jag ska fixa.
Det bästa vore förstås om jag fixar orsaken till felmeddelandena. :)
sodjan
EF Sponsor
Inlägg: 43251
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Inlägg av sodjan »

Har du med :

include "p18f2220.inc"

???


AHA !!
Du har inte slagit av "case sensitive" ! Gör det...
Finns absolut ingen anledning att köra med case sensitive på.
Project -> Build options -> Project -> MPASM, någonting...
Användarvisningsbild
JimmyAndersson
Inlägg: 26578
Blev medlem: 6 augusti 2005, 21:23:33
Ort: Oskarshamn (En bit utanför)
Kontakt:

Inlägg av JimmyAndersson »

Jepp, felen försvann mycket riktigt när jag ändrade "case sensitive".

Det fungerar! :) Lysdioden blinkar! Ser ut som en sågtandvåg.


Nu ska jag försöka få det att fungera i MikroBasic.
edit: Nu *ska* jag få det att fungera i MikroBasic. :)
I'll be back! 8)
sodjan
EF Sponsor
Inlägg: 43251
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Inlägg av sodjan »

Fint att i alla fall *det* fungerar i din miljö... :-)
Användarvisningsbild
JimmyAndersson
Inlägg: 26578
Blev medlem: 6 augusti 2005, 21:23:33
Ort: Oskarshamn (En bit utanför)
Kontakt:

Inlägg av JimmyAndersson »

Jo, det är tur... :)

Har kodat lite i MikroBasic nu: I min inline-asm har jag med det i din kod som ligger från "send2spi" till raden innan "goto loop". Men istället för att räkna upp dac_l och dac_h så plockar jag värdet som skickas till proceduren DAC_Output.
Nu ger MikroBasic inga felmeddelanden. Men det fungerar inte. Dvs, lysdioden blinkar inte, den är släckt hela tiden.

Märkte att du bara skickar nollor till DAC'en i början innan den stegar upp?
I mina tester har jag använt "11000000 00000000", i databladet står programbitarna "1100" för konfigurationen: "The DAC A output is updated on the rising clock edge after D0 is sampled." Men din kod verkar använda "Write data to DAC B and BUFFER" och "slow mode" dvs "0000" som programbitar.
Jag tolkade "Write data to DAC B and BUFFER" som att den inte använde DAC A, men det kanske är fel?
(Jag testade förstås även att sätta programbitarna till "0000".)

Ska prova att byta ut mer och mer i min kod mot inline-asm. Man kan kanske fråga sig varför jag inte kör assembler helt och hållet? Det är en bra fråga... :) Svaret är: Eftersom jag har så mycket annan kod till slutprojektet i MikroBasic så skulle det ta för mycket tid att koda om allt till assembler...

edit: Skrev fel, kopierade inte koden från "loop" och framåt, däremot från "send2spi" och framåt...
Senast redigerad av JimmyAndersson 16 november 2005, 00:54:14, redigerad totalt 1 gång.
sodjan
EF Sponsor
Inlägg: 43251
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Inlägg av sodjan »

Nja, jag har "1000" som command, "Update chan A". Kolla koden. Efter att ha "nollat" värdet gör jag "bsf dac_h, 7", alltså sätter högsta biten i dac_h.
Användarvisningsbild
JimmyAndersson
Inlägg: 26578
Blev medlem: 6 augusti 2005, 21:23:33
Ort: Oskarshamn (En bit utanför)
Kontakt:

Inlägg av JimmyAndersson »

Oj, du har rätt. Jag behöver nog starkare glasögon... Bild

edit: Jag fortsätter förstås byta ut grejjer i min basic-kod och jämföra asm-koden med basic-koden, så du inte tror jag somnat...
Märker att mina assembler-kunskaper förbättras på detta sätt. Riktigt kul faktiskt.

En liten fråga som jag kanske borde fråga MikroElektronika egentligen, men du kanske vet svaret: När man använder inline-asm gör MikroBasic om den koden på något vis, eller blir resultatet likadant som om jag hade skrivit in asm-koden i t.ex MPLAB? (När jag visar asm-koden som MikroBasic genererar så ser jag inte mina inline-asm-rader....)


Assemblerkoden du gjorde fungerar, men inte när jag använder "send2spi", "first_byte_wait" och "sec_byte_wait" från din kod, som inline-asm. Frågan är varför...



Skickar med min kod som den ser ut just nu:

Kod: Markera allt

const CHIP_SELECT  = 0
dim value as word

sub procedure Init
  ADCON1 = %00001111 ' Digitala A-portar!
  TRISA = 0 'TESTLED
  PORTA.0 = 0 'TESTLED
  PORTA.1 = 0 'TESTLED
  PORTA.2 = 0 'TESTLED
  PORTA.3 = 0 'TESTLED

  TRISB = 0   ' LCD
  TRISC.1 = 0 ' LCD
  TRISC.2 = 0 ' LCD
  PORTB = 0   ' LCD
  PORTC.1 = 0 ' LCD
  PORTC.2 = 0 ' LCD

  ClearBit(TRISC,CHIP_SELECT) ' Utgång på ChipSelect (RC0)
  TRISC.3=0 ' Utgång på SCK -Serial Clock-  (RC3)
  TRISC.5=0 ' Utgång på SDO -Data UT-       (RC5)
  TRISC.4=1 ' SDI till ingång.
  SetBit(TRISC,CHIP_SELECT) ' Ska vara hög innan den blir låg.

  'Initierar SPI till DAC-kretsen (TLV 5618A) --------------
  SSPSTAT.SMP=0 ' Input data sampled at the MIDDLE of data output time.
  SSPSTAT.CKE=0 ' Data skickas on falling edge of SCK
  SSPSTAT.5=0
  SSPSTAT.4=0
  SSPSTAT.3=0
  SSPSTAT.2=0
  SSPSTAT.1=0
  SSPSTAT.0=0
  SSPCON1.WCOL=0  ' Ingen WriteCollisionDetect
  SSPCON1.SSPOV=0 ' Ingen ReceiveOverflowIndicator
  SSPCON1.SSPEN=1 ' Enable serieport och SCK, SDo, SDI och SS
  SSPCON1.CKP=0   ' CKP. Idle state for clock is a low level
  SSPCON1.SSPM3=0 ' Master mode, clock = Fosc/64
  SSPCON1.SSPM2=0 ' Master mode, clock = Fosc/64
  SSPCON1.SSPM1=1 ' Master mode, clock = Fosc/64
  SSPCON1.SSPM0=0 ' Master mode, clock = Fosc/64
end sub


sub procedure DAC_Output(dim value as word)

dim dac_h as byte
dim dac_l as byte

dac_h = hi(value)             ' Förbered bit 15-8
dac_l = lo(value)             ' Förbered bit 7-0

asm
send2spi
    bcf       portc,0         ; Enable CS

    movff     dac_h, SSPBUF   ; First byte

first_byte_wait
    btfss     SSPSTAT, BF     ; Wait for BF flag.
    bra       first_byte_wait
    movf      SSPBUF, W       ; Dummy read...

    movff   dac_l, SSPBUF     ; Second byte

sec_byte_wait
    btfss     SSPSTAT, BF     ; Wait for BF flag.
    bra       sec_byte_wait
    movf      SSPBUF, W       ; Dummy read...

    bsf       portc,0         ; Disable CS

end asm
end sub


main:
init

  while true
  value = %1000000000000000
  DAC_Output(value) 'Skickar
  delay_ms(500)
  value = %1000111111111111
  DAC_Output(value) 'Skickar
  delay_ms(500)
  wend

end.
Jag har förresten ändrat CS så den ligger på PORTC,0 istället. Den ändringen fungerade när jag provade med hela assembler-filen i MPLAB.


edit 051116: Nu har jag skrivit om problemet i MikroElektronika's forum. Ska bli intressant att se vad de svarar...
Användarvisningsbild
JimmyAndersson
Inlägg: 26578
Blev medlem: 6 augusti 2005, 21:23:33
Ort: Oskarshamn (En bit utanför)
Kontakt:

Inlägg av JimmyAndersson »

Har fått lite tips på MikroElektronika's forum:

Någon föreslog att jag skulle köra med Fosc/16 eftersom slave-enheten kan ha problem att hänga med i höga hastigheter. Tyvärr hjälpte det inte.
Ett annat tips handlade också om timing, men att man behövde skicka en 17e bit så att SCLK fick ytterligare en puls för att hamna rätt.

Så här alltså:
Note: After transfer of the LSB during a data or control write cycle, one additional rising edge on SCLK is required to reset the internal state machine. This edge can occur when CS is high or low, but must occur before the next falling CS edge that begins the following write cycle. Refer to the timing diagram for more information.

Det hjälpte inte heller. Frågade ytterligare en gång varför inte MikroBasic's egna rutiner/library fungerar och varför det fungerar i assembler när man bara skickar 16bits (så att SCLK får 16 pulser). Väntar på svar om detta därifrån nu... :)

Fick tips om att använda en annan DAC: MCP4922, men det känns onödigt eftersom det inte är något fel på TLV5618A....
sodjan
EF Sponsor
Inlägg: 43251
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Inlägg av sodjan »

Så vitt jag förstår, så är den assmebler som MikroBasic använder inline, inte densamma som den man kör i MPLAB/MPASM. Det verkar saknas stöd för en del inbyggda directiv (som BANKSEL) o.s.v. Ä rdock lite osäker eftersom jag inte har kört inline asm i M-B själv...

När du ändå är på forumet skulle du kunna fråga om någon bättre dokumentation en den som finns i User Guide. Det är ju bara en halv sida....

> (När jag visar asm-koden som MikroBasic genererar så ser jag inte mina inline-asm-rader....)

Det verkar konstigt, lite dåligt om det är så.
Användarvisningsbild
JimmyAndersson
Inlägg: 26578
Blev medlem: 6 augusti 2005, 21:23:33
Ort: Oskarshamn (En bit utanför)
Kontakt:

Inlägg av JimmyAndersson »

Ska fråga om bättre dokumentation, bra idé!


Jag fick en kod av en användare på det forumet, gjord med MikroBasic's egna rutiner/librarys.
Tro det eller ej, men den koden fungerar! :)
Skillnaderna mot min kod (när jag använde MikroBasic's rutiner) är att den här varianten har nop-"delay" och skickar en extra byte till DAC'en.

Tack för assembler-koden och all hjälp med detta problem!


Här är koden som jag fick från "xor" på MikroElektronika's forum:

Kod: Markera allt

const CHIP_SELECT  = 0
dim value as word

sub procedure Init
    ADCON1 = $0F        ' ADCON1 = %00001111 ' Digital A-ports!
    TRISA = 0           ' TESTLED's
    PORTA = 0
    TRISB = 0           ' LCD
    PORTB = 0
    TRISC = 0
    PORTC = 0

    SPI_INIT_ADVANCED(MASTER_OSC_DIV16,  DATA_SAMPLE_MIDDLE,  CLK_IDLE_LOW, LOW_2_HIGH)
    ClearBit(TRISC,CHIP_SELECT)   ' ChipSelect(RC0) direction is output
    SetBit(PORTC, CHIP_SELECT)    ' Disable CS
end sub

sub procedure DAC_Output(dim _value as word)
    dim temp_hi as byte
    dim temp_lo as byte

    ClearBit(PORTC,CHIP_SELECT) ' Enable CS

    temp_hi = hi(_value)
    temp_lo = lo(_value)

    SPI_WRITE(temp_hi)
    SPI_WRITE(temp_lo)

    nop                         '@40MHz some delay may be necessary
    nop
    SetBit(PORTC,CHIP_SELECT)   ' Disable CS

    SPI_WRITE($00)              ' adds the 17th SCLK Pulse and then some
end sub

main:

    Init

    While true
        value = %1100000000000000
        DAC_Output(value)      ' Sending
        delay_ms(500)
        value = %1100111111111111
        DAC_Output(value)      ' Sending
        delay_ms(500)
    Wend

end.


edit: När jag byter ut while-loopen mot nedanstående kod så blir det en snygg upp-toning av lysdioden. (Skrev programbitarna binärt för att det ska vara lättare att se. $C000 hade inte sagt lika mycket.)

Kod: Markera allt

    While true
        prog = %1100000000000000  ' Programbitarna
      for x = 0 to 4095 step 7
        value = prog or x  ' Slår ihop programbitarna med databitarna
        DAC_Output(value)      ' Sending
        delay_ms(10)
      next x
    Wend

Så nu kan jag börja jobba med mitt ursprungliga projekt. Kul! 8)
DeeJayPA
EF Sponsor
Inlägg: 1384
Blev medlem: 4 december 2004, 21:17:57
Ort: Luleå

Inlägg av DeeJayPA »

Grattis :tumupp:
Användarvisningsbild
Greve Hamilton
EF Sponsor
Inlägg: 544
Blev medlem: 4 september 2004, 15:03:35
Ort: GBG

Inlägg av Greve Hamilton »

Härligt när det löser sig!
Användarvisningsbild
JimmyAndersson
Inlägg: 26578
Blev medlem: 6 augusti 2005, 21:23:33
Ort: Oskarshamn (En bit utanför)
Kontakt:

Inlägg av JimmyAndersson »

DeeJayPA & GreveHamilton: Tack! :)

Otroligt att man kan hålla på så länge för att lösa ett problem. Jag började på våren 1937...... :roll:
:lol: ok, kanske inte, men det känns så.


-Sedan är det förstås så att det alltid bara behövs små förändringar för att det ska fungera...
-Mitt första kod-test ser nästan likadant ut som den koden som fungerar! :)
Skriv svar