Näää, vadå? Ingen lokal!
Hur som helst. Jag tänkte skriva en liten metodik hur jag gör för att sätta register. Notera jag har aldrig satt dessa register förut, så jag bara antar att det är så här för att man gör väll likadant i AVR så som PIC.
Projekt:
Få en LED-lampa att blinka.
Metodik:
För att få en LED-lampa att blinka hos en STM32:a så måste jag först plocka fram en 220 ohm resistor och en liten LED. Nu råkar jag använda ett färdigt utvecklingskort med inbyggt LED-lampa.
Nu vet jag att det finns en pinne som heter PA5 som leder till en resistor och LED-lampa i serie. Så jag måste aktivera PA5 och avaktivera PA5 inom ett visst intervall.
Steg 1:
Nu gissar jag bara. Jag antar att detta är en vedertagen standard: Efter man ha satt rekommenderad spänningsnivå på en uC så ska man gå vidare och titta på den som driver själva instruktionerna hos uC:n. Detta måste väll vara oscillatorn som ska driva en fyrkantsvåg/sinusvåg till övriga periferierna hos processorn. Oscillatorn drivs av en kristall. Rätta mig om jag har fel.
Hur som helst! För att veta vilken oscillator jag ska aktivera som ska driva min PA5 pinne, då måste jag titta i referensmanualen. Jag misstänker att man ska kolla blockschemat efter vad som driver GPIO-pinnarnas instruktioner. Jag misstänker att det är
AHB som jag måste titta på för att det står
core. Då antar jag att det är det mest grundläggande periferierna.
Skärmbild 2024-02-22 183837.png
Jag tror jag hittade rätt. Noter att jag har aldrig gjort detta förut. Jag mest bara gissar och drar slutsatser att det kanske borde vara så. Men då vet jag att det är AHB1 som jag måste titta vidare på.
Skärmbild 2024-02-22 184427.png
Men först så måste jag sätta registerna! Jag väljer att använda HSE -
High Speed External. Då aktiverar jag den och sedan kollar jag om den är redo.
Skärmbild 2024-02-22 185356.png
Kod: Markera allt
#include <main.h>
int main(){
/* Start the HSE clock */
RCC->CR |= 1 << 16;
/* Check if the HSE clock is ready */
while(!(RCC->CR & 1 << 17));
/* Now is the HSE clock ready */
}
Då var det dags att välja att min processor ska använda HSE som klocka.
Namnlös.png
Kod: Markera allt
#include <main.h>
int main(){
/* Start the HSE clock */
RCC->CR |= 1 << 16;
/* Check if the HSE clock is ready */
while(!(RCC->CR & 1 << 17));
/* Now is the HSE clock ready - Time to select it as system clock */
RCC->CFGR |= 0b01;
/* Check if the HSE clock is selected */
while(!(RCC->CFGR & 0b0100));
}
Efter jag har valt HSE som systemets klocka. Så då är det dags för en skalare. Jag väljer att dividera 8 MHz med 2, med tanke på att kristallen är på 8 MHz. Alltså får jag nu 4 MHz som jag kan driva AHB med.
Namnlös.png
Nu är det dags för aktivera PA5 hög och sedan låg. Jag måste först deklarera vad pinnen ska vara för något. Analog, digital in eller digital ut. Detta känner jag igen sedan min AVR-tid som jag hade på förra sidan
Jag gissar att den MODER5 är PA5.
Skärmbild 2024-02-22 195200.png
Kod: Markera allt
#include <main.h>
int main(){
/* Start the HSE clock */
RCC->CR |= 1 << 16;
/* Check if the HSE clock is ready */
while(!(RCC->CR & 1 << 17));
/* Now is the HSE clock ready - Time to select it as system clock */
RCC->CFGR |= 0b01;
/* Check if the HSE clock is selected */
while(!(RCC->CFGR & 0b0100));
/* Declare PA5 as digital output */
GPIOA->MODER |= 1 << 10;
}
Deklarera att utgången ska vara en push-pull och inte open-drain.
Skärmbild 2024-02-22 195908.png
Så då var det bara ha en while-sats där jag aktiverar, väntar, avaktiverar, väntar. Detta påminner mig lite om en SR-vippa. Set, Reset
Skärmbild 2024-02-22 200205.png
Kod: Markera allt
#include <main.h>
int main(){
/* Start the HSE clock */
RCC->CR |= (1 << 16);
/* Check if the HSE clock is ready */
while(!(RCC->CR & (1 << 17)));
/* Now is the HSE clock ready - Time to select it as system clock */
RCC->CFGR |= 0b01;
/* Check if the HSE clock is selected */
while(!(RCC->CFGR & 0b0100));
/* Declare PA5 as digital output */
GPIOA->MODER |= 0b10000000000;
/* Declare the digital output PA5 as push-pull */
GPIOA->OTYPER |= (0 << 5);
/* Blink - SR latch */
while(1){
/* Set */
GPIOA->BSRR |= (1 << 5);
for(int i = 0; i < 1000; i++){};
/* Reset the set */
GPIOA->BSRR |= (1 << 21);
for(int i = 0; i < 1000; i++){};
}
}
Problemet är att den lyser inte.
Har jag missat något?
Här är ett problem.
GPIOA verkar inte vara aktiverad. Det kan vara klockan som är orsaken?
Skärmbild 2024-02-22 203645.png
Edit:
Jag glömde att aktivera GPIOA för AHB1.
Så nu fungerar det!
Jag har inte frågat ChatGBT, googlat eller sökt svaret någon annan stans. Jag bara märkte att det fanns ett register till som jag hade glömt.
LED-lampan lyser nu.
Däremot fungerar inte
Så jag måste forska vidare där vad för register som inte är aktiverad.