硬汉嵌入式论坛

 找回密码
 立即注册
查看: 223|回复: 6
收起左侧

[有问必答] 求助,ad7606如何用407的hal库驱动

[复制链接]

2

主题

4

回帖

10

积分

新手上路

积分
10
发表于 2025-7-21 18:58:04 | 显示全部楼层 |阅读模式
如题,困扰多天,谢谢大佬们
回复

使用道具 举报

2

主题

4

回帖

10

积分

新手上路

积分
10
 楼主| 发表于 2025-7-22 02:43:59 | 显示全部楼层
大家来帮我看看吧,我目前看到git上有一个办法,没有配置spi,单纯靠gpio读取某个引脚的电平来读取ad7606的数据,不知道是否可行,代码如下
#include "ad7606.h"

FIFO_t g_tAD;            //定义一个数据交换缓冲区

/*采样率*/
static uint32_t     sample_freq;                     //采样率
static float32_t    Freq;                            //计算出的最大频率
static float32_t    Amplitude;                      //最大频率的幅值
static float32_t    DC_Component;                   //直流分量

/*定义使用中的数组大小和采样点数*/
#define sample_lenth 128                         //采样点数
static float32_t InPutBuffer[sample_lenth];       //定义输入数组 InPutBuffer     该数组是外部变量
static float32_t MidBuffer[sample_lenth];         //定义中间数组
static float32_t OutPutBuffer[sample_lenth/2];    //定义输出数组 OutPutBuffer    该数组是一个静态数组
static float32_t FreqBuffer[(sample_lenth/4)-1];       //定义除了直流分量之外的频域数组

/*定义滤波中使用的中间数组*/
#define Filter_average_num 4                             //平均滤波样本数量
float32_t Mid_Filter_Freq_Buffer[Filter_average_num];    //频率平均滤波时的中间数组


/*定义fft运算中的参数*/
uint32_t fftSize = 64;                          //FFT计算点数
uint32_t doBitReverse = 1;                      //按位取反
uint8_t ifftFlag = 0;                        //FFT变换标志,0表示FFT变换,1表示IFFT变换

/*定义计算结果存放*/
float32_t maxvalue;                             //计算出频域上最大值(包括直流分量)
uint32_t Index;                                 //最大值所在数组位置(包括直流分量)

float32_t Freq_maxvalue;                        //计算出频域上的最大值(不包括直流分量)
uint32_t Freq_Index;                            //最大值所在数组位置(不包括直流分量)

float32_t Virtual_value;                        //有效值
float32_t res;
/*定义完成转换的标志*/
static int fft_complete_flag;                   //定义转换完成标志

/**
* @brief 初始化ad7606
*/
void ad7606_init(void)
{
    ad7606_SetOS(0);    //设置过采样模式

    ad7606_Reset();     //复位ad7606

    AD_CONVST_HIGH();
   
}

/**
* @brief 复位ad7606
*/
void ad7606_Reset(void)
{
    /* AD7606高电平复位,最小脉冲要求50ns */

    AD_RESET_LOW();

    AD_RESET_HIGH();
    AD_RESET_HIGH();
    AD_RESET_HIGH();
    AD_RESET_HIGH();

    AD_RESET_LOW();
}

/**
* @brief 设置过采样模式
* @param ucMode 0表示无过采样 1表示2倍 2表示4倍 3表示8倍 4表示16倍 5表示32倍 6表示64倍
*/
void ad7606_SetOS(uint8_t _ucMode)
{
    if (_ucMode == 1)
    {
        AD_OS2_0();
        AD_OS1_0();
        AD_OS0_1();
    }
    else if (_ucMode == 2)
    {
        AD_OS2_0();
        AD_OS1_1();
        AD_OS0_0();
    }
    else if (_ucMode == 3)
    {
        AD_OS2_0();
        AD_OS1_1();
        AD_OS0_1();
    }
    else if (_ucMode == 4)
    {
        AD_OS2_1();
        AD_OS1_0();
        AD_OS0_0();
    }
    else if (_ucMode == 5)
    {
        AD_OS2_1();
        AD_OS1_0();
        AD_OS0_1();
    }
    else if (_ucMode == 6)
    {
        AD_OS2_1();
        AD_OS1_1();
        AD_OS0_0();
    }
    else
    {
        AD_OS2_0();
        AD_OS1_0();
        AD_OS0_0();
    }
}

/**
* @brief 启动adc转换
*/
void ad7606_StartConv(void)
{
    /* 上升沿开始转换,低电平至少持续25ns  */
    AD_CONVST_LOW();
    AD_CONVST_LOW();
    AD_CONVST_LOW();    /* 连续执行2次,低电平持续时间大约为50ns */
    AD_CONVST_LOW();
    AD_CONVST_LOW();
    AD_CONVST_LOW();
    AD_CONVST_LOW();
    AD_CONVST_LOW();
    AD_CONVST_LOW();

    AD_CONVST_HIGH();
}

/**
* @brief spi写数据
* @param data 待写入数据
*/
void SPI_SendData(uint16_t data)
{
    uint8_t count=0;
    AD_SCK_LOW();
    for(count=0;count<16;count++)
    {
        if(data&0x8000)
            AD_MISO_LOW();
        else
            AD_MISO_HIGH();
        data<<=1;
        AD_SCK_LOW();
        AD_CSK_HIGH();   
    }
}

/**
* @brief spi读数据
*/
uint16_t SPI_ReceiveData(void)
{
    uint8_t count=0;
    uint16_t Num=0;
    AD_CSK_HIGH();
    for(count=0;count<16;count++)
    {
        Num<<=1;
        AD_SCK_LOW();   
        if(AD_MISO_IN)Num++;
        AD_CSK_HIGH();
    }
    return(Num);
}

/**
* @brief 读取ADC采样结果
* @retval usData 采样结果
*/
uint16_t ad7606_ReadBytes(void)
{
    uint16_t usData = 0;

    usData = SPI_ReceiveData();

    /* Return the shifted data */
    return usData;
}

/**
* @brief 定时调用函数,用于读取ADC转换数据
*/
void ad7606_IRQSrc(void)
{
    uint8_t i;
    uint16_t usReadValue;
        static uint32_t j;

    /*
    读取数据
    示波器监视,CS低电平持续时间 35us
    */
    AD_CS_LOW();
    for (i = 0; i < CH_NUM; i++)
    {
        usReadValue = ad7606_ReadBytes();
        if (g_tAD.usWrite < FIFO_SIZE)
        {
            g_tAD.usBuf[g_tAD.usWrite] = usReadValue;
            ++g_tAD.usWrite;
        }
    }

    AD_CS_HIGH();
   
    //g_tAD.usWrite = 0;

    //FFT运算
    ad7606_StartConv();
        if( j < fftSize )
        {
            InPutBuffer[2*j] = ((float)((short)g_tAD.usBuf[0])/32768/2);         //数据存放在输入数组的偶数位
            InPutBuffer[2*j+1] = 0;                                              //奇数位置零
            g_tAD.usWrite = 0;
            j++;
        }
        else if( j == fftSize)
        {
            j = 0;
            if(fft_complete_flag == 0)
            {
                memcpy(MidBuffer,InPutBuffer,sizeof(InPutBuffer));  //将输入数组的值复制到中间数组              
                fft_complete_flag = 1;
            }
            else if(fft_complete_flag == 1)
            {
                fft_complete_flag = 1;
            }
            else
                printf("error");
        }
}

/**
* @brief 开始采集
*/
void ad7606_StartRecord(void)
{
    //ad7606_Reset();

    ad7606_StartConv();

    g_tAD.usRead = 0;
    g_tAD.usWrite = 0;

    MX_TIM4_Init();         //设置定时器4频率
    HAL_TIM_Base_Start_IT(&htim4);         //使能定时器4中断
}

/**
* @brief 停止采集
*/
void ad7606_StopRecord(void)
{
    HAL_TIM_Base_Stop_IT(&htim4);
}

/**
* @brief 获取单通道的AD采样平均值
* @param channal 选择通道,channal在1-8之间
* @param average_num 均值法的迭代次数
* @retval int_singal_sample_val
*/
int32_t ad7606_get_signal_average_val(int8_t channal,int8_t average_num)
{
    int i;
    float val = 0;                                                             //用于累加的中间变量
    int32_t int_singal_sample_val;
    for (i=0; i<average_num;i++)
    {
        val = val + ((float)((short)g_tAD.usBuf[channal-1])/32768/2);           //累加
    }
    g_tAD.usWrite = 0;
    int_singal_sample_val = ((int32_t)10000)*(val / average_num);           //得到平均值
    return int_singal_sample_val;
}


/**
* @brief 获得用于分析的数组,向数组InPutBuffer中填入数据
*/
void ad7606_get_fft_data()
{
        uint32_t i;
        for (i=0;i<fftSize;i++)                                                   
        {
        printf("%ld",i);
                InPutBuffer[2*i] = ((float)((short)g_tAD.usBuf[0])/32768/2);              
                InPutBuffer[2*i+1] = 0;
                g_tAD.usWrite = 0;
                HAL_Delay(1);
        }
}

/**
* @brief 对输入数组进行FFT运算。并且输出
                1、频率 Freq
                2、幅值 Amplitude
                3、直流分量 DC_Component
                4、周期均方(有效值)Virtual_value
*/
void fft_get_maxvalue()
{
        uint32_t k;
       
        if(fft_complete_flag == 1)
        {
                arm_cfft_f32(&arm_cfft_sR_f32_len64,MidBuffer,ifftFlag,doBitReverse);      //对输入数组进行FFT变换,变换结果将存放在输入数组中
       
            arm_cmplx_mag_f32(MidBuffer,OutPutBuffer,fftSize);                         //对经过FFT变换的数组进行取模运算,运算结果将存放在OutPutBuffer数组中
       
            arm_max_f32(OutPutBuffer,fftSize,&maxvalue,&Index);                        //输出数组中频域最大的数值和其所在数组中的位置

                for(k=0;k<(fftSize/2-1);k++)
                {
                        FreqBuffer[k] = OutPutBuffer[k+1];                                       //取输出结果的一半,并且去除直流分量
                }
               
                arm_max_f32(FreqBuffer,(fftSize/2-1),&Freq_maxvalue,&Freq_Index);          //去除直流分量后输出数组中频域最大的数值和其所在数组中的位置
               
                Freq = (Freq_Index+1)*((float)sample_freq/(float)fftSize);                 //频率 = (N-1)*Fs/FFTSize        单位Hz
               
                Amplitude = Freq_maxvalue/((float)fftSize/2)*10000;                        //频率幅度 = value/FFTSize/2*10   单位V
               
                DC_Component = OutPutBuffer[0]/fftSize*10000;                              //直流分量 = value/FFTSize
               
                Virtual_value = Amplitude/1.4142135;                                       //有效值
               
                res = ((Virtual_value-8)/43.3)/(4-((Virtual_value-8)/43.3))*2000;
               
                //printf("maxvalue = %f \r\n location = %d  \r\n",maxvalue,Index);
               
          printf("Fmaxvalue = %f \r\n Amplitude = %f  \r\n  DC_Component = %f  \r\n  Virtual_value = %f  \r\n Res = %f  \r\n  ",Freq,Amplitude,DC_Component,Virtual_value,res);
               
               
                fft_complete_flag = 0;                                                     //标志位置0,表示转换完成
               
        }
}

/**
* @brief        对fft产生的值进行滤波
*/
float32_t filter_fft()
{
        uint16_t j;
        float32_t sum=0;
        float32_t result=0;
       
        for(j=0;j<Filter_average_num;j++)
        {
                fft_get_maxvalue();
               
                sum = sum+Amplitude;
        }
       
        result = sum/4;
       
        printf("Amplitude = %f",result);
       
        return result;
}
回复

使用道具 举报

1万

主题

7万

回帖

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
117512
QQ
发表于 2025-7-22 09:40:58 | 显示全部楼层
qwer3838 发表于 2025-7-22 02:43
大家来帮我看看吧,我目前看到git上有一个办法,没有配置spi,单纯靠gpio读取某个引脚的电平来读取ad7606的 ...

HAL库的SPI接口驱动方式例子没做,FMC接口方式做了,此贴,供参考

【安富莱】V6,V5开发板用户手册,重在BSP驱动包设计方法,HAL库的框架学习,授人以渔,更新至50章(2023-10-24)
https://forum.anfulai.cn/forum.p ... 3255&fromuid=58
(出处: 硬汉嵌入式论坛)
回复

使用道具 举报

2

主题

4

回帖

10

积分

新手上路

积分
10
 楼主| 发表于 2025-7-22 16:55:15 | 显示全部楼层
eric2013 发表于 2025-7-22 09:40
HAL库的SPI接口驱动方式例子没做,FMC接口方式做了,此贴,供参考

【安富莱】V6,V5开发板用户手册, ...

哥很感谢,但我测试了发现我上面的方法也可以驱动,但我很疑惑为什么没进行任何spi配置也可以做到
回复

使用道具 举报

0

主题

8

回帖

8

积分

新手上路

积分
8
发表于 2025-7-23 08:50:38 | 显示全部楼层
qwer3838 发表于 2025-7-22 16:55
哥很感谢,但我测试了发现我上面的方法也可以驱动,但我很疑惑为什么没进行任何spi配置也可以做到

你上面的代码是软件模拟SPI实现的读取,不需要去配置硬件SPI
回复

使用道具 举报

2

主题

4

回帖

10

积分

新手上路

积分
10
 楼主| 发表于 2025-7-27 17:19:39 | 显示全部楼层
树梢的麻雀 发表于 2025-7-23 08:50
你上面的代码是软件模拟SPI实现的读取,不需要去配置硬件SPI

ok,很感谢您,请问ad7606最高采样率为200khz,是否以为最高只能读取100khz的信号
回复

使用道具 举报

1万

主题

7万

回帖

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
117512
QQ
发表于 2025-7-28 08:36:29 | 显示全部楼层
qwer3838 发表于 2025-7-27 17:19
ok,很感谢您,请问ad7606最高采样率为200khz,是否以为最高只能读取100khz的信号

读取最高200K
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|小黑屋|Archiver|手机版|硬汉嵌入式论坛

GMT+8, 2025-8-11 20:53 , Processed in 0.045151 second(s), 25 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

快速回复 返回顶部 返回列表