Ругается, каккую-то строку хочет …
sketch error: expected string-literal before ‘nop’
А дигиталрид эти отличия не воспринимает? Внутренняя частота LGT8 в два раза больше - 32 МГц.
Ругается, каккую-то строку хочет …
sketch error: expected string-literal before ‘nop’
А дигиталрид эти отличия не воспринимает? Внутренняя частота LGT8 в два раза больше - 32 МГц.
if (RND < 1) PORTB &= ~(1 << 2); // установить 0 в бите 2 (10-й пин), пара микросекунд
else PORTB |= (1 << 2); // установить 1 в бите 2 (10-й пин)
asm volatile(“nop”);
asm volatile(“nop”);
int dat = (PINB & (1 << 3));
// int dat = digitalRead(RANDOM_IN);
if (dat < 1) PORTD &= ~(1 << 5); // установить 0 в бите PD5 (5-й пин) - трансляция c 3-го бита PB
else PORTD |= (1 << 5); // установить 1 в бите PD5 (5-й пин)
Что с ней разбираться? Ставишь STM32CubeIDE и настраиваешь что тебе нужно от таймера. А в программе просто указываешь что сделать.
Опиши свою хотелку подробно.
Если завтра будет время, намалюю тебе в стм.
Ну завтра уже 31-е, вроде кто-то уже пьёт ) … (но не я). И тут с дигиталридом тоже работает.
Нужны 3 выхода +1:
if (RND < 1 && RND_OLD < 1) PORTD = PORTD^0b01000000; // смена уровня на выходе в начале бита данных, если второй 0 подряд
if (RND > 0) PORTD = PORTD^0b01000000; // смена уровня на выходе в середине бита по спаду CLC , т.е. CLC должен быть меандром
ну и с выхода данных (RND) через резистор на другой пин (чтобы можно было вместо внутреннего RND подавать внешние данные и чтобы эти if’ы уже их обрабатывали. Просто транслировать RND с выхода на другой вход и потом на другой выход.
блин, редактировать нельзя …
тактовая частота CLC (от 1 до желательно 100 кГц)
Похоже что-то с кавычками не так.
Пробуйте вручную набрать
Если и дальше будет ругаться, пробуйте просто несколько “nop” -ов, без volatile.
Да, кавычки.
С одним asm volatile(“nop”); ничего не меняется. С двумя - вообще другие данные получаются.
А с 5-ю нопами стало нормально
(просто сразу 5 поставил)
Команды прямого чтения/записи порта очень быстрые. Что бы что-то прочитать- сначала надо “надёжно” записать))
P.S.Извиняюсь, я ушёл. Если что - отвечу позже
Ну да, я тоже думал в эту сторону (последовательная запись в разные регистры), но недостаточно профессионально )
Я ставлю ”лайки” на полезные ответы, может ещё как-то надо выделить?
А ещё может быть задержка подачи сигнала на вход через резистор 3,9К. У пина ведь тоже есть входная ёмкость, хоть и маленькая. Я смотрю сигнал на выходе, а на входе он может немного запоздать. И ёмкость щупов осциллографа без делителя больше 100 пФ. Но и частоты вроде не бешеные мегагерцы … Надо будет потом попробовать просто замкнуть.
Итого:
Без нопов: - с резистором - задержка данных на такт (осциллограф ни при чём)
С одним нопом: - с резистором - задержка данных на такт
С 2-я нопами: - с резистором - данные искажаются (как и с двумя volatile)
С 3-я нопами: - с резистором - нормальная передача данных
С 4-я нопами: - с резистором - нормальная передача данных
С 5-ю нопами: - с резистором - нормальная передача данных
Обзор от ИИ
На Arduino нет встроенного “флага подтверждения записи” для аппаратного порта ![]()
ушёл спать …
Глянул даташит - нет не отличается. Всё так же, как на Атмеге328р.
Синхронизация перед чтением - максимум полтора такта. Т.е. 1 NOP-a должно хватить, если учесть, что инструкция тоже, выполняется не мгновенно.
Вообщем, 2 NOP-a должно хватить с запасом.
Остальное, видимо, задержка от RC.
Может, кто ещё чего умного скажет))
Вот код для Ардуино ИДЕ (нужно поставить аддон STM32Duino https://github.com/stm32duino/BoardManagerFiles/raw/main/package_stmicroelectronics_index.json )
#define analogPin PA0
void setup() {
// 1. Включаем тактирование для GPIOA и TIM1
RCC->APB2ENR |= RCC_APB2ENR_IOPAEN | RCC_APB2ENR_TIM1EN;
delayMicroseconds(10); // Даём время на стабилизацию тактирования
// 2. Настраиваем PA8 как альтернативную функцию для ШИМ
// Для PA8 используем регистр CRH (пины 8–15)
GPIOA->CRH &= ~(0x0F << ((8 - 8) * 4)); // Очищаем биты для PA8 (позиция 0 в CRH)
GPIOA->CRH |= (0x0A << ((8 - 8) * 4)); // CNF8=10, MODE8=11
// 3. Настройка параметров таймера
TIM1->PSC = 1; // Предделитель = 2 (тактовая = 72 МГц)
TIM1->ARR = 640; // Период: 640 тактов → 50 кГц
// 4. Настройка канала 1 для ШИМ Mode 1
TIM1->CCMR1 &= ~TIM_CCMR1_OC1M; // Очищаем поле OC1M
TIM1->CCMR1 |= TIM_CCMR1_OC1M_2 | TIM_CCMR1_OC1M_1; // OC1M = 110 (PWM Mode 1)
TIM1->CCMR1 |= TIM_CCMR1_OC1PE; // Включаем буферизацию (OC1PE = 1)
// 5. Включение выхода канала 1
TIM1->CCER |= TIM_CCER_CC1E; // CC1E = 1 (разрешаем выход канала 1)
// 6. Установка коэффициента заполнения 50 %
TIM1->CCR1 = 320;
// 7. ЗАПУСК ТАЙМЕРА: включаем счётчик и буферизацию ARR
TIM1->CR1 |= TIM_CR1_CEN | TIM_CR1_ARPE;
// 8. ЗАПУСК ВЫХОДА: для TIM1 ОБЯЗАТЕЛЬНО включаем основной выход
TIM1->BDTR |= TIM_BDTR_MOE;
}
void loop() {
static uint16_t oldValue;
uint16_t reg = analogRead(analogPin);
reg = map(reg, 0, 4096, 320, 32000);
// Думал вот так изменять частоту ШИМ, но у меня почему-то ошибка: error: expression cannot be used as a function
// @МММ больше в STM32 разбирается, может поможет.
/*
if (reg != oldValue) {
oldValue = reg;
TIM1->ARR = reg; // новое значение частоты
TIM1->CCR1 = (reg / 2); // сохраняем заполнение 50%
TIM1->CNT = 0; // сброс счетчика
*/
}
}
Так-то генерация есть, но у меня почему-то не получилось реализовать изменение частоты при чтении с аналогового порта (может сам разберешься или поможет кто). На твои “плюшки” времени не хватило… )
При счете 320 - максимальная частота (~100кГц), при счете 32000 - минимальная (~1кГц).
Покажи точно сообщение об ошибке. Судя по нему, проблема в синтаксисе и не имеет отношения к регистрам СТМ32
ЗЫ частоты как-то странно у тебя подсчитаны… При ARR =320 будет примерно 225 КГц, а не ~100k
Магия какая-то ))
При попытке повторить ошибку - всё откомпилировалось. Спасибо!
#define analogPin PA0
void setup() {
// 1. Включаем тактирование для GPIOA и TIM1
RCC->APB2ENR |= RCC_APB2ENR_IOPAEN | RCC_APB2ENR_TIM1EN;
delayMicroseconds(10); // Даём время на стабилизацию тактирования
// 2. Настраиваем PA8 как альтернативную функцию для ШИМ
// Для PA8 используем регистр CRH (пины 8–15)
GPIOA->CRH &= ~(0x0F << ((8 - 8) * 4)); // Очищаем биты для PA8 (позиция 0 в CRH)
GPIOA->CRH |= (0x0A << ((8 - 8) * 4)); // CNF8=10, MODE8=11
// 3. Настройка параметров таймера
TIM1->PSC = 1; // Предделитель = 2 (тактовая = 72 МГц)
TIM1->ARR = 640; // Период: 640 тактов → 50 кГц
// 4. Настройка канала 1 для ШИМ Mode 1
TIM1->CCMR1 &= ~TIM_CCMR1_OC1M; // Очищаем поле OC1M
TIM1->CCMR1 |= TIM_CCMR1_OC1M_2 | TIM_CCMR1_OC1M_1; // OC1M = 110 (PWM Mode 1)
TIM1->CCMR1 |= TIM_CCMR1_OC1PE; // Включаем буферизацию (OC1PE = 1)
// 5. Включение выхода канала 1
TIM1->CCER |= TIM_CCER_CC1E; // CC1E = 1 (разрешаем выход канала 1)
// 6. Установка коэффициента заполнения 50 %
TIM1->CCR1 = 320;
// 7. ЗАПУСК ТАЙМЕРА: включаем счётчик и буферизацию ARR
TIM1->CR1 |= TIM_CR1_CEN | TIM_CR1_ARPE;
// 8. ЗАПУСК ВЫХОДА: для TIM1 ОБЯЗАТЕЛЬНО включаем основной выход
TIM1->BDTR |= TIM_BDTR_MOE;
}
void loop() {
static uint16_t oldValue;
uint16_t reg = analogRead(analogPin);
reg = map(reg, 0, 4096, 320, 32000);
// Меняем частоту ШИМ
if (reg != oldValue) {
oldValue = reg;
TIM1->ARR = reg; // новое значение частоты
TIM1->CCR1 = (reg / 2); // сохраняем заполнение 50%
TIM1->CNT = 0; // сброс счетчика
}
}
Скетч использует 11600 байт (17%) памяти устройства. Всего доступно 65536 байт.
Глобальные переменные используют 1092 байт (5%) динамической памяти, оставляя 19388 байт для локальных переменных. Максимум: 20480 байт.
Генерацию ШИМ проверял, работу с аналоговым портом - нет (писал выше).
Ну и отлично. Явных ошибок в логике не вижу, правда правильность употребления имен регистров не проверял, полагаюсь на комментарии ![]()
Сброс счетчика в последней строке лишний.
И да, частоты посмотри
Во первых используется предделитель на 2 (хотел изначально уложить весь диапазон без map(), но понял что не получится, да и оставил):
А то, что при 320 100кГц - этого я не понял. В кубе было иначе. Возможно wiring какие-то вносит погрешности (я не нашел в аддоне где частота тактовая задается).
да, согласен
Ты в Ардуино собираешь? Посмотри в настройках платы частоту. Значение по умолчанию для блюпила в Кларковском аддоне сменили зачем-то с 72 МГц на 64Мгц. Возможно и в СТМ-овском тоже
Я у себя замучился каждый раз менять, забываешь же! - поправил в аддоне, чтобы дефолт был 72, как раньше