Ich bin neu bei STM8S und noch nicht so gut in der Mikrocontroller-Programmierung im Allgemeinen. Ich versuche, etwas über Timer / Zähler in Mikrocontrollern zu lernen.
Ich habe folgenden Code geschrieben, um jede Sekunde eine LED umzuschalten, die am PB5-Pin angeschlossen ist.
#include "stm8s.h"
int main() {
// Default clock is HSI/8 = 2MHz
PB_DDR |= (1 << PB5); // PB5 is now output
PB_CR1 |= (1 << PB5); // PB5 is now pushpull
TIM2_PSCR = 0b00000111; // Prescaler = 128
TIM2_CR1 |= (1 << TIM2_CR1_CEN); // Enable TIM2
while (1) {
if ( ( ((uint16_t)TIM2_CNTRH << 8) + (uint16_t)TIM2_CNTRL ) >= 15625 ) {
// Reset counter back to 0
TIM2_CNTRH = 0;
TIM2_CNTRL = 0;
// Toggle LED.
PB_ODR ^= (1 << PB5);
}
}
}
Mein Mikrocontroller ist nicht mit einer externen Uhr verbunden und verwendet die interne Uhr für den Betrieb.
Nachdem ich das Datenblatt gelesen habe, sehe ich, dass der MCU-Takt standardmäßig HSI / 8 = 2 MHz beträgt. Ich habe 128 als Prescaler für TIM2 eingestellt. Der TIM2-Zähler wird also alle 64 us erhöht. Wenn es also 15625 erreicht, ist es 1 Sekunde (64 * 15625 = 1000000 us = 1 s).
Also nahm ich an, dass die LED jede Sekunde umschaltet.
Das Problem ist, dass die LED die ganze Zeit an bleibt.
Kann mir jemand helfen, das Problem mit meinem Code zu identifizieren?
Vielen Dank im Voraus.
Nachdem ich das Referenzhandbuch weiter gelesen hatte, stellte ich fest, dass wir UG
das Bit setzen müssen TIM2_EGR
, um das Ereignis zu generieren und zu aktualisieren, damit die MCU den Prescaler-Wert für TIMER 4 übernimmt.
TIM2_EGR |= (1 << TIM2_EGR_UG);
Der aktualisierte Code lautet also:
#include "stm8s.h"
int main() {
// Default clock is HSI/8 = 2MHz
PB_DDR |= (1 << PB5); // PB5 is now output
PB_CR1 |= (1 << PB5); // PB5 is now pushpull
TIM2_PSCR = 0b00000111; // Prescaler = 128
TIM2_EGR |= (1 << TIM2_EGR_UG); // Generate an update event so prescaler value will be taken into account.
TIM2_CR1 |= (1 << TIM2_CR1_CEN); // Enable TIM2
while (1) {
if ( ( ((uint16_t)TIM2_CNTRH << 8) + (uint16_t)TIM2_CNTRL ) >= 15625 ) {
// Reset counter back to 0
TIM2_CNTRH = 0;
TIM2_CNTRL = 0;
// Toggle LED.
PB_ODR ^= (1 << PB5);
}
}
}
Jetzt fing die LED an, jede Sekunde umzuschalten !!
Nehmen Sie kleine Änderungen am Code vor: Enthaltener Timer 2-Überlauf-Interrupt.
NOTIZ :
Das Programm wurde mit dem SDCC-Compiler kompiliert und der Mikrocontroller mit ST Visual Programmer (STVP) geflasht.
Stellen Sie sicher, dass Sie die benutzerdefinierte Header-Datei hier herunterladen: https://github.com/ElectronicCircuitDesignTools/STM8S103F3P6/blob/303d53aded5b4b91b23d1356df89df0c97968d30/stm8s103f3p6_register_map.h
#define using_io_ports 1
#define using_tim2 1
#define TIM2_OVF 13
#include "stm8s103f3p6_register_map.h"
unsigned int prescaler = 4;
unsigned char led_state = 0x00;
void isr_timer_2_overflow() __interrupt(TIM2_OVF)
{
PD_ODR ^= ( 1 << ODR4 );
TIM2_CNTRH = (unsigned char)(3035 >> 8); // Load starting value of timer 2 ( high byte ).
TIM2_CNTRL = (unsigned char)(3035 & 0xFF); // Load starting value of timer 2 ( low byte ).
TIM2_SR1 = 0x00; // Clear the update interrupt flag.
}
void main( void )
{
PD_DDR = ( 1 << ODR4 );
PD_CR1 = ( 1 << C14 );
__asm__("sim"); // Disable all interrupts.
TIM2_CNTRL = 0; // Clear Timer 2 counter register ( high byte ).
TIM2_CNTRH = 0; // Clear Timer 2 counter register ( low byte ).
TIM2_PSCR = 0x04; // Set Timer 2 clock speed = f_master / 4.
TIM2_EGR = 0x01; // Enable update event.
TIM2_IER = 0x01; // Enable update interrupt.
TIM2_SR1 = 0x00; // Clear the update interrupt flag.
TIM2_CR1 = 0x01; // Enable Timer 2 operation as counter.
__asm__("rim");
while(1)
{
}
}
rrz0
Juniid
for
Schleife ausführe, um die Verzögerung zu erzeugen.