Difference between revisions of "Programmering STM32"

From Chalmers Robotförening
Line 74: Line 74:
===Logikanalysator===
===Logikanalysator===
Denna är helt ovärderlig vid felsökning av kommunikationsprotokoll. Om du setat mer än 5 minuter med ditt problem med UART/SPI så hämta logikanalysatorn och koppla upp den. Det tar inte många minuter och löser oftast ditt problem. Den är mycket enkelt att få igång. Mer info finns [http://www.saleae.com/ här.] Annars är oscilloskopet din vän. Samma där, det tar inte lång tid att ta fram och sätta upp det.
Denna är helt ovärderlig vid felsökning av kommunikationsprotokoll. Om du setat mer än 5 minuter med ditt problem med UART/SPI så hämta logikanalysatorn och koppla upp den. Det tar inte många minuter och löser oftast ditt problem. Den är mycket enkelt att få igång. Mer info finns [http://www.saleae.com/ här.] Annars är oscilloskopet din vän. Samma där, det tar inte lång tid att ta fram och sätta upp det.
===Min timer dummar sig och sätter sig inte till korrekt idle-värde===
P.g.a att ST har gjort fel i sitt bibliotek fungerar inte TIM15 kanal2. De extrafunktioner som har med break att göra (t.ex. idle state) är inte korrekt gjorda. I funktionen TIM_OC2Init i stm32f10x_tim.c ska du lägga till TIMx==TIM15 i if-satsen för att tillåta att de avancerade funktionerna kan användas. Det ska se ut som "if((TIMx == TIM1) || (TIMx == TIM8) || (TIMx == TIM15))"


==Peripheralexempel==
==Peripheralexempel==

Revision as of 23:29, 21 March 2014

Denna sida är under konstruktion, men kommer att innehålla information om vad man bör tänka på när man programmerar STM32 (och delvis generellt ARM). Notera att denna sida endast handlar om att skriva kod, inte om hur man får programmet att bygga osv. Detta tas upp i artiklarna Förberedelse programmering STM32 och Byggprocess ARM

Tillvägagångssätt för programmering

Innan du kan sätta och och börja koda för STM32 behöver du sätta upp mjukvara för att kunna kompilera koden. Ifall du inte har gjort det, läs Förberedelser för programmering av STM32.

Dokumentation för STM32

Här är en länk till STs standardlib (det är svårare att hitta än man kan tro...). dessa dokument vill du ladda hem, och läsa i för att förstå hur just den funktion du vill ha fungerar. reference sheet datasheet disovery board datasheet

Tips om Eclipse

Filstruktur i projekt

i src lägger du koden du skriver, som slutar på .c

i lib finns bibliotek, främst stdlib från ST, men du kan även ta hem andra bibliotek i framtiden

i inc lägger du alla .h filer

makefile är den fil som läses av programmet make varje gång du trycker på kompilera i Eclipse. Det är ungefär som en göralista som styr vad som ska utföras av make, för att alla filer ska kompileras, allt ska länkas etc. Den skriver du antingen sjläv (baserat på en existerande såklart) eller så låter du Eclipse generera den åt dig.

Här behöver du lägga till nya filer du skriver under SRC, annars kommer inte make ta med dem i kompileringen

kompilera i eclipse

skicka över med st-link program

Testprogram för introARM

Debugging

Blinka med LEDs och UART.

Skriva C-kod

Grunderna

Är du ny? Läs lite i C-bok eller läs exempelkod! Här ska massa länkar till bra material Att lära sig C programmering finnas

skriva kod för stm32

processorer med en ARM kärna skiljer sig från microprocessorer från Atmel och PIC i grund och botten i att .... kärna från arm, periferienheter från ST

Structer

Man skriver inte i register, utan man använder ett abstraheringslager, stdlib, med funktioner och structer etc så bör man inte ändra direkt i register

Klockor

finns en uppsjö av klockor i STM32, se "karta"(?)

Exempelkod

för introARM / discovery board gpio uart timer interrupt

Programmering

Som alla vet programmerar man i C.

Felsökning

Om du setat länge med ett problem finns det några standardmisstag om man brukar göra. Kolla igenom följande checklista så kanske du hittar ditt problem:

Har du givit klocka till peripheral?

Alla peripherals måste ha klocka. Det första man bör gör när man initar någonting peripheral är att anropa funktionen RCC_APBxPeriphClockCmd(RCC_APBxPeriph_PPPPP,ENABLE) där x är den buss din peripheral sitter på och RCC_APBxPeriph_PPPPP är makrot för den peripheral du ska slå igång. Det finns även för RCC_AHB-bussen också. GPIO sitter på APB2 exempelvis. Notera att alla moduler som är inblandade ska ha klocka. Exempelvis om du ska göra PWM så måste du ge klocka både till GPIO, GPIO_AF och timern.

Är du säker på att det är rätt pinne? Har du skrivit rätt Port-namn i koden?

Har du kopplat alternate function till pinnen?

AF till pinnen kopplas med funktionen GPIO_PinAFConfig(GPIO_PORT,GPIO_PinSource,GPIO_AF). Info finns i filen GPIO.c.

Har du kört din init-funktion?

Nej, det har du inte. Kolla igen.

Har du enablat din peripheral?

Detta gör man med Periph_CMD(Enable) (t.ex. TIM_Cmd(TIMx,ENABLE), SPI_Cmd(SPIx,ENABLE) eller USART_Cmd(USARTx,ENABLE)).

Min PWM funkar inte!

Notera att för vissa timers (TIM1, TIM8, TIM15-17 på STM32F1xx och endast TIM1,8 på F4) så måste man anropa en extra funktion som sätter igång PWM. Detta görs med funktionen TIM_CtrlPWMOutputs(TIMx,ENABLE). Denna funktion kan också användas för att stänga av PWM på pinnen (vilket kan vara smidigt ibland)

Min pinne funkar inte!

Är din pinne PB3, PB4, PA13, PA14 eller PA15? Detta är JTAG/SWD-pinnarna och dom är som standard denna funktion och INTE GPIO. Dessa måste remappas innan dom kan användas som GPIO. Detta görs med funktionen GPIO_PinRemapConfig(GPIO_Remap_SWJ_xxx,ENABLE), där xxx finns som följande options: NoJRST som låser upp PB4, JTAGDisable som låser upp PB3, PB4 och PA15 samt Disable som låser upp alla pinnar (ja, det ser skumt ut när man anropar GPIO_PinRemapConfig(GPIO_Remap_SWJ_Disable,ENABLE), men det är korrekt). Notera att på STM32F4xx så finns det ingen remap alls. Där sköts detta enbart via AF-controllern (men man måste fortfarande välja GPIO som AF i STM32F4xx).

Den hänger sig i interrupt!

Det finns många saker som kan bli fel på interrupt. Det vanligaste är:

  • Inte korrekt initad interruptvektor. Du måste ha den funktion som svarar mot din interruptvektor (där du hamnar vid interrupt). Dessa står i startup-filen (.s-filen). Dessa har typiskt formatet void PERIPH_Handler(){ do_interrupt_stuff } där PERIPH är den peripheral du har.
  • Har du kvitterat (clearat) ditt interrupt? Detta bör göras så tidigt som möjligt i interruptet (men kan göras senare vid avancerade applikationer). Det finns inbyggda funktioner för detta. För external interrupt (pinne som ger interrupt) heter den EXTI_ClearItPendingBit(EXTI_Linex), där x är vilket nummer.
  • För vissa interrupt måste du också läsa av interruptkällan (typiskt interrupts som flera källor kan trigga, exempelvis EXTI_Line som kan triggas av flera pinnar)

De_init-funktionen

Många peripherals (t.ex. DMA och I2C) har en de_init-funktion. Den bör man köra innan man initierar peripheralen, annars finns det risk att den inte fungerar.

Logikanalysator

Denna är helt ovärderlig vid felsökning av kommunikationsprotokoll. Om du setat mer än 5 minuter med ditt problem med UART/SPI så hämta logikanalysatorn och koppla upp den. Det tar inte många minuter och löser oftast ditt problem. Den är mycket enkelt att få igång. Mer info finns här. Annars är oscilloskopet din vän. Samma där, det tar inte lång tid att ta fram och sätta upp det.

Min timer dummar sig och sätter sig inte till korrekt idle-värde

P.g.a att ST har gjort fel i sitt bibliotek fungerar inte TIM15 kanal2. De extrafunktioner som har med break att göra (t.ex. idle state) är inte korrekt gjorda. I funktionen TIM_OC2Init i stm32f10x_tim.c ska du lägga till TIMx==TIM15 i if-satsen för att tillåta att de avancerade funktionerna kan användas. Det ska se ut som "if((TIMx == TIM1) || (TIMx == TIM8) || (TIMx == TIM15))"

Peripheralexempel

Med i libbet kommer det massa exempel som är ganska bra och tar upp det mesta. Här följer några skräddassydda och bättre förklarade exempel.

GPIO

Med interrupt

Timer

PWM

UART

Modeller

Det finns massa olika modeller.


Länkar

Vart hittar man datablad? Vart hittar man libbet? Vart köper man dom?