Začínám s STM32L Discovery kit a zkušenosti s TrueSTUDIO

Tak jsem si zakoupil kit a bohužel jsem z toho smutný. Nikdy jsem nezkoušel 32 bit procesory.
Na MCU.cz je návod na kit ale bohužel verze bez displeje a s malinko jiným procesorem.

Prosím pomůže mi někdo a poradí jak začít s Tím TrueSTUDIEM. Jak se třeba deklarují vstupy a výstupy? Nastavení oscilátoru?

Díky všem

:arrow_right: administrator: přejmenováno z "STM32L Discovery kit"

Taky ho mám. Knihovny jsou trochu jiný než u ne-L M3. V TrueStudiu je možnost “najít deklaraci” prvku, na kterym je kurzor. Bez toho by bylo využití knihoven o dost těžší. Tam spoustu věcí najděš.

Tohle je blikátko jesli se dobře pamatuju.
kitL_mcuOnly.zip (512 KB)

Moc děkuji prokoukám a snad se mi podaří udělat pokrok :smiley:

Kdyby se ti pak u něčeho nedařila práce s “peripheral driver library”, tak se neostýchej a zkus to klidně ručně (postaru: PDF, registry a hurá :slight_smile:). Včera jsem bojoval víc jak půl dne s SPI a stejně jsem ho nerozjel. Dneska jsem vzal DS a za hodinu to z toho lítalo. Konfigurace bylo oproti driver lib poloviční. Za další hodinu pak DMA. To už šlo přes driver lib vpohodě. Teda až poté, co jsem si všiml, že jsem sice řadič nakonfiguroval, ale nezapnul :smiley:.

Tak to jsou pro mě ještě hodně vzdálené věci. Já zatím bojuju se základem jako rozsvěcení ledek a konfigurování pinů na vstup a výstu.
Musím se v tom vubec trochu zorientovat a hlavně si to dát trochu v hlave dokupy jak to funguje. Oproti 8 bitu toho je o dost výc nebo jse mi to alespoň tak jeví.
A k tomu ještě ta angličtina :cry: no snad se do toho dostanu.

To co jsi mi poslal a konečně se mi pojedlo spojit kit a atollic a poslat mak kod a i odkrokovat.
Ještě zatím jechápu proč ta modrá se rozliká sama když se nenastavuje?

Timer4, bylo tam snad CTC a negace pinu při compare match.

mcu.cz/comment-n2884.html tady je celý seriál článků na tento kit teda jestli je to ono.

Stačí si přečíst první příspěvek a zjistíš, že není.
STM32L není STM32VL. Rozdíly sice nejsou nijak extrémní, ale jsou.

Omlouvám se Pityy, měl jsem rodinné problémy tak jsem se k učení nedostal. Ale Teď už mám čas, prosím je ještě ochota mi pomoci?

Já to vidím tak že programování 32bProcesorů se asi dělá úplně jinak než jsem zviklí z 8bProcesorů.

Celý program:

[code]
#include <stddef.h>
//#include “stm32l1xx.h”
#include “defs.h”
#include “delay.h”
#include “systick.h”

/volatile int32_t sysInterval;
RCC_ClocksTypeDef clocks;
/
void sysTickService(void);
//void sysTickInit(void); // initializes system timer to 1ms overflow
void rccInit(void);
void gpioInit(void);
void tim4Init(void);
/void sysTickInit(void);
void intervalDec(void);
void delayMs(int32_t time);
/

int main(void)
{
int i = 0;

/*!< At this stage the microcontroller clock setting is already configured,
 this is done through SystemInit() function which is called from startup
 file (startup_stm32l1xx_md.s) before to branch to application main.
 To reconfigure the default setting of SystemInit() function, refer to
 system_stm32l1xx.c file
 */
// 2Mz int. RC

gpioInit();

tim4Init();

sysTickInit(&sysTickService);

RCC_ClocksTypeDef clks;
RCC_GetClocksFreq(&clks);

// Default systick clk source is HCLK/1
// SysTick_CLKSourceConfig makes no changes.
// Systick timer works withouth prescaller
// (Diode using it is 8x faster)
//SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8);
//SysTick_Config(clks.HCLK_Frequency / 8000);

// work correctly
SysTick_Config(clks.HCLK_Frequency / 8000);
SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8);


//rccInit();
//delayMs(500);

/* Infinite loop */
while (1)
{
	i++;

	delayMs(500);
	IO_NEG(LD_PORT, LD_GREEN);
	IO_NEG(LD_PORT, LD_BLUE);

}
return 0;

}

void gpioInit(void)
{
// enable io clock
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOB | RCC_AHBPeriph_GPIOA, ENABLE);

GPIO_InitTypeDef initStr;
initStr.GPIO_Pin = LD_GREEN;// | LD_BLUE;
initStr.GPIO_Mode = GPIO_Mode_OUT;
initStr.GPIO_OType = GPIO_OType_PP;
initStr.GPIO_PuPd = GPIO_PuPd_NOPULL;
initStr.GPIO_Speed = GPIO_Speed_10MHz;
GPIO_Init(LD_PORT, &initStr);
IO_HIGH(LD_PORT,LD_GREEN);
//IO_LOW(LD_PORT,LD_BLUE);

initStr.GPIO_Pin = BT;
initStr.GPIO_Mode = GPIO_Mode_IN;
//initStr.GPIO_OType = GPIO_OType_PP;
initStr.GPIO_PuPd = GPIO_PuPd_NOPULL;
initStr.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_Init(BT_PORT, &initStr);

/*GPIOA->MODER = 0;			// mode: IN/OUT/ALT/ANA
 GPIOA->OTYPER = 0;			// O type: PP/OD
 GPIOA->OSPEEDR = 0;		// O speed: 400k/2m/10m/40m
 GPIOA->PUPDR = 0;			// pull: none/up/down/reserved
 GPIOA->IDR;				// input
 GPIOA->ODR = 0;			// output
 GPIOA->BSRRL = 0;			// bSet
 GPIOA->BSRRH = 0;			// bReset
 GPIOA->LCKR = 0;			// lock
 GPIOA->AFR[0] = 0;			// AF[b7:0]
 GPIOA->AFR[1] = 0;			// AF[b15:8]
 */

}

void rccInit(void)
{
//
RCC_HSICmd(ENABLE);

FLASH_ReadAccess64Cmd(ENABLE);
// can be check that 64-bit access is taken into account by reading FLASH_ACR here
FLASH_SetLatency(FLASH_Latency_1);
// can be check that the new number of WS is taken into account by reading FLASH_ACR here
FLASH_PrefetchBufferCmd(ENABLE);
while (RESET == RCC_GetFlagStatus(RCC_FLAG_HSIRDY))
	; // wait for HSI startup
RCC_HCLKConfig(RCC_SYSCLK_Div4); // Clk/4
RCC_SYSCLKConfig(RCC_SYSCLKSource_HSI); // 16MHz
// final: 4MHz
SystemCoreClockUpdate();

}

void tim4Init(void)
{

RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE); // tim4 clk enable


TIM_TimeBaseInitTypeDef tBinit;
tBinit.TIM_ClockDivision = TIM_CKD_DIV1;
tBinit.TIM_CounterMode = TIM_CounterMode_Down;
tBinit.TIM_Period = 99;
tBinit.TIM_Prescaler = 9999;
TIM_TimeBaseInit(TIM4, &tBinit);

TIM_OCInitTypeDef tOinit;
tOinit.TIM_OCMode = TIM_OCMode_Toggle;
tOinit.TIM_OCPolarity = TIM_OCPolarity_High;
tOinit.TIM_OutputState = TIM_OutputState_Enable;
tOinit.TIM_Pulse = 0;		// OC event on timer reset
TIM_OC1Init(TIM4, &tOinit);

//TIM_SetCounter(TIM4, 99);
TIM_Cmd(TIM4, ENABLE);

// pin config
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOB, ENABLE);
GPIO_InitTypeDef initStr;
initStr.GPIO_Pin = LD_BLUE;
initStr.GPIO_Mode = GPIO_Mode_AF;
initStr.GPIO_OType = GPIO_OType_PP;
initStr.GPIO_PuPd = GPIO_PuPd_NOPULL;
initStr.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_Init(LD_PORT, &initStr);
GPIO_PinAFConfig(LD_PORT, GPIO_PinSource6, GPIO_AF_TIM4);

}

void sysTickService(void)
{
//
#ifdef DELAY_H_
delayIntervalDec();
#endif

}[/code]

Jestli to dobře chápu tak třeba toto je definice vstupu a vystupů:

[code]GPIO_InitTypeDef initStr;
initStr.GPIO_Pin = LD_GREEN;// | LD_BLUE;
initStr.GPIO_Mode = GPIO_Mode_OUT;
initStr.GPIO_OType = GPIO_OType_PP;
initStr.GPIO_PuPd = GPIO_PuPd_NOPULL;
initStr.GPIO_Speed = GPIO_Speed_10MHz;
GPIO_Init(LD_PORT, &initStr);
IO_HIGH(LD_PORT,LD_GREEN);
//IO_LOW(LD_PORT,LD_BLUE);

initStr.GPIO_Pin = BT;
initStr.GPIO_Mode = GPIO_Mode_IN;
//initStr.GPIO_OType = GPIO_OType_PP;
initStr.GPIO_PuPd = GPIO_PuPd_NOPULL;
initStr.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_Init(BT_PORT, &initStr);[/code]

Kde LD_GREN je zelená LED
LD_BLUE je modrá, ale ta je za // takže není definovaná
potom BT je vstup je to tlacitko USER

Prosím rozumím tomu dobře?

Dále jsem chtěl dát podmínku např při stisknutí tlačítka, že zelená led bude blikat pomaleji:

[code]if((GPIOA->IDR & BT) != 0x0)
{
delayMs(5000);
IO_NEG(LD_PORT, LD_GREEN);
}
else
{
delayMs(500);
IO_NEG(LD_PORT, LD_GREEN);
IO_NEG(LD_PORT, LD_BLUE);

}[/code]

Ale právě to už mi při krokování nefunfuje? Nevím kde je chyba

Definice IO - správně.
Proč nefunguje tlačítko nevidím. Používám na to sice makro, ale definované ho mám stejně jako to máš napsané. Bohužel kity mám v práci kde dnes nejsem a na tomto L-kitu mi odešel stabilizátor, takže je momentálně nefunkční. Pošlu ti pokus s tlačítkem.
Využívej funkce IDE a koukej se na definice těch věcí. Když si třeba najdeš definici “GPIO_Init(x, x);” zjistíš, že se to od 8-bitů moc neliší. Je tam registrů víc, ale stále je to jen zapisování jedniček a nul do registrů periferií. Rozdíl je pouze v tom, že pro přístup k jednotlivým registrům nevyužíváš samostatná jména, ale strukturu. Pomocí ní se dostaneš na adresu celé periferie a pak pomocí tečky (nebo šipky v případě pointeru) přistupuješ k jednotlivým registrům. Trochu nepříjemné je, že přesné názvy struktur musíš často hledat v definičním souboru mcu, protože v datasheetu je každý registr pojmenován zvlášť, kdežto pak v C jsou seskupeny do oněch struktur. To se však dá překousnout.
_3_kitL.zip (512 KB)

Tak něco jsem pochopil a něco ne.
Už jsem si dokázal definovat třeba PINB8 jako bit

// PINB8 vystup led initStr.GPIO_Pin = GPIO_Pin_8; initStr.GPIO_Mode = GPIO_Mode_OUT; initStr.GPIO_OType = GPIO_OType_PP; initStr.GPIO_PuPd = GPIO_PuPd_NOPULL; initStr.GPIO_Speed = GPIO_Speed_10MHz; GPIO_Init(GPIOB, &initStr);

A jak bych měl definovat kdybych chtěl definovat cely byte?

Podmínka if jak jste mi poslal mi funguje AKORÁT JAK TO JE DEKLAROVANE TOMU NEROZUMIM

[code]if (IO_TST(BT_PORT, BT))
{

			IO_HIGH(LD_PORT, LD_GREEN);
			IO_HIGH(GPIOB, GPIO_Pin_8);
	}
			else{
	IO_LOW(LD_PORT, LD_GREEN);
	IO_LOW(GPIOB, GPIO_Pin_8);


}[/code]

IO_TST … znamena nevim?

Prosim to že to nemužete odzkoušet vůbec nevadí. Já to budu zkoušet na mém a alespoň třeba tak i na něco málo přijdu sám.
Moc rád bych to pochopil jak programovat tento procesor a jemu podobné

IO_TST(BT_PORT, BT) je funkce, která tesuje bit BT(PA0) portuBT_PORT (GPIOA) , která vrací hodnotu 0, nebo 1

BT_PORT a BT jsou definované v souboru defs.h

#define BT_PORT GPIOA
#define BT (1<<0) // PA0

Ano něco takového jsem si myslel. Ale kde jste to zjistili?
Určitě takových instrukcí je kupa na všelicos možného.

To nejsou instrukce(ani funkce), ale makra, který jsem si napsal. Lou je správně našel v souboru defs.h.
Stejný makra (s jinýma registrama) se používají i na 8bitech.
Jak jsem psal - IDE umí najít definici označeného textu (pravý tlačítko, go to definition nebo tak něco). Když něco neznáš, zkus si to takhle najít a podívat se, co to dělá.

“A jak bych měl definovat kdybych chtěl definovat cely byte?”
=> kdzž si postupem zmíněným výše najdeš co je schováno pod “GPIO_Pin_8” zjistíš, že je to jen jednička na pozici 8. bitu. Jak definovat byte? Dej tedy jedničky na 8 bitů. Místo “GPIO_Pin_8” můžeš napsat “0xFF” nebo “GPIO_Pin_8 | GPIO_Pin_7 | GPIO_Pin_6…” (mimochodem - tady jsou porty 16b).

Aha tak tím že je to makro tak se to vysvětluje, asi už maličko tomu začínám porozumět.

A když chci programovat tedy bez maker. A chci udělat podmínku stisknutí tlačítka na PORTA.0 - tl. USER

nadefinuji si PORTA.0 jako vstup:

// vstup tlacitko USER initStr.GPIO_Pin = GPIO_Pin_0; initStr.GPIO_Mode = GPIO_Mode_IN; initStr.GPIO_PuPd = GPIO_PuPd_NOPULL; initStr.GPIO_Speed = GPIO_Speed_2MHz; GPIO_Init(GPIOA, &initStr);

a teď nevím jak zapsat tu podmínku u 8bit např ATMEGA to píši takto:

if( PINA.B0 == 1)

Zkusil jsem napsat tuto, ale je to blbost určitě protože to nefunguje

if( (GPIOA, GPIO_Pin_0) == 1)

Makro není nic jiného než pojmenovaný kus kódu. Stačí si to z toho souboru defs.h přečíst když ty makra nechceš používat. Zrovna v tomto případě bych u nich ovšem zůstal (můžeš si je zkopírovat do svého souboru a nemusíš mít samostatný). Kdybys totiž přešel na ne-L procesor, stačilo by změnit 1 makro a všechno pracuje dál (ikdyž zrovna tesstovací makro zůstává shodné). Na builderu je seriál o C. Tam si o makrech můžeš něco přečíst.

z toho je tedy zřejmý kód: if((GPIOA->IDR) & GPIO_Pin_0) {}

I GPIOA je jen uživatelská definice - skrývá se pod ní skutečná adresa registru stejně jako PORTA u AVRka.

Já osobně se snažím odpoutat od stylu práce naučeném na 8mibitech a příjmout pravidla nastavená STM - mají v knihovnách prakticky všechno co potřebuješ - nic nemusíš vymýšlet - stačí hledat to co potřebuješ - začátečník jako tyn nebo já tam určitě vždycky najde.

Takže když potřebuješ něco co se týká I/O portů tak se podíváš do souboru stm32l1xx_gpio.c a tam najdeš třeba funkci pro čtení stavu bitu příslušného portu:

[code]uint8_t GPIO_ReadInputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)
{
uint8_t bitstatus = 0x00;

/* Check the parameters */
assert_param(IS_GPIO_ALL_PERIPH(GPIOx));
assert_param(IS_GET_GPIO_PIN(GPIO_Pin));

if ((GPIOx->IDR & GPIO_Pin) != (uint32_t)Bit_RESET)
{
bitstatus = (uint8_t)Bit_SET;
}
else
{
bitstatus = (uint8_t)Bit_RESET;
}
return bitstatus;
}[/code]

takže dotaz na stav vstupu můžeš použít buď přímo tuto funkci, nebo z ní vyčíst jak se to dělá - příslušnou část jsem zvýraznil.

pak by tvůj případ vypadal takto:

if ((GPIOA->IDR & GPIO_Pin_0) != 0)

mně taky od začátku strašně vadil ten způsob zápisu - třeba:

/* Configure Output for LCD */ /* Port A */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_8 | GPIO_Pin_9 |GPIO_Pin_10 |GPIO_Pin_15; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; GPIO_Init( GPIOA, &GPIO_InitStructure);

místo PORTA=0x870E;

mimochodem zápis GPIOA->IDR =0x870E; je taky možný, ale v tom by se nevyznalo ani prase, natož autor.

Ale asi je to potřeba.

Nj tak touhle uvahou musim tedy souhlasit že makra nebudou vůbec špatná. Budu se tedi učit
a DĚKUJI!

Abych nevypadal že se opakuju - než jsem odeslal příspěvek tak už tam byl ten piityyho :slight_smile: .

Diky i tobě lou, jsem moc rád za každou pomoc a vysvětlení každeho kousku kódu