Novinka:Začínáme s STM32 VL Discovery kitem 7
(Kategorie: Mikroprocesory)
Napsal mard
12.10.2010 00:00

V tomto dílu dokončíme začátečnický úvod do používání TrueSTUDIO ve spojení s STM32 VL Discovery kitem, ukážeme si ladění a další podrobnosti. Odladíme si tedy první demoprogram z minulého dílu a odstraníme jeho chyby.

Ladění

V minulém dílu (6) jsme skončili u ladění, při kterém jsme nic neladili, pouze jsme jej využili k nahrání přeloženého programu do flash paměti ARM mcu na VL Discovery kitu, abychom viděli zda skutečně začnou LEDky blikat.

LEDky skutečně blikaly, ale záměr programu, aby blikala modrá LED4 stále a zelená LED3 se rozsvítila, jen když stiskneme modré tlačítko na kitu, se nenaplnil. Obě LED blikají stále. Takže se musíme podívat, kde máme chybu. Dle popisu v minulém dílu se opět dostaneme do stavu TrueSTUDIO odpovídající ladění programu. V prostřední části obrazovky je vypsán program main.c a text "GPIO_Inicializace();", což je řádka 29 programu, je vysvícen světle zeleně - to nám ukazuje, kde je zastaveno provádění programu. LED zatím neblikají, protože jsme zatím nestiskli ikonu Resume pro spuštění programu.

Podívejme se na ikony pro ovládání běhu programu podrobněji.



Obrázek odpovídá části menu, pod položkou Run. Ale pochopitelně, že je jednodušší kliknout přímo na příslušnou ikonku, kterou máme hned nad oknem Debug, které je vlevo nahoře (nad oknem ve kterém se vypisuje část programu, kterou zrovna mcu provádí a kde je nyní vypsán program main.c).
V minulém dílu jsme klikli na Resume a program se začal provádět. Nyní zkusme jednotlivé části vykonávat postupně. Používáme k tomu ikony Step Into a Step Over.

Step Into - při ladění vstoupí ladění dovnitř (pokud to jde) vykonávaného příkazu. Tj. pokud stiskneme tuto ikonu v současném stavu, tak se nám ukáže první příkaz funkce GPIO_Inicializace(). Postupným použitím této ikony se dostaneme skutečně hluboko do prováděného příkazu, takže se můžete přesvědčit jak se vykoná daný příkaz, který je voláním knihovní funkce.
Step Over - ladicí program vykoná celý daný příkaz a skočí na další příkaz v programu. Tj. pokud stiskneme tuto ikonu v současném stavu, tak se vykoná celá funkce GPIO_Inicializace() a ladění se pak přesune na další příkaz v pořadí - zde na řádku č. 32.

Pokud se chcete vrátit s laděním opět na začátek, využijete ikonu Restart (to uvádím pro případ, že jste hned vyzkoušeli Step Into a nyní jste někde v hlubinách přeloženého programu ).

Při ladění můžeme nastavit zarážku pro běh programu - Breakpoint. Pokud spustíte provádění programu pomocí Resume, tak se provádění na místě, kde je Breakpoint zastaví. Nastavíme jej tak, že klikneme pravým tlačítkem myši na čísle řádku kde jej chceme nastavit a z menu vybereme Toggle Breakpoint (nebo jednodušeji dvojklikem na čísle řádku). Nastavený Breakpoint se nám hned ukáže v seznamu Breakpointů, který je vpravo nahoře na záložce Breakpoints.

Často využijete i vedlejší záložku Variables, kam můžete sledovat proměnnou, jejíž hodnotu potřebujete znát. Pokud při ladění našeho demoprogramu pomocí Step Into vstoupíte do vykonávání funkce Delay, tak se vám v záložce Variables na první řádce objeví nTick a vedle i aktuální hodnota (349525). Jistě sami objevíte že po kliknutím pravým tlačítkem na této proměnné, můžete třeba změnit její hodnotu.


Praktický příklad


Odladíme tedy, proč nám program chodí jinak, než jsme předpokládali. Stiskneme ikonu Restart, abychom se dostali s laděním na začátek, pokud jste něco zkoušeli a pomocí ikony Step Over začneme krokovat program.
Řádka 29: GPIO_Inicializace(); se vykoná tak jak předpokládáme. Nic se opticky nezmění, ani modrá ani zelená LED nesvítí.
Řádka 32: STM32_Discovery_LEDOff(LED4), se vykoná jak předpokládáme, nic nesvítí.
Řádka 33: Delay(0x55555); V pořádku, čekání se vykoná, nic se nezmění.
Řádka 34: STM32_Discovery_LEDToggle(LED4); se vykoná jak předpokládáme - rozsvítí se modrá LED.
Řádka 35: Delay(0x55555); V pořádku, čekání se vykoná, nic se nezmění.
Řádka 37: if(0 == STM32_Discovery_PBGetState(BUTTON_USER)). Načte se hodnota tlačítka, které není stisknuto.
Nyní se provádění dostane na řádku 40. Což je jinam, než předpokládáme. Je zřejmé, že když tlačítko není stisknuto, tak je výsledkem funkce STM32_Discovery_PBGetState hodnota 0. Tedy musíme zaměnit buď porovnání například na if(0 != STM32_Discovery_PBGetState(BUTTON_USER)), nebo musíme prohodit příkazy Zapnem/Vypnem LED. Pochopitelně jednodušší bude první způsob. Ale pokračujme v ladění dále.
Řádka 40: STM32_Discovery_LEDToggle(LED3); se vykoná jak předpokládáme - rozsvítí se zelená LED.
nyní se vrátíme na začátek cyklu, na řádku 32.
Řádka 32: STM32_Discovery_LEDOff(LED4), se vykoná jak předpokládáme, nic nesvítí.
Řádka 33: Delay(0x55555); V pořádku, čekání se vykoná, nic se nezmění.
Řádka 34: STM32_Discovery_LEDToggle(LED4); se vykoná jak předpokládáme - rozsvítí se modrá LED.
Řádka 35: Delay(0x55555); V pořádku, čekání se vykoná, nic se nezmění.
Řádka 37: if(0 == STM32_Discovery_PBGetState(BUTTON_USER)). Načte se hodnota tlačítka, které není stisknuto.
Řádka 40: STM32_Discovery_LEDToggle(LED3); se vykoná jinak než předpokládáme - zelená LED zhasne!
Takže teď je zřejmé, proč program chodí jinak, než jsme předpokládali. příkaz LEDToggle nezpůsobí rozsvícení LED, ale pouze přepnutí z jednoho stavu do druhého. Takže program musíme opravit. Ukončíme ladění stiskem ikony červeného čtverečku (Terminate) a dostaneme se zpět do editace.

Změníme obsah if podmínky a LEDToggle změníme v druhém případě na LEDOn a navíc změníme blikání na trochu pomalejší. Ale abychom nemuseli měnit stále hodnoty všech volání Delay, tak si nadefinujeme parametr DELKA. Výsledná verze main.c je pak následující:

/*
* GPIO 2. dil LED blink/main.c
* Odladene spravne blikani
* <a href="http://mcu.cz"  rel="external">odkaz</a>
* Mard 2010/10/09 ver. 1.1
*/


/* Includes ------------------------------------------------------------------*/
#include <stddef.h>#include "stm32f10x.h"
#include "STM32_Discovery.h"
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
#define DELKA 0xAAAAA
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/

void GPIO_Inicializace(void); // nastavení vstupne/vystupnich pinu na kitu
void Delay(__IO uint32_t nTick);

/* Private functions ---------------------------------------------------------*/

/**
  * @brief  Main program.
  * @param  None
  * @retval : None
  */

int main(void)
{
  GPIO_Inicializace();
  while (1)
  {
    STM32_Discovery_LEDOff(LED4);     // vypnem LED4 - modra
    Delay(DELKA);
    STM32_Discovery_LEDToggle(LED4); // zapnem LED4 - modra
    Delay(DELKA);

    if(0 != STM32_Discovery_PBGetState(BUTTON_USER))
    {
      // tj. když je stisknuto tlacitko
      STM32_Discovery_LEDOn(LED3); // zapnem LED3 - zelena
    }
    else
    {
      // tj. když není stisknuto tlacitko
      STM32_Discovery_LEDOff(LED3);   // vypnem LED3 - zelena
    }
  }
}

/**
  * @brief  Configure the GPIO Pins.
  * @param  None
  * @retval : None
  */

void GPIO_Inicializace(void)
{
  STM32_Discovery_LEDInit(LED3);
  STM32_Discovery_LEDInit(LED4);
  STM32_Discovery_PBInit(BUTTON_USER, BUTTON_MODE_GPIO);
  STM32_Discovery_LEDOff(LED3);
  STM32_Discovery_LEDOff(LED4);
}

/**
  * @brief  Cekani
  * @param nTick: delka cekaci smycky
  * @retval : None
  */

void Delay(__IO uint32_t nTick)
{
  for(; nTick != 0; nTick--);
}



Rozdělení programu

Pokud bychom chtěli funkci Delay použít i v jiných programech, které bychom někdy v budoucnu napsali, tak bychom do všech programů museli její deklaraci nakopírovat. Což je otravné a navíc, pokud bychom v budoucnu objevili nějakou chybu v definici funkce, tak bychom museli opravit veškeré programu, kde by se tato deklarace nacházela. Je proto výhodnější mít jeden extra soubor, kam tuto funkci přesuneme a pak už jí můžeme v budoucnu používat snáze. Pochopitelně použití Delay je jen příklad, obecně bychom takto měli postupovat i jindy, například když si vytvoříme funkce pro komunikaci s LCD, atd.
Vytvoříme soubor delay.c tak, že v Project Exploreru klikneme pravým tlačítkem na adresáři src a zvolíme New a pak Source File. Do souboru přesuneme z konce souboru main.c celou deklaraci funkce Delay(). Dále vytvoříme hlavičkový soubor delay.h (podobně jako výše, jen zvolíme New/Header File) a do tohoto souboru přeneseme prototyp funkce delay z řádky 20 ze souboru main.c!
Nakonec tedy máme v adresáři src dva soubory delay navíc, jeden s koncovkou .c a druhý s .h!

Celý projekt v zazipované podobě je stáhnutelný dle odkazů na konci textu.


Drobnosti na závěr

Nastavení TrueSTUDIO před námi úplně skrylo nějaké podrobnosti o tom, kde je jaká LED nebo tlačítko připojeno. Pro začátečníky je to fajn, že se jim věc nekomplikuje, ale zkušenější uživatelé mohou být nervózní. Proto uvádím připojení:
  • LED3 (zelená) je připojena na pin PC9
  • LED4 (modrá) je připojena na PC8
  • Tlačítko USER je připojeno na PA0

Funkce PA0 kromě GPIO - WakeUP, vstup Timer2 Channel1
Funkce PC8 kromě GPIO - výstup Timer3 Channel3
Funkce PC9 kromě GPIO - výstup Timer3 Channel4


Odkazy

STM32-VL DISCOVERY popis je zde.
STM32-VL Discovery 2. (další popis, osobní poznatky) je zde.
Začínáme s STM32 VL Discovery kitem naleznete zde.
Začínáme s STM32 VL Discovery kitem 2. naleznete zde.
Začínáme s STM32 VL Discovery kitem 3. naleznete zde.
Začínáme s STM32 VL Discovery kitem 4. naleznete zde.
Začínáme s STM32 VL Discovery kitem 5. naleznete zde.
Začínáme s STM32 VL Discovery kitem 6. naleznete zde.
Celý projekt pro tento díl projekt.zip.

Doporučuji se rovněž podívat na QuickStart Guide k TrueSTUDIO (pdf), které najdete zde.



Tato novinka je z -MCU-mikroelektronika
( http://mcu.cz/news.php?extend.2118 )