eGospodarka.pl
eGospodarka.pl poleca

eGospodarka.plGrupypl.misc.elektronikaSTM32 - problem z ADCRe: STM32 - problem z ADC
  • Data: 2011-11-10 05:36:55
    Temat: Re: STM32 - problem z ADC
    Od: SM <b...@k...com.pl> szukaj wiadomości tego autora
    [ pokaż wszystkie nagłówki ]

    > Ja ADc używam tylko do orientacyjnego pomiaru napięcia i prądu, więc
    > nawet, jeśli te problemy u mnie by wystąpiły - nie zauważyłbym ich. Mogę
    > jutro spróbować coś pomierzyć i pooglądać... Ale najpierw - powiedz,
    > jaki to ADC, czy masz osobne VREF, czy wspólne z AVCC itp. Patrzyłeś na
    > zasilanie AVCC?? Może stmtąd coś przechodzi?? Jak masz ustawiony
    > przetwornik?? Ile cykli na próbkowanie?? Czy próbowałeś to zmieniać i
    > jak to wpływało na pomiary??
    >

    Procesorek STM32F103RBT6, tak więc VREF wewnętrznie połączone do VDDA.
    VDDA zasilane z VDD poprzez dławik 100uH, odsprzęgnięte 1uF+10nF
    (ceramiczne SMD). Masa analogowa VSSA połączona w jednym punkcie
    z VSS i wyprowadzona do stopnia wejściowego części analogowej.

    Zmiana czasu próbkowania w SMPR2 dawała niewielkie zmiany (to było
    dla mnie największym zaskoczeniem). Podobnie zmiana preskalera ADC
    w CFGR.

    Róźnice były przy przetwarzaniu na jednym kanale (PA0) i na 4 (PA0..3).
    Poziom zakłóceń zmieniał się w zależności od napięć panujących na
    wejściach. Np. Gdy miałem tylko PA0 to tam były największe zakłócenia,
    ale gdy PA0..3 to PA0 i PA1 prawie nie zakłócały PA2 zakłócało, PA3
    zakłócało najmocniej.

    P.S.
    Kawałek kodu.

    @ --- clocks config ADC clk = 12MHz

    ldr r0, [r12, #RCC_CFGR_OFS]
    ldr r1, =(4 << RCC_CFGR_PPRE1) | (2 << RCC_CFGR_SW) | (2 <<
    RCC_CFGR_ADCPRE)
    orr r0, r1
    str r0, [r12, #RCC_CFGR_OFS]

    @ --- APB2 - 72MHz (ADC enable)

    ldr r0, [r12, #RCC_APB2ENR_OFS]
    ldr r1, =(1 << RCC_APB2ENR_IOPAEN) | (1 << RCC_APB2ENR_IOPBEN) | (1 <<
    RCC_APB2ENR_IOPCEN) | (1 << RCC_APB2ENR_IOPDEN) | (1 << RCC_APB2ENR_AFIOEN)
    orr r0, r1
    ldr r1, =(1 << RCC_APB2ENR_TIM1EN) | (1 << RCC_APB2ENR_ADC1EN)
    orr r0, r1
    str r0, [r12, #RCC_APB2ENR_OFS]

    @ --- init ADC

    .equiv ADC_CR1_OFS, 0x04
    .equiv ADC_SMPR2_OFS, 0x10

    ldr r12, =ADC1_BASE

    @ CR1

    ldr r0, =0
    str r0, [r12, #ADC_CR1_OFS]

    @ CR2

    ldr r0, =(7 << 17)
    str r0, [r12, #ADC_CR2_OFS]

    @ SQR1 (nbr of channels = 1)

    ldr r0, =(0 << 20)
    str r0, [r12, #ADC_SQR1_OFS]

    @ SMPR2 (sample time) - tutaj robiłem zmiany

    ldr r0, =(7 << 0) | (7 << 3) | (7 << 6) | (7 << 9)
    str r0, [r12, #ADC_SMPR2_OFS]

    @ SQR3 (sel channel IN0)

    ldr r0, =(0 << 0)
    str r0, [r12, #ADC_SQR3_OFS]

    @ ADC power on

    bez uruchomienia ADC (ADON=1) nie działa
    u mnie kalibracja chociaż w PDFie piszą że kalibracja powinna być
    robiona przy ADON=0. Ale STM nawet w swoich przykładach daje
    ADON=1 przed kalibracją.

    ldr r0, =(7 << 17) | (1 << 0)
    str r0, [r12, #ADC_CR2_OFS]

    @ reset kalibracji

    ldr r0, [r12, #ADC_CR2_OFS]
    orr r0, #0x8
    ldr r0, =(7 << 17) | (1 << 3) | (1 << 0)
    str r0, [r12, #ADC_CR2_OFS]

    @ czekanie na zakończenie

    jmp1: ldr r0, [r12, #ADC_CR2_OFS]
    tst r0, #(1 << 3)
    bne jmp1

    @ start kalibracji

    ldr r0, [r12, #ADC_CR2_OFS]
    orr r0, #0x4
    ldr r0, =(7 << 17) | (1 << 2) | (1 << 0)
    str r0, [r12, #ADC_CR2_OFS]

    @ czekanie na zakończenie

    jmp2: ldr r0, [r12, #ADC_CR2_OFS]
    tst r0, #(1 << 2)
    bne jmp2


    W przerwaniu co 5kHz wykonuję:

    @ odczyt ADC

    ldr r12, =ADC1_BASE
    ldr r0, [r12, #ADC_DR_OFS]

    @ zapis do bufora w RAM

    ...

    @ start ADC

    ldr r0, =(7 << 17) | (1 << 20) | (1 << 22) | (1 << 0)
    str r0, [r12, #ADC_CR2_OFS]


    Dla wyjaśnienia - jak widać wszystko w asemblerze. C używam tylko
    do bardzo dużych projektów. Tutaj mam tylko ADC, obsługa SD Card,
    obsługa USB jako CDC, więc dużo tego nie jest.

    Ponieważ do RAM i rejestrów można dostać się tylko adresowaniem
    pośrednim, żeby skrócić program używam pewnych na stałe przypisanych
    rejestrów:
    R12 - zawsze baza dla danego peryferium (ADC1_BASE, TIM1_BASE, ...)
    R11 - zawsze wskazuje początek RAM (bss_beg) dzięki temu dostęp do
    zmiennych byte, half word, word realizuję poprzez makra:

    .macro getb Reg Name
    ldrb \Reg, [r11, #\Name - bss_beg]
    .endm

    .macro geth Reg Name
    ldrh \Reg, [r11, #\Name - bss_beg]
    .endm

    .macro getw Reg Name
    ldr \Reg, [r11, #\Name - bss_beg]
    .endm

    .macro putb Reg Name
    strb \Reg, [r11, #\Name - bss_beg]
    .endm

    .macro puth Reg Name
    strh \Reg, [r11, #\Name - bss_beg]
    .endm

    .macro putw Reg Name
    str \Reg, [r11, #\Name - bss_beg]
    .endm

    np:
    getw r1, rx_cnt
    putb r0, adc_num

    nie muszę za każdym razem ładować do rejestru pomocniczego
    adresu zmiennej żeby ją zapisać/odczytać
    podobnie z dostępem do peryferiów - ładuje do R12 bazę
    i posługuję się adresowaniem z przesunięciem

Podziel się

Poleć ten post znajomemu poleć

Wydrukuj ten post drukuj


Następne wpisy z tego wątku

Najnowsze wątki z tej grupy


Najnowsze wątki

Szukaj w grupach

Eksperci egospodarka.pl

1 1 1

Wpisz nazwę miasta, dla którego chcesz znaleźć jednostkę ZUS.

Wzory dokumentów

Bezpłatne wzory dokumentów i formularzy.
Wyszukaj i pobierz za darmo: