Hledám učitele STM32F a uVision

Ahoj, posílám ti příklad mé inicializace MCU resp. main.c jak to používám já…netvrdím, že je to bůhvíjak skvělý přístup, ale na druhou stranu píšu už dost složité projekty abych byl schopen tvrdit, že tento systém je odzkoušený a spolehlivý. Snažím se nepoužívat žádné knihovny třetích stran a vycházím jen z toho co je v datasheetu a v knihovne stm32f10x.h popr. core_cm3.h

#include <stdint.h>
#include <stm32f10x.h>
#include <stm32f10x_flash.h>

#include <watchdog.h>
#include <memory_map_bios.h>
#include <var_bios.h>
#include <led_driver.h>

#include "main.h"

static void init_ram_memory(void);
static void init_mcu(void);

extern void init_gpio(void);
extern void init_slave_komunikace(void);
extern void init_rtc(void);
extern void init_adc(void);
extern void init_beeper(void);
extern void init_led(void);
extern void init_wifi(void);
extern void handle_rtc(void);
extern void handle_gpio(void);
extern void handle_adc(void);
extern void handle_slave_komunikace(void);
extern void handle_led(void);
extern void handle_wifi(void);

int main(void){   
  init_mcu();                                                                   // init HW MCU
  FLASH_Unlock();                                                               // povoli zapis do FLASH pameti MCU - emulace EEPROM
  init_ram_memory();                                                            // vymazani pametovych oblasti  
  
  init_gpio();
  init_slave_komunikace();
  init_rtc();
  init_beeper();
  init_adc();
  init_led();
  init_wifi();
  
  SysTick_Config(SystemCoreClock/1000);                                          //10-100ms,100-10ms,200-5ms,1000-1ms,10000-100us,100000-10us,
  init_wdt(TIMEOUT_13600MS);
  
  for(;;){
    handle_wdt();                                                               //obsluha Watchdog timeru
    handle_rtc();                                                               //obsluha realneho casu
    handle_adc();                                                               //obsluha analogu pres DMA
    handle_gpio();                                                              //obsluha vstupne-vystupnich portu    
    handle_led();                                                               //obsluha led - mela by byt tesne za obsluhou gpio
    handle_wifi();
    handle_slave_komunikace();                                                  //obsluha mirkom slave komunikace    
    // zde je umistena regulace - na konci hlavni smycky ///////////////////////
    //handle_application();
    }
  }

static void init_ram_memory(void){
  uint32_t i;
  
  #if defined(RAM_ADC)  
  //sem se plni analogove hodnoty z ADC pomoci DMA
  for(i = 0; i < RAM_ADC_SIZE; i+=4){ *(uint32_t*)(RAM_ADC_ADDR + i) = 0;}   
  #endif

  #if defined(RAM_BIOS)
  //toto je oblast pameti v BIOS, ktera je adresovana absolutne
  for(i = 0; i < RAM_BIOS_SIZE; i+=4){ *(uint32_t*)(RAM_BIOS_ADDR + i) = 0;}   
  #endif

  #if defined(RAM_APPL_DATA)       
  //toto je oblast pameti v APPL, ktera neni sdilena  
  for(i = 0; i < RAM_APPL_DATA_SIZE; i+=4){ *(uint32_t*)(RAM_APPL_DATA_ADDR + i) = 0;} 
  #endif  
  
  #if defined(RAM_APPL)
  //toto je oblast pameti v APPL, ktera je adresovana absolutne
  for(i = 0; i < RAM_APPL_SIZE; i+=4){ *(uint32_t*)(RAM_APPL_ADDR + i) = 0;}   
  #endif 

  #if defined(RAM_EXPAND)
  //toto je oblast pameti v APPL, ktera je adresovana absolutne
  for(i = 0; i < XRAM_APPL_SIZE; i+=4){ *(uint32_t*)(XRAM_APPL_ADDR + i) = 0xFFFFFFFF;}   
  #endif 
  }

static void init_mcu(void){
  //pro Analog se pin nenastavuje - standartne je jako vstupni
  RCC->AHBENR = 0
  | RCC_AHBENR_DMA1EN;                  // DMA1 clock enable
  
  RCC->APB1ENR = 0
  | RCC_APB1ENR_TIM2EN                  // Timer 2 clock enable (casovani RS485)
  | RCC_APB1ENR_TIM3EN                  // Timer 3 clock enable pro PWMku (BEEPER) 
  | RCC_APB1ENR_TIM4EN                  // Timer 4 clock enable spousteni AD prevodniku  
  | RCC_APB1ENR_TIM7EN                  // Timer 7 clock enable BEEPER (casovani) 
  | RCC_APB1ENR_DACEN                   // DAC interface clock enable 
  | RCC_APB1ENR_SPI2EN                  // SPI 2 clock enable (LED driver)   
  | RCC_APB1ENR_USART2EN                // USART2 clock enable        
  | RCC_APB1ENR_USART3EN                // USART3 clock enable
  | RCC_APB1ENR_I2C1EN                  // I2C 1 clock enable (WIFI driver)       
  | RCC_APB1ENR_PWREN                   // Power interface clock enable pro RTC         
  | RCC_APB1ENR_BKPEN;                  // Backup interface clock enable - uzivatelske registry v RTC
  
  RCC->APB2ENR = 0                      // Most of the peripherals are connected to APB2. Turn on the clocks for the interesting peripherals 
  | RCC_APB2ENR_AFIOEN                  // Alternate Function I/O clock enable - peripheral
  | RCC_APB2ENR_IOPAEN                  // I/O port A clock enable
  | RCC_APB2ENR_IOPBEN                  // I/O port B clock enable  
  | RCC_APB2ENR_IOPCEN                  // I/O port C clock enable
  | RCC_APB2ENR_IOPDEN                  // I/O port D clock enable 
  | RCC_APB2ENR_ADC1EN                  // ADC 1 interface clock enable 
  | RCC_APB2ENR_USART1EN;               // USART1 clock enable  
  
  AFIO->MAPR = 0         
  | AFIO_MAPR_TIM3_REMAP
  | AFIO_MAPR_USART3_REMAP_PARTIALREMAP        
  | AFIO_MAPR_SWJ_CFG_JTAGDISABLE; 
  
  GPIOB->ODR = 0  
  | GPIO_ODR_ODR14;                     // Pull-up on pin - wifi fabric init
  
  GPIOA->ODR = 0  
  | GPIO_ODR_ODR12;                     // Pull-up on pin - PROG
  
  GPIOA->CRL = 0
  | GPIO_CRL_CNF0_0                     // Input floating - AN8 (umozni cist AD i LOG hodnotu vstupu - rychle an vstupy)
  | GPIO_CRL_CNF1_0                     // Input floating - AN1 (umozni cist AD i LOG hodnotu vstupu - rychle an vstupy)         
  | GPIO_CRL_MODE2_0                    // Max output speed 10MHz - wifi USART2 TXD   
  | GPIO_CRL_CNF2_1                     // Alternate output with Push-pull - wifi USART2 TXD 
  | GPIO_CRL_CNF3_1                     // Input with pull-up - wifi USART2 RXD          
  | GPIO_CRL_MODE4_0                    // Max output speed 10MHz - DAC channel 1
  | (GPIO_CRL_CNF4_0|GPIO_CRL_CNF4_1)   // Alternate output open-drain - DAC channel 1
  | GPIO_CRL_MODE5_0                    // Max output speed 10MHz - DAC channel 2
  | (GPIO_CRL_CNF5_0|GPIO_CRL_CNF5_1)   // Alternate output open-drain - DAC channel 2
  | GPIO_CRL_CNF6_0                     // Input floating - AN4 (umozni cist AD i LOG hodnotu vstupu - rychle an vstupy)
  | GPIO_CRL_CNF7_0;                    // Input floating - AN6 (umozni cist AD i LOG hodnotu vstupu - rychle an vstupy)  
  
  GPIOA->CRH = 0             
  | GPIO_CRH_MODE8_0                    // Max output speed 10MHz - OUT 2         
  | GPIO_CRH_MODE9_0                    // Max output speed 10MHz - debug USART1 TXD   
  | GPIO_CRH_CNF9_1                     // Alternate output with Push-pull - debug USART1 TXD 
  | GPIO_CRH_CNF10_1                    // Input with pull-up - debug USART1 RXD   
  | GPIO_CRH_MODE11_0                   // Max output speed 10MHz - USART3 DIR RS485 
  | GPIO_CRH_CNF12_1                    // Input with pull-up - PROG        
  | GPIO_CRH_MODE15_0;                  // Max output speed 10MHz - WIFI RST      
  
  GPIOB->CRL = 0   
  | GPIO_CRL_CNF0_0                     // Input floating - AN2 (umozni cist AD i LOG hodnotu vstupu - rychle an vstupy)
  | GPIO_CRL_CNF1_0                     // Input floating - AN9 (umozni cist AD i LOG hodnotu vstupu - rychle an vstupy)        
  | GPIO_CRL_MODE3_0                    // Max output speed 10MHz - WIFI BOOT    
  | GPIO_CRL_MODE4_0                    // Max output speed 10MHz - STROBE (LED driver)  
  | GPIO_CRL_MODE6_0                    // Max output speed 10MHz on Pin 6 
  | (GPIO_CRL_CNF6_0|GPIO_CRL_CNF6_1)   // Alternate output open-drain - I2C SCL
  | GPIO_CRL_MODE7_0                    // Max output speed 10MHz on Pin 7       
  | (GPIO_CRL_CNF7_0|GPIO_CRL_CNF7_1);  // Alternate output open-drain - I2C SDA    
  
  GPIOB->CRH = 0    
  | GPIO_CRH_MODE8_0                    // Max output speed 10MHz - OUT 8 
  | GPIO_CRH_MODE9_0                    // Max output speed 10MHz - OUT 7 
  | GPIO_CRH_MODE12_0                   // Max output speed 10MHz - OUT 3        
  | GPIO_CRH_MODE13_0                   // Max output speed 10MHz on Pin 13 - SPI2 SCK          
  | GPIO_CRH_CNF13_1                    // Alternate output with Push-pull - SPI2 SCK  
  | GPIO_CRH_CNF14_1                    // Input with pull-up - wifi fabric init        
  | GPIO_CRH_MODE15_0                   // Max output speed 10MHz on Pin 15 - SPI2 SI         
  | GPIO_CRH_CNF15_1;                   // Alternate output with Push-pull - SPI2 SI        
  
  GPIOC->CRL = 0  
  | GPIO_CRL_CNF3_0                     // Input floating - AN7 (umozni cist AD i LOG hodnotu vstupu - rychle an vstupy)
  | GPIO_CRL_CNF4_0                     // Input floating - AN5 (umozni cist AD i LOG hodnotu vstupu - rychle an vstupy)
  | GPIO_CRL_CNF5_0                     // Input floating - AN3 (umozni cist AD i LOG hodnotu vstupu - rychle an vstupy)
  | GPIO_CRL_MODE6_0                    // Max output speed 10MHz - PWM 
  | GPIO_CRL_CNF6_1                     // Alternate output with Push-pull - PWM
  | GPIO_CRL_MODE7_0;                   // Max output speed 10MHz - OUT 4         
  
  GPIOC->CRH = 0      
  | GPIO_CRH_MODE8_0                    // Max output speed 10MHz - OUT 6 
  | GPIO_CRH_MODE9_0                    // Max output speed 10MHz - OUT 5         
  | GPIO_CRH_MODE10_0                   // Max output speed 10MHz - debug USART3 TXD   
  | GPIO_CRH_CNF10_1                    // Alternate output with Push-pull - debug USART3 TXD 
  | GPIO_CRH_CNF11_1                    // Input with pull-up - debug USART3 RXD
  | GPIO_CRH_MODE12_0;                  // Max output speed 10MHz - USART1 DIR RS485
  
  GPIOD->CRL = 0   
  | GPIO_CRL_MODE2_0;                   // Max output speed 10MHz - OUT 1     
  }

void SysTick_Handler(void){
  static uint8_t c_5ms = 0;
  static uint8_t c_100ms = 0;
  static uint8_t c_500ms = 0;
  static uint8_t m_1s = 0;
  
  p_bios_fce_DRIVE_SERVO_X jump_drive_servo;
  
  bram_m_global_cas |= (1<<C_1MS_LED);
  if(c_5ms != 0){c_5ms--;}  
  else{
    c_5ms = TIMER_MS(5,1);
    bram_m_global_cas |= (1<<C_5MS_USER_1)|(1<<C_5MS_USER_2);

    if(c_100ms != 0){c_100ms--;}
    else{    
      c_100ms = TIMER_MS(100,5);
      bram_m_global_cas |= (1<<C_100MS_WIFI)|(1<<C_100MS_USER_1)|(1<<C_100MS_USER_2);   
      
      if(bram_fce_DRIVE_SERVO1 != 0xFFFFFFFF){
        jump_drive_servo = (p_bios_fce_DRIVE_SERVO_X)bram_fce_DRIVE_SERVO1;  
        jump_drive_servo();      
        }
      
      if(bram_fce_DRIVE_SERVO2 != 0xFFFFFFFF){
        jump_drive_servo = (p_bios_fce_DRIVE_SERVO_X)bram_fce_DRIVE_SERVO2;  
        jump_drive_servo();
        }

      if(c_500ms != 0){c_500ms--;}
      else{
        c_500ms = TIMER_MS(500,100);   
        bram_m_global_cas |= (1<<C_500MS_USER_1)|(1<<C_500MS_USER_2);

        m_1s = ~m_1s;
        if(m_1s){
          bram_m_global_cas |= (1<<C_1S_ADC_DELAY)|(1<<C_1S_USER_1)|(1<<C_1S_USER_2);
          }
        }
      }
    }
  }

Používám startup soubor staženej ze stránek st.com. V něm se provádí inicializace automatických promených a nastavení hodin MCU.
Pro mě je nejdůležitější volání funkce init_mcu(), kde nastavuju periferie procesoru jaké budou v programu použity. Samotné nastavení periferií provádím až v konkrétních modulech viz ukázka knihovny na ovládání beepru.

#include <stdint.h>
#include <memory_map_bios.h>
#include <stm32f10x.h>
#include <beeper.h>

static uint16_t c_beep;
static uint16_t *p_melody;

const static uint16_t melodie_start] = {                                       //piskani pri zapnuti napajeni
  TON_OFF, BMS(100),
  TON_E  , BMS(100),
  TON_OFF, BMS(100),
  TON_F  , BMS(100),
  TON_OFF, BMS(100),
  TON_E  , BMS(100),
  0xFFFF,         
  };

void init_beeper(void){
  TIM3->PSC = TON_OFF;                                                          // Set prescaler to 0 (PSC + 1)
  TIM3->ARR = 16 - 1;                                                           // Auto reload value - dela rozsah  
  TIM3->CCR2 = 0;                                                               // Duty cycle

  TIM3->CCMR1 = 0  
  | TIM_CCMR1_OC1PE                                                             // Enable CCR1 preloading
  | TIM_CCMR1_OC1M_2                                                            // PWM mode 1: OC1M = 110  
  | TIM_CCMR1_OC1M_1; 
  
  TIM3->CCER = 0
  | TIM_CCER_CC1E;                                                              // Enable Capture/Compare output 2
  
  TIM3->CR1 = 0        
  | TIM_CR1_CEN; 
  
  BEEP_OFF;  
  
  // Set prescaler
  TIM7->PSC = 132;
  TIM7->CNT = 0;
  TIM7->DIER = TIM_DIER_UIE;                                                    // Enable update interrupt (timer level)
  NVIC_EnableIRQ(TIM7_IRQn);                                                    // Enable interrupt from TIM7 (NVIC level) 
  
  c_beep = 0;
  *p_melody = 0;
  
  start_melody((uint32_t)melodie_start);                                        //uvodni piskani
  }

//=============================================================================
// TIM7 Interrupt Handler
//=============================================================================
void TIM7_IRQHandler(void){                                                     
  if(TIM7->SR & TIM_SR_UIF){                                                    // if UIF flag is set   
    TIM7->SR &= ~TIM_SR_UIF;                                                    // clear UIF flag
    if(*(p_melody + (c_beep+=2)) == 0xFFFF){
      TIM7->CR1 &= ~TIM_CR1_CEN;
      TIM3->PSC = TON_OFF;
      BEEP_OFF;
      return;
      }    
    if(*(p_melody + c_beep) == 0xFFFE){ c_beep = 0;}
    else{TIM3->PSC = *(p_melody + c_beep);}  
    TIM7->ARR = *(p_melody + c_beep + 1);
    }
  }

void start_melody(uint32_t melody){  
  if((TIM7->CR1 & TIM_CR1_CEN) != 0){return;}
  else{
    BEEP_ON;
    c_beep = 0;
    p_melody = (uint16_t*)melody;
    TIM3->PSC = *(p_melody + 0); 
    TIM7->ARR = *(p_melody + 1);
    TIM7->CR1 |= TIM_CR1_CEN;                                                   // Enable timer
    }
  }

Jinak co se týče toho, že se ti nezdá jednoduchá cesta pochopit princip fungování maker a struktur tak si upřímně myslim že jsi tatar…když jsem z stmkem začínal rozhodněj jsem netvrdil, že umim dobře programovat atmel, ale kontrétně tohle mi přišlo naprosto intuitivní. ST má jedny z nejlepších tadasheetu k MCU co jsem kdy viděl.