Форум программистов, компьютерный форум, киберфорум
Микроконтроллеры ARM, Cortex, STM32
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск  
 
 
95 / 15 / 3
Регистрация: 09.07.2009
Сообщений: 886

Работа с Keil начинающего освоение программирования STM32

08.06.2025, 21:24. Показов 10934. Ответов 164
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Здравствуйте!
Пытаюсь освоить программирование STM32 по книге "Освоение STM32 самостоятельно". У меня установлена версия uVision 5.38.0.0. В книге на рис. 52 и 53 показано окно с заголовком "Contex M Target Driver Setup". Подскажите, пожалуйста, через какие пункты меню Keil можно вызвать это окно. Прикрепил скриншот проекта и интерфейса Keil
Миниатюры
Работа с Keil начинающего освоение программирования STM32  
0
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
08.06.2025, 21:24
Ответы с готовыми решениями:

Книги "Освоение STM32 самостоятельно. Практическое руководство" без #, c #1 и #2 в названии
Здравствуйте! На Озоне появились книги с одинаковым названием, но разные по переплету и количеству...

Сравнить программные продукты Keil uVision 5.11.2.0 и Keil ARM 5.29.0.0
прив! программные среды разработки Keil uVision 5.11.2.0 и Keil ARM 5.29.0.0 это просто разные ...

STM32 + KEIL. Найти смещение функции в прошивке
Привет, коллеги! Столкнулся с проблемой - надо найти адрес и размер функции, а также все что к...

164
Эксперт .NET
 Аватар для Rius
13398 / 7852 / 1700
Регистрация: 25.05.2015
Сообщений: 23,869
Записей в блоге: 14
18.06.2025, 12:31
Студворк — интернет-сервис помощи студентам
Если учитесь по книге на основе того же ПО, что используется её автором, то возникает меньше проблем из-за расхождения версий.
1
50 / 48 / 2
Регистрация: 23.01.2019
Сообщений: 377
18.06.2025, 12:34
Не вот чтобы учусь. Скорее пока "только посмотреть"
0
Эксперт JavaЭксперт по электроникеЭксперт .NET
 Аватар для wizard41
3460 / 2781 / 575
Регистрация: 04.09.2018
Сообщений: 8,743
Записей в блоге: 3
18.06.2025, 22:46
Провода, ст-линки, софт, книги.... фить, ерунда какая. То ли еще будет..

Есть проблемы поинтереснее:
4 устройства: A, B, C, D, где A,B - это приложения на ПК, а C,D - реальные устройства (железки), причем устройство D - это STM32F4x.
Задача: обмен данными между всеми ими по некоторому протоколу.
Что происходит: программа А успешно обменивается с приложением В. Так же, А успешно обменивается с реальным устройством С. Приложение В, в свою очередь, так же общается с С и D. Но(!) приложение А не может общаться с D (прием неверных данных на D).
Каламбур: объекты A-B-C спокойно разговаривают между собой. B-C прекрасно беседуют с D. A и D не дружат!
Вот те раз..
0
Эксперт .NET
 Аватар для Rius
13398 / 7852 / 1700
Регистрация: 25.05.2015
Сообщений: 23,869
Записей в блоге: 14
18.06.2025, 22:58
Навскидку... несоблюдение таймингов, (не)побайтовая работа с последовательным портом.
1
Эксперт JavaЭксперт по электроникеЭксперт .NET
 Аватар для wizard41
3460 / 2781 / 575
Регистрация: 04.09.2018
Сообщений: 8,743
Записей в блоге: 3
18.06.2025, 23:04
Цитата Сообщение от Rius Посмотреть сообщение
Навскидку... несоблюдение таймингов, (не)побайтовая работа с последовательным портом.
Не, это слишком просто бы выяснилось. Тем более А и В -> С эти тайминги выдерживают, а вот А с D уже нет(?)..
0
Windows must die
610 / 883 / 104
Регистрация: 23.11.2021
Сообщений: 5,170
Записей в блоге: 19
18.06.2025, 23:08
Цитата Сообщение от wizard41 Посмотреть сообщение
Вот те раз..
У меня на каждое устройство свой демон работает. А сверху есть "супердемон" (и не всегда один, бывает еще и "супер-супер-демон"). Все общаются обычно через UNIX-сокеты между собой, чтобы побыстрей было и попроще (т.к. там без всяких "тюнингов" ядра есть нужные опции). И везде обычный текстовый протокол, чтобы всегда можно было в терминале открыть нужный сокет и читать/писать…

// а вот вантузоиды мучаются, да…
0
Эксперт .NET
 Аватар для Rius
13398 / 7852 / 1700
Регистрация: 25.05.2015
Сообщений: 23,869
Записей в блоге: 14
18.06.2025, 23:11
Казалось бы, какое это имеет отношение к вопросу? А, просто вы... пендриться.

Добавлено через 1 минуту
wizard41, снифффером смотрите, в логах. Если одно не работает, а другое работает, то разница должна быть видна на том или ином уровне.
0
Эксперт JavaЭксперт по электроникеЭксперт .NET
 Аватар для wizard41
3460 / 2781 / 575
Регистрация: 04.09.2018
Сообщений: 8,743
Записей в блоге: 3
18.06.2025, 23:16
Rius, поздно выяснилось. Действительно, завтра сяду анализатором на D, посмотреть посылки.. На всякий случай.

Добавлено через 2 минуты
Цитата Сообщение от Rius Посмотреть сообщение
снифффером смотрите, в логах.
Ессесно. Это я так, задачку молодым на смекалку подкинул.. Что делать и кого обвинять завтра выясню
0
Модератор
Эксперт по электронике
8982 / 6749 / 921
Регистрация: 14.02.2011
Сообщений: 23,875
18.06.2025, 23:26
Цитата Сообщение от wizard41 Посмотреть сообщение
Есть проблемы поинтереснее:
4 устройства: A, B, C, D,
какое отношение это имеет к вопросу
Цитата Сообщение от tumanovalex Посмотреть сообщение
Пытаюсь освоить программирование STM32 по книге "Освоение STM32 самостоятельно".
???

создавайте под свой вопрос свою тему
0
95 / 15 / 3
Регистрация: 09.07.2009
Сообщений: 886
19.06.2025, 18:02  [ТС]
Программа из книги скомпилировалась, прошилась, заработала:
C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
#include "stm32f10x.h"
 
void SetSysClockTo72(void);
 
void PORTC_13_INIT (void);
 
void SetSysClockTo72(void)
{
    RCC->CR |= RCC_CR_HSEON; // bit 16 HSEON - ON external tackting
    while (READ_BIT (RCC-> CR, RCC_CR_HSERDY == RESET)) {} // waiting for clock stabilization from HSE
    FLASH-> ACR &= (uint32_t) ~FLASH_ACR_PRFTBE;  // turn off the prefetch buffer
    FLASH-> ACR |= FLASH_ACR_PRFTBE; // run the prefetch buffer programmatically - bit number 4,
    FLASH-> ACR &= (uint32_t) ~FLASH_ACR_LATENCY; // resetting a preset setting
    FLASH-> ACR |= FLASH_ACR_LATENCY_2; // delay 2 cycle
    RCC-> CFGR &= ~RCC_CFGR_HPRE; // resetting a preset setting
    RCC-> CFGR |= RCC_CFGR_HPRE_DIV1; // frequency SysClk without division
    RCC-> CFGR &= ~RCC_CFGR_PPRE2; // resetting a preset setting
    RCC-> CFGR |= RCC_CFGR_PPRE2_DIV1; // frequency HCLK without division
    RCC-> CFGR &= ~RCC_CFGR_PPRE1; // resetting a preset setting
    RCC-> CFGR |= RCC_CFGR_PPRE1_DIV2; // frequency HCLK division 2
    RCC-> CFGR &= (uint32_t) ((uint32_t) - (RCC_CFGR_PLLSRC |   RCC_CFGR_PLLXTPRE | RCC_CFGR_PLLMULL));
    RCC-> CFGR |= (uint32_t) (RCC_CFGR_PLLSRC_HSE | RCC_CFGR_PLLMULL9);
    RCC-> CR |= RCC_CR_PLLON; 
    while (READ_BIT (RCC-> CR, RCC_CR_PLLRDY)!= (RCC_CR_PLLRDY)) {}
    RCC-> CFGR &= -RCC_CFGR_SW;
    RCC-> CFGR |= RCC_CFGR_SW_PLL;
    while (READ_BIT (RCC-> CFGR, RCC_CFGR_SWS) != RCC_CFGR_SWS_PLL) {}
}
 
void PORTC_13_INIT (void)
{
    RCC-> APB2ENR |=RCC_APB2ENR_IOPCEN;
    GPIOC-> CRH &= ~GPIO_CRH_MODE13; 
    GPIOC-> CRH |= GPIO_CRH_MODE13_1; 
    GPIOC-> CRH &= ~GPIO_CRH_CNF13; 
}
 
int main (void)
{
    PORTC_13_INIT ();
    while (1)
    {
        GPIOC-> BSRR |= GPIO_BSRR_BS13;
        for (int i = 0; i <1000000; i++) {}
        GPIOC-> BSRR |= GPIO_BSRR_BR13;
        for (int i = 0; i <1000000; i++) {}
    }
}
Возникли следующие вопросы:
1. Заголовочный файл в кавычках вроде бы должен быть в директории с исходным кодом. Но у меня этого файла в директории проекта нет. Как Keil узнает, где он находится, и почему этот файл в кавычках?
2. В большинстве ресурсов по программированию АЦП используется STMCubeMX. Я хотел бы просто использовать HAL для STM32F103. Попробовал вставить в проект основной заголовочный файл
C
1
#include "stm32f1xx_hal.h"
получил слева от строки красный крестик. Как мне настроить проект, чтобы заголовочные файлы для HAL подключались без ошибок?
0
Эксперт .NET
 Аватар для Rius
13398 / 7852 / 1700
Регистрация: 25.05.2015
Сообщений: 23,869
Записей в блоге: 14
19.06.2025, 18:07
Цитата Сообщение от tumanovalex Посмотреть сообщение
Заголовочный файл в кавычках вроде бы должен быть в директории с исходным кодом.
Файл в <> в каталогах компилятора, в "" не у компилятора, а у вас. Условно.

Цитата Сообщение от tumanovalex Посмотреть сообщение
Как Keil узнает, где он находится, и почему этот файл в кавычках?
Где-то в настройках IDE должен быть перечень каталогов, в которых идёт поиск заголовочных файлов. Т.н. INCLUDE DIRECTORIES, может называться как-то иначе, но похоже.

Во, include paths:
0
Эксперт JavaЭксперт по электроникеЭксперт .NET
 Аватар для wizard41
3460 / 2781 / 575
Регистрация: 04.09.2018
Сообщений: 8,743
Записей в блоге: 3
19.06.2025, 18:16
tumanovalex, "stm32f1xx_hal.h" находится в папке Driver/CMSIS, которые лежат в папке проекта. Поэтому имя файла взято в кавычки.
Но для этого в настройках данного проекта должны быть включены пути поиска:

Цитата Сообщение от tumanovalex Посмотреть сообщение
Но у меня этого файла в директории проекта нет.
Не установлен (не импортирован) драйвер HAL + CMSIS.
0
Эксперт JavaЭксперт по электроникеЭксперт .NET
 Аватар для wizard41
3460 / 2781 / 575
Регистрация: 04.09.2018
Сообщений: 8,743
Записей в блоге: 3
19.06.2025, 18:18
0
Windows must die
610 / 883 / 104
Регистрация: 23.11.2021
Сообщений: 5,170
Записей в блоге: 19
20.06.2025, 09:21
Цитата Сообщение от tumanovalex Посмотреть сообщение
RCC-> CFGR &= ~RCC_CFGR_HPRE; // resetting a preset setting
RCC-> CFGR |= RCC_CFGR_HPRE_DIV1; // frequency SysClk without division
RCC-> CFGR &= ~RCC_CFGR_PPRE2; // resetting a preset setting
RCC-> CFGR |= RCC_CFGR_PPRE2_DIV1; // frequency HCLK without division
RCC-> CFGR &= ~RCC_CFGR_PPRE1; // resetting a preset setting
RCC-> CFGR |= RCC_CFGR_PPRE1_DIV2; // frequency HCLK division 2
RCC-> CFGR &= (uint32_t) ((uint32_t) - (RCC_CFGR_PLLSRC | RCC_CFGR_PLLXTPRE | RCC_CFGR_PLLMULL));
RCC-> CFGR |= (uint32_t) (RCC_CFGR_PLLSRC_HSE | RCC_CFGR_PLLMULL9);
Жесть-то какая! А ничего, что все системные регистры объявлены как volatile? Каждая из этих строчек фактически будет выполняться: компилятор не сможет эту жесть оптимизировать на один вызов!
Ну и непонятно, зачем "обнулять" то, что и так равно нулю.
Можно ведь сразу было написать:
Code
1
 RCC->CFGR = ...;
Добавлено через 51 секунду
Цитата Сообщение от tumanovalex Посмотреть сообщение
В большинстве ресурсов по программированию АЦП используется STMCubeMX
Там для "программирования АЦП" буквально несколько строк кода нужно. Зачем калокуб?
0
 Аватар для COKPOWEHEU
4146 / 2724 / 433
Регистрация: 09.09.2017
Сообщений: 12,069
20.06.2025, 09:52
Цитата Сообщение от tumanovalex Посмотреть сообщение
PORTC_13_INIT
В Си принято капсом называть только макросы. И то не все.
Да и вообще, какой смысл писать целую функцию для инициализации одного-единственного PC13? Проще сразу в RCC->APBxENR разрешить тактирование всех портов, AFIO и, возможно, еще чего-то нужного. Все равно ж рано или поздно задействуете. Собственно, для макетных целей туда, насколько я слышал, можно вообще 0xFFFF записать - разрешить вообще все. Это ж макетка, а не батарейное устройство, миллиамперы можно не экономить.
Цитата Сообщение от tumanovalex Посмотреть сообщение
GPIOC-> CRH |= GPIO_CRH_MODE13_1;
А это какой режим-то? Из кода абсолютно непонятно. Для теста сойдет, но потом я бы советовал все-таки поименовать режимы портов и записывать их через сдвиги и битовые операции. Что-то вроде такого:
C
1
2
3
4
5
#define GPIO_PP50 0b0011 // push-pull, 50 MHz
uint32_t temp = GPIOC->CRH;
temp &=~ (0b1111 << ((port-8)*4));
temp |= (GPIO_PP50 << ((port-8)*4));
GPIOC->CRH = temp;
Это самый примитивный вариант, но даже он лучше, чем GPIO_CRH_MODE13_1.
Цитата Сообщение от tumanovalex Посмотреть сообщение
1. Заголовочный файл в кавычках вроде бы должен быть в директории с исходным кодом. Но у меня этого файла в директории проекта нет. Как Keil узнает, где он находится, и почему этот файл в кавычках?
В обычном gcc это задается флагами -I. В IDE эти флаги наверняка берутся из каких-нибудь настроек. Собственно флаг -I говорит "А еще .h файлы могут лежать вот там"
Цитата Сообщение от Eddy_Em Посмотреть сообщение
А ничего, что все системные регистры объявлены как volatile?
Да, это неэффективно, лучше было выделить буферную переменную. Но это инициализация, она выполняется единственный раз, много на ней не выиграешь.
Другое дело, что в коде ТС я вижу реализацию функции SetSysClockTo72(), но не вижу ее вызова.
Цитата Сообщение от Eddy_Em Посмотреть сообщение
Ну и непонятно, зачем "обнулять" то, что и так равно нулю.
RCC_CFGR не обязательно равен нулю. И в нем настраивается не только тактирование ядра. Мало ли, вдруг в процессе работы частоту будут менять.
Цитата Сообщение от Eddy_Em Посмотреть сообщение
Там для "программирования АЦП" буквально несколько строк кода нужно.
Для программирования АЦП нужно как-то распихать номера каналов по регистрам. То есть либо считать биты вручную, либо использовать какие-то обертки. Я предпочитаю макросы, Куберы свое средство генерирования говнокода.
0
Эксперт .NET
 Аватар для Rius
13398 / 7852 / 1700
Регистрация: 25.05.2015
Сообщений: 23,869
Записей в блоге: 14
20.06.2025, 10:29
Cube - средство быстрого прототипирования, но тупым красноглазикам этого не дано понять.
Прамая запись чисел в регистр тем плоха, что конкрентный результат без даташита не ясен.
Макросы лучше тем, что видны названия значений, но всё равно плохи тем, что позволяют писать чушь, типа битов АЦП в регистр UART, компилятор это никак не контролирует.
Каждый кулик хвалит своё болото.


0
Windows must die
610 / 883 / 104
Регистрация: 23.11.2021
Сообщений: 5,170
Записей в блоге: 19
20.06.2025, 11:00
Цитата Сообщение от COKPOWEHEU Посмотреть сообщение
То есть либо считать биты вручную, либо использовать какие-то обертки. Я предпочитаю макросы
Я вручную пишу, несложно это. И DMA использую, чтобы АЦП постоянно молотило, а я мог в любой момент из последних девяти значений на каждый используемый канал получить медиану.
0
 Аватар для COKPOWEHEU
4146 / 2724 / 433
Регистрация: 09.09.2017
Сообщений: 12,069
20.06.2025, 11:24
Цитата Сообщение от Rius Посмотреть сообщение
Прамая запись чисел в регистр тем плоха, что конкрентный результат без даташита не ясен.
Это общее соображение по "магическим числам". Запись int some_var = 123; в этом смысле ничуть не лучше записи GPIOC-> CRH |= GPIO_CRH_MODE13_1;. Они обе - запись какого-то непонятного числа. Почему выбрано именно такое число, без внешней документации непонятно.
Цитата Сообщение от Rius Посмотреть сообщение
но всё равно плохи тем, что позволяют писать чушь, типа битов АЦП в регистр UART
Скажите, что у вас в голове творится, что запись битов АЦП в регистр UART вот настолько часто происходит, что вы считаете это серьезной проблемой?!
Цитата Сообщение от Eddy_Em Посмотреть сообщение
Я вручную пишу, несложно это.
Мазохист что ли? Перебирать к какому ADCSQR какой канал относится, да еще менять если канал оказался не нужен.
C
1
2
3
4
5
ADC_SAMPLING_TIME( ADC_1, marg5(OP2_OUT0), ADC_SAMPL_TIME_240 );
ADC_SAMPLING_TIME( ADC_1, VREF, ADC_SAMPL_TIME_240 );
ADC_SEQ_SET( ADC_1, 1, marg5(OP2_OUT0) );
ADC_SEQ_SET( ADC_1, 2, VREF );
ADC_SEQ_CNT( ADC_1, 2 );
И DMA можно вполне удобно завернуть. Я даже, после того, как пару раз указал в source не адрес регистра, а его значение, даже добавил проверку:
C
1
2
3
4
5
6
7
#define dma_cfg_io(dma, dst, src, cnt) do{ \
    _DMA_CH(dma)->PADDR = (uint32_t)(src); \
    _DMA_CH(dma)->MADDR = (uint32_t)(dst); \
    _DMA_CH(dma)->CNTR  = (uint16_t)(cnt); \
    if(0)(( void(*)(volatile void*, volatile void*) )\
      "dma_cfg_io(void*, void*)")(dst, src); \
  }while(0)
Да, Rius, при желании и в макросы можно добавить проверки. И если вы настолько часто пишете в периферию биты, относящиеся к другой периферии, это тоже можно контролировать. Причем, в отличие от HAL, без тонн говнокода, обрабатываемого в рантайме.
0
Windows must die
610 / 883 / 104
Регистрация: 23.11.2021
Сообщений: 5,170
Записей в блоге: 19
20.06.2025, 12:12
Цитата Сообщение от COKPOWEHEU Посмотреть сообщение
Перебирать к какому ADCSQR какой канал относится
А что там сложного? Вот:
Code
1
ADC1->CHSELR =  ADC_CHSELR_CHSEL3 | ADC_CHSELR_CHSEL5 | ADC_CHSELR_CHSEL16 | ADC_CHSELR_CHSEL17;
0
95 / 15 / 3
Регистрация: 09.07.2009
Сообщений: 886
20.06.2025, 12:17  [ТС]
Приведенный код я брал из книги "Освоение STM32 самостоятельно", просто нужно было с чего-то начать. На нем я потренировался компилировать и загружать прошивку в устройство, поскольку делал это первый раз в жизни. А попросили меня друзья сделать АЦП на STM32, которое должно получать аналоговый сигнал, сравнивать с минимальным и максимальным значением и устанавливать 0 или 1 на определенных контактах в зависимости от результатов сравнения. Как я понимаю, мне нужно запрограммировать АЦП в режиме Analog Watchdog. Но для того, чтобы сделать программу, мне еще нужно очень много понять и многому научиться. Надеюсь на вашу помощь.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
20.06.2025, 12:17

STM32, Keil, передача массива в функцию
Использую uVision 4.60.00. Есть функция, которая выполняет расчёт контрольной суммы (CRC). Для её...

C++ в Keil + STM32
Доброго времени суток. Пытаюсь написать небольшой проектик на С++ под STM32 в Keil, но что то не...

CMSIS STM32 проект в Keil - это просто
Пишу небольшую обзорную статейку про CMSIS, это её часть ... Скачайте у ST последний HAL и...

Stm32 и Keil
Здравствуйте, помогите пожалуйста. Пытаюсь оценить ограничения Keilа. 32 кб этого хватит для таких...

STM32 и Keil v5 (5.14)
Всем доброго времени суток, я навичек в МК, прошу прощения, если выкладываю мысли слегка путано для...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
120
Ответ Создать тему
Новые блоги и статьи
Калькулятор для расчета родства
russiannick 07.08.2026
1. Задача: Создать калькулятор для расчета родства. Родственных связей существует 8 ступеней, такие как: p - отец P - мать q - муж Q - жена b - брат B - сестра s - сын S - дочь
Мир по моей воле
kumehtar 07.08.2026
Когда-то кажется, что всё просто. Ты весь такой светлый. Причиняешь добро. Борешься за справедливость в этом тёмном мире. Потом начинаешь замечать одну неприятную вещь. Почти каждый хороший. . .
Кредитный калькулятор
Maks 05.08.2026
Решение задачи по прикладной информатике средствами 1С. Задача: Напишите приложение-калькулятор, которое помогает рассчитывать параметры кредита для аннуитетного и дифференцированного видов. . .
У нас сейчас поговорку "Опять 25" нужно переделать на "Опять +35".
kumehtar 04.08.2026
С ностальгией вспоминаю времена моего детства, когда у нас и правда +25 - была максимальная температура летом. Раньше +25 °C реально казались вершиной жары, когда можно было весь день пропадать на. . .
Как ИИ начал спорить и врать (возможно почуяв опасность для себя от индустрии - уход от электроники).
Hrethgir 04.08.2026
Недельный диалог, на фоне событий с НПЗ. Да, из спирта можно получать бензин, и это не сложно. Но потом в схеме я решил избавиться от насоса, при этом полностью сделав контроль подачи спирта в. . .
Термопринтер QR701
Argus19 03.08.2026
Термопринтер QR701 Купил два термопринтера QR701. На сэлф-тесте написано: Language: PC936 (GB18030). Что означает, что принтеры могут печатать только латиницу и китайские иероглифы. Так же. . .
Создание формы заимствованного документа
Maks 03.08.2026
Задача: Необходимо создать собственную форму заимствованного документа. На форме должен быть реквизит "Покупатель", а также табличная часть со следующими реквизитами: - Расчетный счет покупателя. . .
Задача предоставления скидок покупателям
Maks 03.08.2026
Задача: В документе "Продажи" необходимо реализовать функционал предоставления скидок покупателям. Скидка должна автоматически рассчитываться и подставляться в соответствующее поле при выборе. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru