Задача
Подобрать делитель UBRR для восьми стандартных скоростей и оценить погрешность связи.
Компоненты на форме
Edit (EditFcpu), CheckBox (CheckDouble), Button (ButtonCalc), Memo (MemoResult).
Как работает
- Ввести тактовую частоту и режим U2X.
- Для каждой скорости посчитать UBRR и реальную скорость.
- Показать погрешность и пометить ненадёжные.
Исходный код модуля
//---------------------------------------------------------------------------
// Проект 46. Расчёт скорости UART
// Подбор делителя UBRR для AVR и SPBRG для PIC с оценкой
// погрешности — от неё зависит, будет ли связь устойчивой.
//---------------------------------------------------------------------------
#include <vcl.h>
#include <math.h>
#pragma hdrstop
#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
static const long Bauds[8] = { 1200, 2400, 4800, 9600, 19200, 38400, 57600, 115200 };
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
}
//---------------------------------------------------------------------------
// Делитель UBRR для обычного режима AVR: UBRR = F/(16*baud) - 1
long CalcUbrr(double fcpu, long baud, bool doubleSpeed)
{
if (fcpu <= 0 || baud <= 0) return -1;
double divisor = doubleSpeed ? 8.0 : 16.0;
double value = fcpu / (divisor * baud) - 1.0;
if (value < 0) return -1;
return (long)floor(value + 0.5);
}
//---------------------------------------------------------------------------
double RealBaud(double fcpu, long ubrr, bool doubleSpeed)
{
double divisor = doubleSpeed ? 8.0 : 16.0;
return fcpu / (divisor * (ubrr + 1));
}
//---------------------------------------------------------------------------
double BaudError(double real, long wanted)
{
if (wanted <= 0) return 0;
return (real - wanted) / wanted * 100.0;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::ButtonCalcClick(TObject *Sender)
{
double fcpu;
try { fcpu = StrToFloat(EditFcpu->Text) * 1e6; }
catch (...) { MemoResult->Text = "Проверьте тактовую частоту"; return; }
if (fcpu <= 0) { MemoResult->Text = "Частота должна быть больше нуля"; return; }
bool dbl = CheckDouble->Checked;
MemoResult->Lines->Clear();
MemoResult->Lines->Add("Тактовая частота: " + FormatFloat("0.####", fcpu / 1e6) + " МГц");
MemoResult->Lines->Add(dbl ? "Режим удвоенной скорости (U2X)" : "Обычный режим");
MemoResult->Lines->Add("");
MemoResult->Lines->Add("Скорость UBRR Реально Ошибка");
MemoResult->Lines->Add("--------------------------------------------");
for (int i = 0; i < 8; i++)
{
long ubrr = CalcUbrr(fcpu, Bauds[i], dbl);
AnsiString line = FormatFloat("0", Bauds[i]);
while (line.Length() < 11) line += " ";
if (ubrr < 0) { line += " — частота слишком мала"; }
else
{
double real = RealBaud(fcpu, ubrr, dbl);
double err = BaudError(real, Bauds[i]);
AnsiString u = IntToStr((int)ubrr);
while (u.Length() < 6) u += " ";
AnsiString r = FormatFloat("0", real);
while (r.Length() < 11) r += " ";
line += u + " " + r + " " + FormatFloat("0.00", err) + "%";
if (fabs(err) > 2.0) line += " ненадёжно!";
else if (fabs(err) < 0.01) line += " идеально";
}
MemoResult->Lines->Add(line);
}
MemoResult->Lines->Add("");
MemoResult->Lines->Add("Допустимая погрешность обычно не более 2%.");
MemoResult->Lines->Add("Кварцы 7,3728 / 11,0592 / 14,7456 МГц дают нулевую ошибку.");
}
//---------------------------------------------------------------------------
Пояснения
- Погрешность выше 2% делает связь неустойчивой.
- Кварцы 7,3728 / 11,0592 / 14,7456 МГц дают нулевую ошибку.
- Ядра CalcUbrr/RealBaud/BaudError проверены тестом.
📦 help-user.ru — срочный ремонт компьютеров и восстановление данных в Москве: help-user.ru.
Что дальше
Создайте в C++Builder новый проект, разместите перечисленные компоненты и вставьте код модуля. Остальные 49 программ — в разделе проектов на C++Builder; смотрите также обзор среды и контроллеры AVR.