基于OpenHarmony操作系统的简易示波器开发心得(下) 原创

福州市凌睿智捷电子有限公司
发布于 2022-5-6 13:36
917浏览
0收藏

三、简易示波器功能的实现
1.峰值检测
通过查找ad采集的数据内的最大值和最小值,然后相减即得峰峰值。

{
        uint16_t i;
        float MAX=0,MIN=3500,Vpp=0; 
        for(i=0;i<Ns;i++)                    // 扫描ADC数组,获取最大值和最小值
        {
            if(arr[i]>MAX)          
                MAX=arr[i];
            if(arr[i]<MIN)
                MIN=arr[i];
        }
        Vpp=MAX-MIN;
        return Vpp;
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.

2.频率检测
通过FFT变换,FFT变换的数据需要两部分,实部和虚部,由于变换的是数据是AD采集的实数据,所以只需将采集的值存入实部,虚部存入零即可。通过变换将时域信号转换到频域,然后通过取模排序,然后计算即可得到频率。他的基本思想是把原始的 N 点序列,依次分解成一系列的短序列。充分利用 DFT 计算式中指数因子所具有的对称性质和周期性质,进而求出这些短序列相应的 DFT 并进行适当组合,达到删除重复计算,减少乘法运算和简化结构的目的。当N是素数时,可以将 DFT算转化为求循环卷积,从而更进一步减少乘法次数,提高速度。
(1)FFT变换函数

    if (isign != 1 && isign != -1) {//isign=1,正变换;isign=-1,逆变换 
        return;
    }
    const int Lv = mylog(n, 2);//蝶形级数 
    int L;//蝶形运算级数,用于循环
    int N;//蝶形运算数据量,用于循环 
    int distance;//蝶形运算两节点间的距离,用于循环(distance=N/2) 
    int group;//蝶形运算的组数 
    float tmpr1, tmpi1, tmpr2, tmpi2;//临时变量
    int i, j, k;
    for (i = 0; i < n; i++) {//数位倒读 
        j = rev(i, Lv);
        real_out[j] = real_in[i];
        imag_out[j] = imag_in[i];
    }
    L = 1;
    distance = 1;
    N = 2;
    group = n >> 1;
    for (; L <= Lv; L++) {//蝶形循环 
        for (i = 0; i < group; i++) {//每级蝶形各组循环 
            for (k = 0; k < distance; k++) {//每组蝶形运算 
                float theta = -2 * PI * k / N * isign;//旋转因子,逆变换的角度与正变换相反 
                tmpr1 = real_out[N * i + k];
                tmpi1 = imag_out[N * i + k];//X(k)
                tmpr2 = mycos(theta) * real_out[N * i + k + distance] - mysin(theta) * imag_out[N * i + k + distance];
                tmpi2 = mycos(theta) * imag_out[N * i + k + distance] + mysin(theta) * real_out[N * i + k + distance];//WN(k)*X(k+N/2)
                real_out[N * i + k] = tmpr1 + tmpr2;
                imag_out[N * i + k] = tmpi1 + tmpi2;//X(k)=X(k)+WN(K)*X(k+N/2)
                real_out[N * i + k + distance] = tmpr1 - tmpr2;
                imag_out[N * i + k + distance] = tmpi1 - tmpi2;//X(k+N/2)=X(k)-WN(K)*X(k+N/2)
                if (isign == -1) {//逆变换结果需除以N,即除以Lv次2 
                    real_out[N * i + k] *= 0.5;
                    imag_out[N * i + k] *= 0.5;
                    real_out[N * i + k + distance] *= 0.5;
                    imag_out[N * i + k + distance] *= 0.5;
                }
            }
        }
        N <<= 1;
        distance <<= 1;
        group >>= 1;
    }
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.

(2)取模运算函数

{
    uint16_t i=0;
    float Y,X,Mag;
  for (i=0; i < Ns/2; i++)
  {
    
       X =((float)y2r[i])/32768* Ns;
       Y = ((float)y2i[i])/32768* Ns;
       Mag = sqrt(X*X+ Y*Y)/Ns;         // 先平方和,再开方
       y2[i] = (uint32_t)(Mag*65536);           
    
  }
  y2[0] = y2[0]/2;      //直流
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.

(3)然后将FFT变换的幅值进行排序,同时也对他们的下标进行了排序,以便后续的计算,即除了直流信号的第一个频率点即为改信号的频率。

{
    uint16_t i,j;
    uint32_t temp1;
    
    for(i=0;i<Ns/2;i++)                     //下标赋初值
    {
        xb[i]=i;
    }
    for(j=0;j<(Ns/2-1);j++)                 // 冒泡排序
     { 
        for(i=1;i<(Ns/2-j-1);i++)       //直流项不参与排序  从第二项开始              
        { 
            if(y2[i]<y2[i+1]) 
            {               
                temp1=y2[i];                //交换数据
                y2[i]=y2[i+1]; 
                y2[i+1]=temp1;

                temp1=xb[i];                            //交换下标
                xb[i]=xb[i+1]; 
                xb[i+1]=temp1; 
            }        
        }                                                               
     }
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.

(4)通过计算即可得到频率,采样点数将采样频率进行平分,通过排序取得的幅值最大的那个点的下标进行相乘即为频率,1.47为补偿系数,因为ADS1256采集数据后有延时,导致进行FFT变换后所对应的幅值最大点的下标前移,导致计算频率时候会偏小。

    3.波形显示
    通过将采集的幅值进行计算,使最后的值在屏幕大小的范围内,进行描点画图。

    {
        uint16_t x;
        int y;
        y = (int) rawValue/30+30;   //data processing code
        if(y<0 || y > 240)
        y = lastY;
        //这里之所以是120-rawValue/280,与屏幕的扫描方向有关,如果出现上下颠倒的情况,可以改成120 + 
        if(firstPoint)//如果是第一次画点,则无需连线,直接描点即可
        {
            LCD_DrawPoint(0,y,color);
            lastX=0;
            lastY=y;
            firstPoint=0;
        }
        else
        {
            x=lastX+2;
            if(x<320)  //不超过屏幕宽度
            {
                LCD_DrawLine(lastX,lastY,x,y,color);
                lastX=x;
                lastY=y;
            }
            else  //超出屏幕宽度,清屏,从第一个点开始绘制,实现动态更新效果
            {
                //LCD_Fill(0, 0, LCD_W, LCD_H, LCD_WHITE);//清屏//清屏,白色背景
                LCD_DrawPoint(0,y,color);
                lastX=0;
                lastY=y;
            }
      }
    }
    
    • 1.
    • 2.
    • 3.
    • 4.
    • 5.
    • 6.
    • 7.
    • 8.
    • 9.
    • 10.
    • 11.
    • 12.
    • 13.
    • 14.
    • 15.
    • 16.
    • 17.
    • 18.
    • 19.
    • 20.
    • 21.
    • 22.
    • 23.
    • 24.
    • 25.
    • 26.
    • 27.
    • 28.
    • 29.
    • 30.
    • 31.
    • 32.

    4.LCD显示
    Gitee社区已有这部分源代码和说明文档,感兴趣的读者可以参考:https://gitee.com/Lockzhiner-Electronics/lockzhiner-rk2206-openharmony3.0lts/tree/master/vendor/lockzhiner/rk2206/samples/b4_lcd。
    四、心得体会
    通过OpenHarmony操作系统 + 小凌派-RK2206开发板进行项目开发,OpenHarmony的实时性好,稳定性高,瑞芯微RK2206芯片接口比较丰富,移植适配稳定性较好,整体开发进度比较顺利,开发的难度都集中在数据处理算法上。通过这一次的应用开发,整体上对OpenHarmony和国产芯片开发还是蛮认可的,是一次不错的学习体验,特此记录!

    ©著作权归作者所有,如需转载,请注明出处,否则将追究法律责任
    已于2023-2-2 10:23:09修改
    收藏
    回复
    举报
    回复
      相关推荐