LinkedIn YouTube Facebook
Szukaj

Wstecz
IoT

Motylowy termometr

Kontroler DMA

Mikrokontrolery STM32F107 wyposażono w 12-kanałowy kontroler DMA. Każdy kanał może mieć programowo przypisany priorytet. Możliwa jest transmisja pomiędzy dwoma urządzeniami peryferyjnymi, z urządzenia peryferyjnego do pamięci, z pamięci do urządzenia peryferyjnego oraz z pamięci do pamięci. Dane można przesyłać od/do pojedynczych adresów, można także przesyłać bloki danych, przy czym maksymalny rozmiar takiego bloku może wynosić 65535 elementów (bajtów, półsłów lub słów).
Fragment programu konfigurującego kontroler DMA do pracy z przetwornikiem A/C przedstawiono na list. 2.

List. 2. Konfiguracja DMA do pracy z przetwornikiem A/C

 

// Konfiguracja DMA
DMA_DeInit(DMA1_Channel1);
DMA_InitStruct.DMA_PeripheralBaseAddr = ADC1_DR_Address;
DMA_InitStruct.DMA_MemoryBaseAddr = (u32)&ADCVal;
// Kierunek: zrodlem jest ADC
DMA_InitStruct.DMA_DIR = DMA_DIR_PeripheralSRC;
// Rozmiar burora: jeden kanal = rozmiar bufora 1
DMA_InitStruct.DMA_BufferSize = 1;

DMA_InitStruct.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_InitStruct.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_InitStruct.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
DMA_InitStruct.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
// Dane beda przesylane ciagle
DMA_InitStruct.DMA_Mode = DMA_Mode_Circular;

DMA_InitStruct.DMA_Priority = DMA_Priority_High;
DMA_InitStruct.DMA_M2M = DMA_M2M_Disable;

DMA_Init(DMA1_Channel1, &DMA_InitStruct);
// Wlacz DMA
DMA_Cmd(DMA1_Channel1, ENABLE);

 

Sterowniki wyświetlacza LCD

Na potrzeby aplikacji przygotowano trójwymiarową tablice zawierającą wygląd cyfr o wymiarach 24 na 40 pikseli, co umożliwiło zdefiniowanie czcionki Comic Sans MS o rozmiarze 36 punktów. Oprócz cyfr od 0 do 9 w tablicy znajduje się również znak oC. Fragment tablicy zamieszczono na list. 3.

List. 3. Fragment tablicy definicji znaków o rozmiarze 24 na 40 pikseli

 

// 24x40 pikseli, czcionka 36 punktow, Comic Sans MS
static const char number[11][5][24]  = {

//0
{{
0x00 , 0x00 , 0xC0 , 0xF0 , 0xF8 , 0xFC , 0xFE , 0x7E,
0x3F , 0x1F , 0x1F , 0x1F , 0x1F , 0x3F , 0x7F , 0xFE,
0xFC , 0xF8 , 0xE0 , 0xC0 , 0x00 , 0x00 , 0x00 , 0x00
},{
0xE0 , 0xFF , 0xFF , 0xFF , 0xFF , 0x1F , 0x01 , 0x00,
0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x01,
0x0F , 0xFF , 0xFF , 0xFF , 0xFF , 0xF8 , 0x00 , 0x00
},{
0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0x00 , 0x00 , 0x00,
0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00,
0x80 , 0xFF , 0xFF , 0xFF , 0xFF , 0x7F , 0x00 , 0x00
},{
0x00 , 0x3F , 0xFF , 0xFF , 0xFF , 0xFF , 0xF0 , 0x80,
0x80 , 0x00 , 0x00 , 0x00 , 0x80 , 0xC0 , 0xE0 , 0xF8,
0xFF , 0xFF , 0xFF , 0x3F , 0x0F , 0x00 , 0x00 , 0x00
},{
0x00 , 0x00 , 0x00 , 0x01 , 0x03 , 0x07 , 0x0F , 0x0F,
0x1F , 0x1F , 0x1F , 0x1F , 0x0F , 0x0F , 0x0F , 0x07,
0x03 , 0x01 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00
}},

Wyświetlenie znaku z tablicy odbywa się za pomocą wywołania funkcji LCD_WriteChar(). W argumentach należy podać pozycję znaku w tablicy oraz numery wiersza i kolumny (początek rysowania znaku). Ciało funkcji przedstawiono na list. 4.

List. 4. Funkcja rysująca na LCD duże cyfry

void LCD_WriteChar (unsigned 
char ch, unsigned char col, unsigned char row)
{
    unsigned char i, j;

    if(ch == 'o')
        ch = 10;
    else
        ch = ch & 0x0f;

    for(i=0;i<5;i++)
    {
        LCD_GotoXY (col, row+i);

        for(j=0; j<24; j++)
        {
            lcd_buffer[cursor_row][cursor_col + j] |=  number[ch][i][j];
            LCD_WriteData(lcd_buffer[cursor_row][cursor_col + j]);
        }
    }
}

 

Spojrzenie na całość

Po zakończeniu konfiguracji mikrokontroler przystępuje do wykonywania pętli while, przedstawionej na list. 5. Wynik pomiaru temperatury po obliczeniach jest przechowywany w zmiennej globalnej temp_a, jest to aktualna wartość temperatury zmierzonej przez czujnik ulokowany w strukturze mikrokontrolera.

List. 5. Główna pętla programu

 

while(1)
{
    // Odczyt temperatury + obliczenia
    temp_a = (1430 - ADCVal[0]*0.805) / 4.3 + 25;
    // Obliczenie sredniej z 256 pomiarow
    for(avg_cnt=0; avg_cnt>= 8;

    // Jesli temperatura sie zmienila
    if(temp_a != temp_p)
    {
        // Zapisanie wynikow pomiarow do tablic znakow
        sprintf(temp_tab, "%d", temp_a);

        LCD_Clear ();
        LCD_WriteChar('o', 53, 1); // Znak st C
        LCD_WriteChar(temp_tab[0], 5, 1);
        LCD_WriteChar(temp_tab[1], 29, 1);
        temp_p = temp_a;
    }
}

Dla poprawienia dokładności pomiarów obliczana jest średnia arytmetyczna wyników kolejnych 256 pomiarów. Następnie mikrokontroler sprawdza, czy od ostatniej aktualizacji zawartości wyświetlacza temperatura zmieniła się. Jeśli tak, to zawartość wyświetlacza LCD jest aktualizowana, a wartość aktualnej temperatury jest archiwizowana w zmiennej temp_p.