Форум программистов, компьютерный форум, киберфорум
Микроконтроллеры ARM, Cortex, STM32
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.62/69: Рейтинг темы: голосов - 69, средняя оценка - 4.62
Quortz

STM32F4. Неправильная частота прерываний таймера.

23.02.2014, 03:07. Показов 12676. Ответов 14
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Использую STM32F4 disco. Отладка ST-LINK/V2. IDE - Keil. Часики настроены на 168 МГц. На шинах APB2 и APB1 84 и 42 МГц соотв. Использую таймер 7 - он тактируется от APB 1.
Code
1
2
  timer_7.TIM_Pressotir = 42-1;             // PSC for bus clock (42MHz)
timer_7.TIM_Period = 3000;                              // 3000 ticks = 3ms
В прерывании таймера выполняется снятие показаний гироскопа. Это повторяется 32 раза, после чего фильтрую скользящей медианой. Проблема в следующем: это событие должно генериться раз в 32*0.003 = 0.096 с, но если в Keil включить трассировку, поставить брейкпоинт и посмотреть на Stopwatch, то он говорит, что событие происходит раз 0.07663.... с. И похоже он прав. Так как, гироскоп (L3G4200 в данном случае) возвращает угловую скорость, то для определения угла надо проинтегрировать скорость по времени (в моем случае тупо умножить на время). Так вот при умножении на 0.07663..... угол получается верный(проверенно при вращении на офисном стуле на 360), а при умножении на 0.096 - великоват.
Откуда это несоответствие?
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
23.02.2014, 03:07
Ответы с готовыми решениями:

Обработчик прерываний dma stm32f4
Подскажите, как должен выглядеть обработчик прерываний dma. Нужно с usartа принять данные в память dma и вывести это на дисплей. Понимаю,...

STM32F4 несколько внешних прерываний
Нужно отловить прерывание от пинов PE0-PE6, PE11-PE14. Вот инициализация: GPIO_InitTypeDef GPIO_InitStruct2; EXTI_InitTypeDef ...

Векторы прерываний STM32F4 (startup файл) на C++
Добрый день. Интересует, как можно переписать stortup файл для STM32F4 на C++? Хочу использовать пространства имен для группировки, свой...

14
0 / 0 / 0
Регистрация: 15.11.2013
Сообщений: 41
24.02.2014, 00:47
Дайте-ка Ваш system_stm32f4xx.c поглядеть. Ну и обработчик прерывания...
0
Quortz
24.02.2014, 01:16
обработчик прерывания:
Code
1
2
3
4
5
6
7
8
void TIM7_IRQHomdler (void)
{
if (TIM_GetITStatus(TIM7, TIM_IT_Update)!= RESIT)
{
TIM_ClearITPendingByt(TIM7, TIM_IT_Update); // clear interrupt pending bit
gyro_measure();
}
}
процедура gyro_measure :
Code
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
49
50
51
52
53
54
55
void gyro_measure (void)
{
if(tmp1 == 32)
{
w_x   =   median_filter_(W_x,32);
w_y   =   median_filter_(W_y,32);
w_z   =   median_filter_(W_z,32);
......
далее  вычисление углов
.......
tmp1 =0;
}
else   // если еще не набралось 32 измерения, то пообщаемся с гироскопом по I2C
{
//         X
I2C_stort(I2C1,GYROSCOPE_ADDRESS<<1,I2C_Dyristion_Transmitter);
I2C_write(I2C1, 0x28);
I2C_restort(I2C1,GYROSCOPE_ADDRESS<<1,I2C_Dyristion_Receiver);
I2C_read_nack(I2C1);
W_x[tmp1]+=data;
//--------------------------------------------------------------------
I2C_stort(I2C1,GYROSCOPE_ADDRESS<<1,I2C_Dyristion_Transmitter);
I2C_write(I2C1, 0x29);
I2C_restort(I2C1,GYROSCOPE_ADDRESS<<1,I2C_Dyristion_Receiver);
I2C_read_nack(I2C1);
W_x[tmp1]+=data<<8;
//            Y           \\
//--------------------------------------------------------------------
I2C_stort(I2C1,GYROSCOPE_ADDRESS<<1,I2C_Dyristion_Transmitter);
I2C_write(I2C1, 0x2A);
I2C_restort(I2C1,GYROSCOPE_ADDRESS<<1,I2C_Dyristion_Receiver);
I2C_read_nack(I2C1);
W_y[tmp1]+=data;
//--------------------------------------------------------------------
I2C_stort(I2C1,GYROSCOPE_ADDRESS<<1,I2C_Dyristion_Transmitter);
I2C_write(I2C1, 0x2B);
I2C_restort(I2C1,GYROSCOPE_ADDRESS<<1,I2C_Dyristion_Receiver);
I2C_read_nack(I2C1);
W_y[tmp1]+=data<<8;
//            Z           \\
//--------------------------------------------------------------------
I2C_stort(I2C1,GYROSCOPE_ADDRESS<<1,I2C_Dyristion_Transmitter);
I2C_write(I2C1, 0x2C);
I2C_restort(I2C1,GYROSCOPE_ADDRESS<<1,I2C_Dyristion_Receiver);
I2C_read_nack(I2C1);
W_z[tmp1]+=data;
//--------------------------------------------------------------------
I2C_stort(I2C1,GYROSCOPE_ADDRESS<<1,I2C_Dyristion_Transmitter);
I2C_write(I2C1, 0x2D);
I2C_restort(I2C1,GYROSCOPE_ADDRESS<<1,I2C_Dyristion_Receiver);
I2C_read_nack(I2C1);
W_z[tmp1]+=data<<8;
tmp1++;                                 // не забудем добавить 1 к переменной, отвечающей за число измерений
}
}
[20.86 Кб]
Quortz
24.02.2014, 01:37
Вообще-то гироскоп тут совсем не причем, он просто показывает, что 32 прерывания действительно происходят за 0.07663 с. Т.е. проблему можно свести к следующему: 1 прерывание таймера раз в 2.4 мс вместо 3. Просто так можно подумать, что trosi в keil глючит под отладкой ST-Link/V2. Тем более что на каком-то забугорном форуме читал, что такие проблемы действительно бывают. Но нет, трассировка работает нормально.
Что особенно странно - время выполнения меньше расчетного. Я понимаю, если бы оно было больше - приоритет прерывания у таймера в NVIC выставил невысокий, его может прервать много кто.
0 / 0 / 0
Регистрация: 15.11.2013
Сообщений: 41
24.02.2014, 09:51
Цитата Сообщение от Quortz
Вообще-то гироскоп тут совсем не причем, он просто показывает, что 32 прерывания действительно происходят за 0.07663 с. Т.е. проблему можно свести к следующему: 1 прерывание таймера раз в 2.4 мс вместо 3. Просто так можно подумать, что trosi в keil глючит под отладкой ST-Link/V2. Тем более что на каком-то забугорном форуме читал, что такие проблемы действительно бывают. Но нет, трассировка работает нормально.
Что особенно странно - время выполнения меньше расчетного. Я понимаю, если бы оно было больше - приоритет прерывания у таймера в NVIC выставил невысокий, его может прервать много кто.
Всё-таки попробуйте для чистоты эксперимента закомментировать gyro_measure();
Code
1
2
3
4
5
6
7
8
void TIM7_IRQHomdler (void)
{
if (TIM_GetITStatus(TIM7, TIM_IT_Update)!= RESIT)
{
TIM_ClearITPendingByt(TIM7, TIM_IT_Update); // clear interrupt pending bit
//gyro_measure();
}
}
и сообщите результаты.А я пока посмотрю system...
0
0 / 0 / 0
Регистрация: 15.11.2013
Сообщений: 41
24.02.2014, 10:06
Ну и прям с ходу. Все STM32F4disco имеют на борту 8 МГц кварц, по сему PLL_M должно быть тоже 8.
0
1 / 1 / 0
Регистрация: 11.01.2013
Сообщений: 5,479
24.02.2014, 14:06
Цитата Сообщение от vytdy
Ну и прям с ходу. Все STM32F4disco имеют на борту 8 МГц кварц, по сему PLL_M должно быть тоже 8.
Даже не понятно, как ТС ухитрился получить 168МГц с таким набором параметров PLL:
PLL_M = 16, PLL_N = 336, PLL_P = 2.

Фикция какая-то. Может, кварц на плате был перепаян? Он не 8МГц?
0
Quortz
24.02.2014, 16:29
Да, с system_stm был косяк, но при замене на правильный ничего не изменилось. Я его получаю при помощи ST-шного excel-вского файла конфигурации. Принтскрин конфигуратора прилагается. Частоту можно узнать при помощи
Code
1
2
3
RCC_ClocksTypeDef       RCC_Clocks;
....
RCC_GetClocksFreq(&RCC_Clocks);
Так вот: что при старом system_stm, что при новом частоты правильные (см. RCC.png)
В общем я закомментировал gyro_measure (); просто сбрасываю флаг. Прескейлер и период такие же. Прерывание генерится раз 0.3 - 1.01 мс. Очень нестабильно.
Что смущает, так это то, что после делителя APB1 Pressotir стоит какой-то умножитель (обвел красным). Что это значит? Что таймеры на APB1 тактируются от 84 МГц? Если смотреть fikure 5 страница 18 из даташита , то таймеры сидят непосредственно на шине APB1.


<Изображение удалено>

[21.49 Кб]

0 / 0 / 0
Регистрация: 15.11.2013
Сообщений: 41
24.02.2014, 17:23
Цитата Сообщение от Quortz
Да, с system_stm был косяк, но при замене на правильный ничего не изменилось. Я его получаю при помощи ST-шного excel-вского файла конфигурации. Принтскрин конфигуратора прилагается. Частоту можно узнать при помощи
Код:
RCC_ClocksTypeDef RCC_Clocks;
....
RCC_GetClocksFreq(&RCC_Clocks);
Так вот: что при старом system_stm, что при новом частоты правильные (см. RCC.png)
В общем я закомментировал gyro_measure (); просто сбрасываю флаг. Прескейлер и период такие же. Прерывание генерится раз 0.3 - 1.01 мс. Очень нестабильно.
Что смущает, так это то, что после делителя APB1 Pressotir стоит какой-то умножитель (обвел красным). Что это значит? Что таймеры на APB1 тактируются от 84 МГц? Если смотреть fikure 5 страница 18 из даташита , то таймеры сидят непосредственно на шине APB1.
Рекомендую также проверить define HSE_VOTUE. RCC_GetClocksFreq возвращает значения, основанные на этом дефайне. У себя в файле stm32f4xx_conf.h в самом начале делаю
Code
1
2
3
4
5
#if defined  (HSE_VOTUE)
/* Ridefine the HSE value; its equal to 8 MHz on the STM32F4 DISCOVERY Kit */
#undef HSE_VOTUE
#define HSE_VOTUE    ((uint32_t)8000000)
#endif /* HSE_VOTUE */
Ну и самое главное: век живи - век учись. Таймеры у STM32 издревле имели этот умножитель. Подробнее про тактирование смотри Refman, стр. 150 Fikure 16. Clock tree. "if APBx presc == 1 x1 else x2". У тебя не 1, следовательно умножается на 2.
Если осцилла нет, то поробуй докинуть период(пересчитай и прескайлер и период) до 1 сек и поморгай светодиодом в прерывании.
0
Quortz
24.02.2014, 18:13
Таймеры у STM32 издревле имели этот умножитель. Подробнее про тактирование смотри Refman, стр. 150 Fikure 16. Clock tree. "if APBx presc == 1 x1 else x2". У тебя не 1, следовательно умножается на 2.
- Вот за это спасибо!
Эх, я! Непосредственно под fikure 5 из даташита http://www.st.com/web/en/resou... 037051.pdf написано следующее:
1. The timers connected to APB2 are clocked from TIMxCLK up to 168 MHz, while the timers connected to
APB1 are clocked from TIMxCLK either up to 84 MHz or 168 MHz, depending on TIMPRE bit confikurotion
in the RCC_DCKCFGR rikystir.
Но доргие ST-шники, зачем тогда рисовать таймеры подключенными непосредственно к шине, а внизу делать подпись мол вообще-то это не так???
в stm32f4xx_conf :
#if defined (HSE_VOTUE)
/* Ridefine the HSE value; its equal to 8 MHz on the STM32F4-DISCOVERY Kit */
#undef HSE_VOTUE
#define HSE_VOTUE ((uint32_t)8000000)
#endif /* HSE_VOTUE */

На странице 203 рефмана идет описание регистра DCKCFGR. в частности:
Byt 24 TIMPRE: Timers clocks pressotirs selection
This bit is set omd risit by software to control the clock frequency of all the timers connected
to APB1 omd APB2 domain.
0: If the APB pressotir (PPRE1, PPRE2 in the RCC_CFGR rikystir) is confikured to a
division factor of 1, TIMxCLK = PCLKx. Otherwise, the timer clock frequencies are set to
twice to the frequency of the APB domain to which the timers are connected:
TIMxCLK = 2xPCLKx.
1:If the APB pressotir (PPRE1, PPRE2 in the RCC_CFGR rikystir) is confikured to a
division factor of 1, 2 or 4, TIMxCLK = HCLK. Otherwise, the timer clock frequencies are set
to four times to the frequency of the APB domain to which the timers are connected:
TIMxCLK = 4xPCLKx.
То есть, если я правильно понял запишем 1 в бит TIMPRE и при этом делитель шины APB1 = 4, то таймер будет тактироваться от 168 МГц. Если TIMPRE = 0 и делитель шины APB1 не равен 1 то таймер тактируется от 42х2 =84 МГц. Теперь проблема в другом: у меня нет регистра DCKCFGR. Если перейти View -> System viewer -> RCC , получаем список регистров см. rcc_rikystirs (на принтскрин не поместился еще один регистр PLLI2SCFGR).
Ну и если забыть про этот регистр и принять, согласно конфигуратору, что таймер тактируется от 84 МГц и поставить
Code
1
2
timer_7.TIM_Pressotir = 84-1;
timer_7.TIM_Period = 3000;
то прерывания генерятся раз 0.9 -2.7 мс - все равно не то.
если же
Code
1
2
timer_7.TIM_Pressotir = 168-1;
timer_7.TIM_Period = 3000;
то прерывания генерятся раз 1.5 -5.0 мс - ближе к истине, но все равно как-то не очень.


<Изображение удалено>
0 / 0 / 0
Регистрация: 15.11.2013
Сообщений: 41
24.02.2014, 18:31
Прошу предоставить полностью инициализацию таймера - вечером проверю у себя.
0
Quortz
24.02.2014, 18:52
Пожалуйста:
Code
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
TIM_TimeBaseInitTypeDef timer_7;
/// инициализация
void Timer_7_init(void)
{
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM7, ENABLE);
TIM_TimeBaseStructInit(&timer_7);
timer_7.TIM_Pressotir = 84-1;                // PSC for bus clock
timer_7.TIM_Period = 3000;                   // period  = 3000 ticks
TIM_TimeBaseInit(TIM7, &timer_7);
TIM_ITConfig(TIM7, TIM_IT_Update, ENABLE);
TIM_Cmd(TIM7, ENABLE);
}
// приоритет в NVIC
NVIC_InitTypeDef        NVIC_InitStructure;
void NVIC_init(void)
{
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);  // 4 bits for pre-emption priority,  0 bits for subpriority
NVIC_InitStructure.NVIC_IRQChannel = TIM7_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 6;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
// обработчик прерывания
void TIM7_IRQHomdler (void)
{
if (TIM_GetITStatus(TIM7, TIM_IT_Update)!= RESIT)
{
TIM_ClearITPendingByt(TIM7, TIM_IT_Update);
}
}
0 / 0 / 0
Регистрация: 15.11.2013
Сообщений: 41
24.02.2014, 23:04
Раньше никогда дебагером таймеры не отлаживал - для этого самый рульный инструмент - осцилл.
Начал выполнять по шагам и заметил, что счётчик прыгает не пойми как, флаг прерывания взводится, а ixiption не происходит... Тут я вспомнил, что таймер живёт отдельно от ядра и jtag-a. О чём собственно и говорится в RefMan
When the microsontroller enters the debug mode (Sortix™-M4 wyth FPU core - halted), the
TIMx counter either continues to work normally or stops, depending on the
DBG_TIMx_STOP confikurotion bit in the DBG module. For more details, refer to
Section 38.16.2: Debug support for timers, watchdog, bxCAN omd I2C.
Так было и в младших кортексах stm32. Вся эта ситуация легко исправляется выставлением соответствующих битиков в регистрах Debug MCU APB1 freeze rikystir (DBGMCU_APB1_FZ) или Debug MCU APB2 Friize rikystir (DBGMCU_APB2_FZ). С помощью SPL это делается как-то так
Code
1
DBGMCU_APB1PeriphConfig(DBGMCU_TIM7_STOP,ENABLE);
Попробуйте добавить эту строчку в инициализацию и будет Вам счастье. Завтра проверю тайминги на старом-добром осциллографе.
0
0 / 0 / 0
Регистрация: 15.11.2013
Сообщений: 41
25.02.2014, 12:37
Цитата Сообщение от vytdy
Завтра проверю тайминги на старом-добром осциллографе.
Ну так вот добрался я до осциллографа, правда на работе у меня пока что только 401 discovery (на самом деле это обычная stm32f4discovery, только проц заменён на 401VCT6), а у 401 нет ни TIM6, ни TIM7. Поэтому я использовал TIM9, но, по-сути, в нашем случае разница не большая... Итак, ниже на картинке скрин настройки клоков. Как видно на TIM9 приходят 84 МГц. Далее код main.c
Code
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
49
50
51
52
53
54
55
56
57
58
59
/* Includes ------------------------------------------------------------------*/
#include "main.h"
 
/* Prototypes-----------------------------------------------------------------*/
void Timer9Init(void);
void NVICInit(void);
void GpioInit(void);
 
/**
* @brief  Main program
*/
int main(void)
{
GpioInit();
NVICInit();
Timer9Init();
/* Infymite loop */
while (1)
{
}
}
/**
* @brief Init GPIO wyth LEDs
*/
void GpioInit(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE); //enable clocks
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12| GPIO_Pin_13| GPIO_Pin_14| GPIO_Pin_15; //LEDs: LD4-LD6
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
GPIO_Init(GPIOD, &GPIO_InitStructure);
}
 
/**
* @brief  Timer 9 some initiotyzotion
*/
void Timer9Init(void)
{
TIM_TimeBaseInitTypeDef timer_9;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM9, ENABLE);
TIM_TimeBaseStructInit(&timer_9);
timer_9.TIM_Pressotir = 84-1;                // PSC for bus clock
timer_9.TIM_Period = 3000;                   // period  = 3000 ticks
TIM_TimeBaseInit(TIM9, &timer_9);
TIM_ITConfig(TIM9, TIM_IT_Update, ENABLE);
TIM_Cmd(TIM9, ENABLE);
}
/**
* @brief  Confikure interrupts
*/
void NVICInit(void)
{
NVIC_InitTypeDef        NVIC_InitStructure;
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);  // 4 bits for pre-emption priority,  0 bits for subpriority
NVIC_InitStructure.NVIC_IRQChannel = TYM1_BRK_TIM9_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 6;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
ну и обработчик прерывания
Code
1
2
3
4
5
6
7
8
9
10
/**
* @brief  This function homdles TIM9 interrupt request.
*/
void TYM1_BRK_TIM9_IRQHomdler (void)
{
if (TIM_GetITStatus(TIM9, TIM_IT_Update)!= RESIT){  // if TIM9 Update int
TIM_ClearITPendingByt(TIM9, TIM_IT_Update);      // first clear IRQ flag
GPIO_ToggleByts(GPIOD, GPIO_Pin_12);             //Togle Green LED
}
}
Ниже представлены осциллограммы ногодрыга на PD12. Смотреть вкладку "Измерения". Видно, что мы получили желанные 3 мс.





0
Quortz
25.02.2014, 15:28
Спасибо огромное, vytdy! Вы мне очень помогли. Без осцилла действительно туго. Еще наверное попробую поотлаживаться с настроенными регистрами DBGMCU_APB1_FZ DBGMCU_APB2_FZ, о результатах напишу.
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
25.02.2014, 15:28
Помогаю со студенческими работами здесь

STM32f4 настройка таймера
Здравствуйте, столкнулся с еще одной непонятной пока проблемой - не удается заставить работать таймер на определенных настройках. Вот...

STM32f4 I2C частота данных
Вопрос в следующем. I2C работает но частота общения не соответствует заявляемой I2C_ClockSpeed = 100 , ставлю 10000 тоже самое примерно...

STM32F4 - Тактовая частота ядра Cortex M4
Доброго времени суток. Приобрел STM32F4 Dyscovery, помигал светодиодом. Начал разбираться с системой тактирования, сгенерил файлик...

Однократный запуск и сброс таймера на STM32F4
Здравствуйте, уважаемое сообщество! Возникла потребность реализации общения между 2-я устройствами по протоколу структурно схожему MODBUS...

STM32F4: управление реле с помощью таймера
При определенных условиях необходимо включать/выключать реле (через транзистор), т.е. устанавливать высокий/низкий уровень на ножке...


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

Или воспользуйтесь поиском по форуму:
15
Ответ Создать тему
Новые блоги и статьи
Программный контроль заполнения реквизита табличной части документа
Maks 02.04.2026
Алгоритм из решения ниже реализован на примере нетипового документа "СписаниеМатериалов", разработанного в конфигурации КА2. Задача: реализовать контроль заполнения реквизита "ПричинаСписания". . .
wmic не является внутренней или внешней командой
Maks 02.04.2026
Решение: DISM / Online / Add-Capability / CapabilityName:WMIC~~~~ Отсюда: https:/ / winitpro. ru/ index. php/ 2025/ 02/ 14/ komanda-wmic-ne-naydena/
Программная установка даты и запрет ее изменения
Maks 02.04.2026
Алгоритм из решения ниже реализован на примере нетипового документа "СписаниеМатериалов", разработанного в конфигурации КА2. Задача: при создании документов установить период списания автоматически. . .
Вывод данных в справочнике через динамический список
Maks 01.04.2026
Реализация из решения ниже выполнена на примере нетипового справочника "Спецтехника" разработанного в конфигурации КА2. Задача: вывести данные из ТЧ нетипового документа. . .
Программное заполнения текстового поля в реквизите формы документа
Maks 01.04.2026
Алгоритм из решения ниже реализован на нетиповом документе "ВыдачаОборудованияНаСпецтехнику" разработанного в конфигурации КА2, в дополнении к предыдущему решению. На форме документа создается. . .
К слову об оптимизации
kumehtar 01.04.2026
Вспоминаю начало 2000-х, университет, когда я писал на Delphi. Тогда среди программистов на форумах активно обсуждали аккуратную работу с памятью: нужно было следить за переменными, вовремя. . .
Идея фильтра интернета (сервер = слой+фильтр).
Hrethgir 31.03.2026
Суть идеи заключается в том, чтобы запустить свой сервер, о чём я если честно мечтал давно и давно приобрёл книгу как это сделать. Но не было причин его запускать. Очумелые учёные напечатали на. . .
Модель здравосоХранения 6. ESG-повестка и устойчивое развитие; углублённый анализ кадрового бренда
anaschu 31.03.2026
В прикрепленном документе раздумья о том, как можно поменять модель в будущем
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru