Формула последовательного регистра COM
Я работаю над atmega328p, учусь использовать его регистры вместо кодирования с помощью обычного кода Arduino.
Я нашел эту формулу для получения скорости передачи данных на последовательном порту (используя протокол USART):
как я могу набрать это на языке C? или конкретно в arduino IDE?
--
Я провел некоторые исследования и обнаружил, что это можно записать таким образом:
float _baudrate = (16000000/(16*9600));
затем я преобразую значение в int (потому что мне нужно целочисленное значение)
int _baudrate_int = (int)_baudrate;enter code here
Все это, конечно, для скорости 9600 бод.
Но когда я это делаю, я не понимаю почему, код не вычисляет правильно. У меня должно быть 103-104, а я получаю 710.
Это сработает, если я вручную введу (16*9600) product. То есть 153600
float _baudrate = (16000000/153600);
затем я получаю правильный результат скорости передачи данных. но что, если я хочу, чтобы код все рассчитал? как мне это сделать?
где моя ошибка в этой строке кода?
float _baudrate = (16000000/(16*9600));
@gowb0w, 👍0
Обсуждение1 ответ
Лучший ответ:
Здесь:
float _baudrate = (16000000/(16*9600)
за исключением отсутствующих скобок и точки с запятой, у вас есть целое число
переполнение. Проблема в том, что на Arduino на базе AVR int
доступен только
16-битная длина. Константы 16
и 9600
достаточно малы, чтобы поместиться
int
, им неявно дается тип int
. Затем их
Умножение также выполняется с типом int
, а произведение
переполняется и обертывается по модулю 216 до 22528.
Вы можете исправить это, указав один или оба этих числа как L
суффикс, который заставит их использовать тип данных long
. В качестве альтернативы, если
Если вам нужно вычисление с плавающей точкой, вы можете использовать .0
в качестве суффикса.
Не то чтобы avr-libc предоставлял заголовочный файл с некоторыми макросами для этого расчет, который затем выполняется препроцессором: <util/setbaud.h>: Вспомогательные макросы для скорости передачи данных расчеты. Вы можете использовать их следующим образом:
#define BAUD 9600
#include <util/setbaud.h>
void set_baud_rate() {
UBRR0 = UBRR_VALUE;
#if USE_2X
UCSR0A |= _BV(U2X0);
#else
UCSR0A &= ~_BV(U2X0);
#endif
}
Редактировать:
Отвечая на вопрос в комментарии: да, суффикс L
создает
long
константа, и таким образом это похоже на создание long
переменной
(за исключением того, что это константа, а не переменная).
Я предлагаю вам взглянуть на строку ниже из setbaud.h. В случае где U2X0 не требуется, значение регистра скорости передачи данных вычисляется как:
#define UBRR_VALUE (((F_CPU) + 8UL * (BAUD)) / (16UL * (BAUD)) -1UL)
Несколько вещей, на которые следует обратить внимание:
- Все это вычисляется с помощью целых чисел, без плавающей точки. На самом деле, вычисления выполняются компилятором во время сборки, а не Ардуино.
- Суффикс
UL
означаетunsigned long
- Добавление 8 перед делением на 16 — это способ округлить результат до Ближайшее целое число, вместо округления до нуля. Равенства округляются в большую сторону.
- В конце есть
-1UL
, так как это требуется для оборудования UART. (он есть в формуле из таблицы данных).
Да, я знаю, что не хватает скобок и точки с запятой. Просто неправильно нажал ctrl+c ctrl+v., @gowb0w
Я добавил суффикс L, и это сработало. Впечатляет, это работает! И я понимаю, что вы объяснили, и тот факт, что это заставит их использовать длинный тип данных. У меня есть еще один небольшой вопрос: добавление суффикса L — это то же самое, что и добавление другой переменной и придание ей значения = (длинная)переменная? Если вы понимаете, о чем я, @gowb0w
да, я понимаю. та же формула с добавлением 8 и присвоением ей длинного типа перед округлением и преобразованием в целое число., @gowb0w
- устаревшее преобразование из строковой константы в 'char*'
- Как запрограммировать ардуино на чистом C/C++?
- Количество элементов в массиве char
- Регистры ввода-вывода SAM3X8E (Arduino Due)
- как быстро loop() работает в Arduino
- Arduino: как получить тип платы в коде
- Как вызвать функции C из скетча ардуино?
- Как преобразовать полезную нагрузку byte* в строку
как бы вы это сделали на бумаге?, @jsotola
Добро пожаловать на SE/Arduino! Пожалуйста, пройдите [тур], чтобы узнать, как работает этот сайт, и прочитайте "[спросить]". Затем вернитесь и [отредактируйте] свой вопрос, чтобы указать источник, который у вас есть на данный момент. Пожалуйста, укажите, где именно вы спотыкаетесь. Кстати, общие вопросы по C лучше задавать на [so], особенно если они не имеют отношения к Arduino. Но здесь все в порядке, поскольку вы спрашиваете об Arduino IDE. Вы знаете, что программируете на C++, если используете Arduino IDE? C++ и C — это разные языки., @the busybee