正弦曲线生成

主要为单片机开发,其占用 ROM 少,同时采用查表以减少运行时间
只保存四分之一的正弦波数据以供查表

可以通过PWM、DAC生成正弦波,实现SPWM、正弦波模拟信号等

qt5.13测试程软件,下面是源码

下图为一个正弦曲线周期

下图为一个正弦曲线周期的1/4部分

//SinCurve.h
#ifndef SINCURVE_H
#define SINCURVE_H

#include <QObject>

#define D_SIN_CURVE_BITS 16
struct SinCurve
{
public:
    /**
     * @brief SinCurve
     * @param D_BITS
     * @param size 2的次方
     */
    SinCurve(uint16_t size );
    /**
     * @brief CurveValue
     * @param index 取出曲线中的值
     * @return
     */
    uint16_t CurveValue( int index );
    uint16_t angleCurveValue( double angle );

    inline int tableSize(){return s_table_size;}
    inline uint16_t* table(){return s_table;}

    inline int indexSize(){return s_table_size<<2;}

private:
    /**
       * @brief baseCurveValue
       * @param type 曲线类型
       * @param index 取出曲线中的值
       * @return
       */
    uint16_t baseCurveValue( int type, int index );

public:
    /*
     * 整形数的连续位乘除均采用左移和右移,单片机可以单周期完成。

    如: x>>1==x/2;  x>>2==x/4; x>>3==x/8
    */

    uint16_t D_BITS; // 数组的位宽
    uint16_t D_BITS_MARK ; //
    uint16_t s_table_size; // 4分之1周期数组长度
    uint16_t sh_table_size; // 半周期数组长度
    uint16_t *s_table;//;
    uint16_t sbit_size; // 1周期精度
    uint16_t hbit_size; // 半周期
    uint16_t hmod; // 半周期

private:
    /**
     * @brief createrCurveTable  生成一个正弦周期的1/4正弦曲线数据


     * @param size 一维数组大小
     * @param s_table 数组指针
     */
    void createrCurveTable( int size, uint16_t *s_table );

};

#endif // SINCURVE_H

//SinCurve.cpp
#include "SinCurve.h"
#include <math.h>
#include <qdebug.h>

SinCurve::SinCurve( uint16_t size )
{
    this->D_BITS = D_SIN_CURVE_BITS; // 数组的位宽,最大16
    D_BITS_MARK = ((0x01<<D_SIN_CURVE_BITS)-1); //
    sbit_size=size+2;//1个周期的精度
    s_table_size = (uint16_t)powl(2,size); // 4分之1周期数组长度,长度越大曲线精度越高
    sh_table_size=s_table_size<<1; // 半周期数组长度
    s_table = new uint16_t[s_table_size] ; // 创建保存空间
    hbit_size=sbit_size-1;
    hmod=((0x01<<(hbit_size))-1);
    //  qDebug()<<D_BITS<<D_BITS_MARK<<s_table_size;
    createrCurveTable( s_table_size, s_table ); //生成数据

    //    // 1个正弦
    //    for ( int ik=0 ; ik<2; ik++)
    //    {
    //        for ( int i=0 ; i<sh_table_size; i++)
    //        {
    //            baseCurveValue( ik&0x01, i%(sh_table_size) );
    //        }
    //    }


    //    // 10个正弦
    //    for ( int ik=0 ; ik<20; ik++)
    //    {
    //        for ( int i=0 ; i<sh_table_size; i++)
    //        {
    //            baseCurveValue( ik&0x01, i%(sh_table_size) );
    //        }
    //    }
}



/**
* @brief createrCurveTable  生成一个正弦周期的1/4正弦曲线数据


* @param size 一维数组大小
* @param s_table 数组指针
*/
void SinCurve::createrCurveTable( int size, uint16_t *s_table )
{
    for(int i=0;i<size;i++)
    {
        //   qDebug()<<i<<D_BITS_MARK-(( sin(i*(M_PI/((size<<1)-1.0))+(M_PI/2.0)) +1)*(D_BITS_MARK>>1));
        s_table[i] = D_BITS_MARK-(( sin(i*(M_PI/((size<<1)-1.0))+(M_PI/2.0)) +1)*(D_BITS_MARK>>1));
    }
}


uint16_t SinCurve::CurveValue( int index )
{
    //   int max=sh_table_size;
    //  int mm=max-1;

    //int ik=index/max ;
    //int i=index%max ;

    int ik=index>>(hbit_size) ;//商
    int i=index&hmod ;//余数

    // qDebug()<<  Curve->baseCurveValue( ik&0x01, i%(Curve->size()*2) );
    return  baseCurveValue( ik&0x01, i );
}


uint16_t SinCurve::angleCurveValue( double angle )
{
    int i = indexSize()*angle/360.0 ;
    return CurveValue( i );
}

/**
 * @brief baseCurveValue
 * @param type 曲线类型
 * @param index 取出曲线中的值
 * @return
 */
uint16_t SinCurve::baseCurveValue( int type, int index )
{
#if 0
    if(type==0)// 加速
    {
        return s_table[index];
    }
    else// 减速
    {
        return D_BITS_MARK-s_table[index];
    }
#else

    // 4个像限
    if(type==0)//
    {
        if(index<s_table_size)//0-126
        {
            //qDebug()<<index;
            return s_table[index];
        }
        else if(index<(sh_table_size))
        {
            //qDebug()<<((sh_table_size)-1-index)<<index;
            return D_BITS_MARK-s_table[(sh_table_size)-1-index];
        }
    }
    else if(type==1)//
    {
        if(index<s_table_size)
        {
            return D_BITS_MARK-s_table[index];
        }
        else if(index<(sh_table_size))
        {
            return s_table[(sh_table_size)-1-index];
        }
    }
    else if(type==2)//
    {
        if(index<s_table_size)//0-127
        {
            return (D_BITS_MARK>>1)-s_table[s_table_size-index-1];
        }
        else if(index<(sh_table_size))//128-255//
        {
            return (D_BITS_MARK>>1)-s_table[ -s_table_size+index ];
        }
    }
    else
    {
        if(index<s_table_size)
        {
            return  s_table[s_table_size-index-1];
        }
        else if(index<(sh_table_size))
        {
            return  s_table[ -s_table_size+index ];
        }
    }
#endif
}

//mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include "SinCurve.h"

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = nullptr);
    ~MainWindow();

private slots:
    void on_pushButton_clicked();

    void on_pushButton_2_clicked();

    void on_pushButton_3_clicked();

    void on_pushButton_4_clicked();

private:
    Ui::MainWindow *ui;

    SinCurve *Curve;
};

#endif // MAINWINDOW_H

//mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"

#include "qdebug.h"


MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    Curve = nullptr;
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::on_pushButton_clicked()
{
    QString tempStr;
    for ( int ik=0 ,k=0; k<ui->spinBox_2->value() && ik<ui->spinBox->value()*Curve->indexSize(); ik++, k++)
    {
        tempStr+=QString::asprintf("%u\n", Curve->CurveValue( ik ) );
    }
    ui->plainTextEdit->appendPlainText(tempStr);
}

void MainWindow::on_pushButton_2_clicked()
{
    if(Curve!=nullptr)
        delete  Curve;

    Curve = new SinCurve( 6 );

    QString tempStr;
    uint16_t* temp=Curve->table();
    for ( int i=0 ,k=0; k<ui->spinBox_2->value() && i<Curve->tableSize(); i++,k++)
    {
        tempStr+=QString::asprintf("%u\n", temp[i] );
    }
    ui->plainTextEdit->appendPlainText(tempStr);

    ui->pushButton->setEnabled(true);
    ui->pushButton_3->setEnabled(true);
}

void MainWindow::on_pushButton_3_clicked()
{
    QString temp;
    double angle = Curve->indexSize()*ui->doubleSpinBox_2->value()/360.0 ;
    for ( double i = angle ,k=0; k<ui->spinBox_2->value() && i<Curve->indexSize()*ui->spinBox->value()+angle;
          i+=ui->doubleSpinBox_3->value(), k++ )
    {
        temp+=QString::asprintf("%u\n", Curve->CurveValue( i ));
    }
    ui->plainTextEdit->appendPlainText(temp);
}

void MainWindow::on_pushButton_4_clicked()
{
    ui->plainTextEdit->clear();
}

//mainwindow.ui

<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
 <class>MainWindow</class>
 <widget class="QMainWindow" name="MainWindow">
  <property name="geometry">
   <rect>
    <x>0</x>
    <y>0</y>
    <width>712</width>
    <height>635</height>
   </rect>
  </property>
  <property name="windowTitle">
   <string>MainWindow</string>
  </property>
  <widget class="QWidget" name="centralWidget">
   <layout class="QVBoxLayout" name="verticalLayout_2">
    <item>
     <widget class="QSplitter" name="splitter">
      <property name="orientation">
       <enum>Qt::Horizontal</enum>
      </property>
      <property name="handleWidth">
       <number>10</number>
      </property>
      <widget class="QPlainTextEdit" name="plainTextEdit"/>
      <widget class="QFrame" name="frame">
       <property name="frameShape">
        <enum>QFrame::StyledPanel</enum>
       </property>
       <property name="frameShadow">
        <enum>QFrame::Raised</enum>
       </property>
       <layout class="QVBoxLayout" name="verticalLayout">
        <item>
         <widget class="QPushButton" name="pushButton_2">
          <property name="text">
           <string>生成表</string>
          </property>
         </widget>
        </item>
        <item>
         <layout class="QGridLayout" name="gridLayout">
          <item row="0" column="2">
           <widget class="QPushButton" name="pushButton">
            <property name="enabled">
             <bool>false</bool>
            </property>
            <property name="text">
             <string>生成数据</string>
            </property>
           </widget>
          </item>
          <item row="1" column="1">
           <widget class="QDoubleSpinBox" name="doubleSpinBox_2">
            <property name="buttonSymbols">
             <enum>QAbstractSpinBox::NoButtons</enum>
            </property>
            <property name="decimals">
             <number>6</number>
            </property>
            <property name="maximum">
             <double>360.000000000000000</double>
            </property>
            <property name="singleStep">
             <double>0.000001000000000</double>
            </property>
           </widget>
          </item>
          <item row="2" column="0">
           <widget class="QLabel" name="label_3">
            <property name="text">
             <string>递进精度</string>
            </property>
           </widget>
          </item>
          <item row="0" column="1">
           <widget class="QSpinBox" name="spinBox">
            <property name="buttonSymbols">
             <enum>QAbstractSpinBox::NoButtons</enum>
            </property>
            <property name="minimum">
             <number>1</number>
            </property>
            <property name="maximum">
             <number>16</number>
            </property>
            <property name="value">
             <number>4</number>
            </property>
           </widget>
          </item>
          <item row="2" column="1">
           <widget class="QDoubleSpinBox" name="doubleSpinBox_3">
            <property name="buttonSymbols">
             <enum>QAbstractSpinBox::NoButtons</enum>
            </property>
            <property name="decimals">
             <number>6</number>
            </property>
            <property name="maximum">
             <double>360.000000000000000</double>
            </property>
            <property name="singleStep">
             <double>0.000001000000000</double>
            </property>
            <property name="value">
             <double>0.100000000000000</double>
            </property>
           </widget>
          </item>
          <item row="1" column="0">
           <widget class="QLabel" name="label_2">
            <property name="text">
             <string>开始相位</string>
            </property>
           </widget>
          </item>
          <item row="0" column="0">
           <widget class="QLabel" name="label">
            <property name="text">
             <string>周期</string>
            </property>
           </widget>
          </item>
          <item row="3" column="0">
           <widget class="QLabel" name="label_4">
            <property name="text">
             <string>最大数据量</string>
            </property>
           </widget>
          </item>
          <item row="3" column="1">
           <widget class="QSpinBox" name="spinBox_2">
            <property name="buttonSymbols">
             <enum>QAbstractSpinBox::NoButtons</enum>
            </property>
            <property name="minimum">
             <number>1000</number>
            </property>
            <property name="maximum">
             <number>99999</number>
            </property>
            <property name="value">
             <number>20000</number>
            </property>
           </widget>
          </item>
          <item row="1" column="2" rowspan="3">
           <widget class="QPushButton" name="pushButton_3">
            <property name="enabled">
             <bool>false</bool>
            </property>
            <property name="sizePolicy">
             <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
              <horstretch>0</horstretch>
              <verstretch>0</verstretch>
             </sizepolicy>
            </property>
            <property name="text">
             <string>生成相
位数据</string>
            </property>
           </widget>
          </item>
         </layout>
        </item>
        <item>
         <widget class="QPushButton" name="pushButton_4">
          <property name="text">
           <string>清空</string>
          </property>
         </widget>
        </item>
        <item>
         <spacer name="verticalSpacer">
          <property name="orientation">
           <enum>Qt::Vertical</enum>
          </property>
          <property name="sizeHint" stdset="0">
           <size>
            <width>20</width>
            <height>40</height>
           </size>
          </property>
         </spacer>
        </item>
       </layout>
      </widget>
     </widget>
    </item>
   </layout>
  </widget>
  <widget class="QStatusBar" name="statusBar"/>
 </widget>
 <layoutdefault spacing="6" margin="11"/>
 <resources/>
 <connections/>
</ui>

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值