Администрация форума не несёт ответственности за достоверность информации и оставляет за собой право редактировать или в особых случаях даже удалять посты без предупреждения. Спасибо за понимание.

Программирование ATMEL в BASCOM.

Информация о пользователе

Привет, Гость! Войдите или зарегистрируйтесь.



Первые шаги

Сообщений 1 страница 3 из 3

1

Ну вот я и сделал первый шаг к новым вершинам.
Код чисто символический, написан для пробы. Потом всё начну оформлять как положено с раздельными файлами С и хидерами. Пока для эксперимента.

Код:
/*******************************************************************************
File:     main.c
Info:     Generated by Atollic TrueSTUDIO(R) 9.3.0   2019-10-18
********************************************************************************/
/* Подключаемые файлы */
#include "stm32l4xx.h"

/* Функции */
int ClockInit()
{
/* Запускаем генератор HSE */
	__IO int Cnt;
	  int Error;
	  RCC->CR |= RCC_CR_HSEON_Msk;            //Запуск
	  for(Cnt=0; ; Cnt++)                     //Ждём сигнал подтверждения
	  {
	    if(RCC->CR & (1<<RCC_CR_HSERDY_Pos))  //Всё ОК, сбросим флаг ошибки и выходим
	    {
	    Error=0;
	    break;
	    }
	    if(Cnt > 0x1000)                      //Запуск не получился, установим флаг ошибки и выходим
	    {
	      RCC->CR &= ~(1<<RCC_CR_HSEON_Pos);
	      Error=1;
	    }
	  }
	  return Error;
}

/* Главная */
int main(void)
{
  int Er=0, Flag=0;
  Er=ClockInit;
  if(Er==1)
    Flag=1;
}

Несколько вопросов знатокам.
1. Atollic подчёркивает красным комментарии на русском. Можно ли это исправить? Не критично, но раздражает.
2. При компиляции ошибок нет, есть два предупреждения.
http://s9.uploads.ru/t/mfdZr.jpg

Второе вроде понятно. Говорит, что переменная есть, но нигде не используется, а вот первое не очень понятно.
Если не сложно, то объясните пожалуйста.

Всё Разобрался. Надо было так написать: Er=ClockInit(); Забыл скобки поставить.

Отредактировано sva-don (2019-10-18 11:09:31)

0

2

Я бы функцию так написал бы.

Код:
uint8_t ClockInit(void)
{
    volatile uint32_t Cnt=0;
    uint8_t Error=0;
    
    RCC->CR |= RCC_CR_HSEON;
    
    while (RCC->CR & RCC_CR_HSERDY == 0)
    {
        if (Cnt++ > 100000)
        {
            Error=1;
            break;
        }
    }
    return Error;
}

Из типа переменной сразу очевиден ее размер, т. е. 32 (uint32_t) и 8 (uint8_t) бит. Использовать int конечно можно, но так нагляднее. И я бы использовал 32-ух битный счетчик DWT (где-то на форуме выкладывал код) для отсчета временных интервалов, точность которых не зависят от тактовой частоты (ее можно изменять программно) и выполнения прерываний, т. е. задал интервал скажем 10 мс и условие будет выполнено по прошествии этого времени.

sva-don написал(а):

1. Atollic подчёркивает красным комментарии на русском. Можно ли это исправить? Не критично, но раздражает.

Предупреждение критично, т. к. код будет выполнятся не так как задумано. В строке вместо вызова функции в Er помещается указатель на нее. Нужно добавить скобки.

+1

3

Пётр написал(а):

я бы использовал 32-ух битный счетчик DWT

Вчера забыл выложить файлы.

DWT_Delay.h
Код:
#ifndef DELAY_H_INCLUDED
#define DELAY_H_INCLUDED

#include "stm32l431xx.h"

void DWT_DelayUpdate(void);
void DWT_Init(void);
void DWT_Deinit(void);
void DWT_Delay_sec(uint32_t sec);
void DWT_Delay_ms(uint32_t ms);
void DWT_Delay_us(uint32_t us);

uint8_t DWT_Test_sec(uint32_t start, uint32_t time);
uint8_t DWT_Test_ms(uint32_t start, uint32_t time);
uint8_t DWT_Test_us(uint32_t start, uint32_t time);

uint32_t DWT_Time_sec(uint32_t start, uint32_t current);
uint32_t DWT_Time_ms(uint32_t start, uint32_t current);
uint32_t DWT_Time_us(uint32_t start, uint32_t current);

__attribute__((always_inline)) __STATIC_INLINE
uint32_t DWT_GetTick(void)
{
   return DWT->CYCCNT;
}

#endif /* DELAY_H_INCLUDED */
DWT_Delay.c
Код:
#include "DWT_Delay.h"

extern uint32_t SystemCoreClock;
static uint32_t Delay_us, Delay_ms;
static uint8_t init_state=0;

void DWT_DelayUpdate(void)
{
    Delay_ms = SystemCoreClock / 1000;    // Число тактов ядра за миллисекунду.
    Delay_us = SystemCoreClock / 1000000; // Число тактов ядра за микросекунду.
}

void DWT_Init(void)
{
    if (init_state == 0)
    {
        init_state=1;
        CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk;
        DWT->CTRL |= DWT_CTRL_CYCCNTENA_Msk;
        DWT->CYCCNT = 0;
        DWT_DelayUpdate();
    }
}


void DWT_Deinit(void)
{
    if (init_state)
    {
        init_state=0;
        DWT->CTRL &= ~DWT_CTRL_CYCCNTENA_Msk;
        CoreDebug->DEMCR &= ~CoreDebug_DEMCR_TRCENA_Msk;
    }
}


void DWT_Delay_sec(uint32_t sec) // В секундах.
{
    uint32_t Count = DWT->CYCCNT;
    sec = sec * SystemCoreClock;
    while((DWT->CYCCNT - Count) < sec);
}

void DWT_Delay_ms(uint32_t ms) // В миллисекундах
{
    uint32_t Count = DWT->CYCCNT;
    ms = ms * Delay_ms;
    while((DWT->CYCCNT - Count) < ms);
}

void DWT_Delay_us(uint32_t us) // В микросекундах.
{
    uint32_t Count = DWT->CYCCNT;
    us = us * Delay_us;
    while((DWT->CYCCNT - Count) < us);
}

// 0 - если время меньше заданного. 1 если время больше и равно заданному.
// Параметры. start - число тиков ядра в начале отсчета. time - время.
__attribute__((optimize("-Ofast")))
uint8_t DWT_Test_sec(uint32_t start, uint32_t time)
{
    return (((DWT->CYCCNT - start) >= (time*SystemCoreClock)) ? 1 : 0);
}

__attribute__((optimize("-Ofast")))
uint8_t DWT_Test_ms(uint32_t start, uint32_t time)
{
    return (((DWT->CYCCNT - start) >= (time*Delay_ms)) ? 1 : 0);
}

__attribute__((optimize("-Ofast")))
uint8_t DWT_Test_us(uint32_t start, uint32_t time)
{
    return (((DWT->CYCCNT - start) >= (time*Delay_us)) ? 1 : 0);
}


// Время прошедшее с начала отсчета.
// Параметры. start - число тиков ядра в начале отсчета. current - текущее число тиков ядра.
__attribute__((optimize("-Ofast")))
uint32_t DWT_Time_sec(uint32_t start, uint32_t current)
{
    return (current - start) / SystemCoreClock;
}

__attribute__((optimize("-Ofast")))
uint32_t DWT_Time_ms(uint32_t start, uint32_t current)
{
    return (current - start) / Delay_ms;
}

__attribute__((optimize("-Ofast")))
uint32_t DWT_Time_us(uint32_t start, uint32_t current)
{
    return (current - start) / Delay_us;
}

Вначале кода (после настройки тактирования) вызывается функция SystemCoreClockUpdate(), а за ней DWT_Init().
Далее можно пользоваться функциями библиотеки.
Если частота ядра изменится, нужно вызвать SystemCoreClockUpdate() и после нее DWT_DelayUpdate().

0