AFON//Радиотехник
C++Builder · проект 46/50

Расчёт скорости UART

Таблица UBRR и погрешность для восьми скоростей.

Задача

Подобрать делитель UBRR для восьми стандартных скоростей и оценить погрешность связи.

Компоненты на форме

Edit (EditFcpu), CheckBox (CheckDouble), Button (ButtonCalc), Memo (MemoResult).

Как работает

  1. Ввести тактовую частоту и режим U2X.
  2. Для каждой скорости посчитать UBRR и реальную скорость.
  3. Показать погрешность и пометить ненадёжные.

Исходный код модуля

//---------------------------------------------------------------------------
// Проект 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.