硬汉嵌入式论坛

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

求助!AD7606的FIFO模式无法正常工作。

[复制链接]

1

主题

8

回帖

11

积分

新手上路

积分
11
发表于 2024-4-8 22:22:11 | 显示全部楼层 |阅读模式
本帖最后由 习惯了寂寞 于 2024-4-8 22:29 编辑

参考AD7606模块的资料,将程序移植到STM32F407ZGT6上,用于驱动AD7606。如图片所示,软件定时获取方式采集1 KHz的正弦波正常;但使用FIFO模式时,采集的结果完全看不懂,尝试过多种不同速率采集,波形始终不对。
硬件是自己设计的,其中ADC的CONVT引脚与PB15相连,BUSY引脚与PB13相连。
在这里,小可先感谢各位大神百忙之中的指点了!
代码采用库函数编写,相关配置代码如下。
AD7606.c文件里的相关函数。
/*------------------------------------------------------------------------------------------------------------------------------
*****-----功能介绍:配置硬件工作在自动采集模式,结果存储在FIFO缓冲区
*****-----函数  名:AD7606_EnterAutoMode()
*****-----入口参数:ulFreq : 采样频率,单位Hz,    1k,2k,5k,10k,20K,50k,100k,200k
*****-----返回  值:无
*****-----备    注:
                                     CONVST 引脚,PB15使用TIM12_CH2输出PWM脉冲,触发AD7606启动ADC转换。
                                     设置BUSY口线为下降沿中断。在中断服务程序保存ADC结果。
                                     配置PB15为复用功能,TIM12_CH2 . 执行后AD7606_Init()对PB15口线的配置将失效
------------------------------------------------------------------------------------------------------------------------------*/
void AD7606_EnterAutoMode(uint32_t _ulFreq)
{
    {
        GPIO_InitTypeDef GPIO_InitStructure;

        RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM12, ENABLE);//使能TIM12的时钟
        RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);//使能GPIOB的时钟

        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_15;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
        GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
        GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP ;
        GPIO_Init(GPIOB, &GPIO_InitStructure);
        
        GPIO_PinAFConfig(GPIOB, GPIO_PinSource15, GPIO_AF_TIM12);//Connect TIM12 pins to AF2
    }

    {
        TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
        TIM_OCInitTypeDef  TIM_OCInitStructure;//用于配置定制器的通道输出比较(Output Compare)功能。
        uint32_t uiTIMxCLK;//时钟周期
        uint16_t usPrescaler;//分频系数 [15:0]
        uint16_t usPeriod;//自动重载计数周期值 [15:0]

        //TIM_DeInit(TIM12);    //复位TIM定时器

/*------------------------------------------------------------------------------------------------------------------------------
            system_stm32f4xx.c 文件中 void SetSysClock(void) 函数对时钟的配置如下:

            HCLK = SYSCLK / 1     (AHB1Periph)
            PCLK2 = HCLK / 2      (APB2Periph)
            PCLK1 = HCLK / 4      (APB1Periph) 42 MHz

            因为APB1 prescaler != 1, 所以 APB1上的TIMxCLK = PCLK1 x 2 = SystemCoreClock / 2; 84 MHz
            因为APB2 prescaler != 1, 所以 APB2上的TIMxCLK = PCLK2 x 2 = SystemCoreClock;

            APB1 定时器有 TIM2, TIM3 ,TIM4, TIM5, TIM6, TIM6, TIM12, TIM13,TIM14
            APB2 定时器有 TIM1, TIM8 ,TIM9, TIM10, TIM11
------------------------------------------------------------------------------------------------------------------------------*/

        uiTIMxCLK = SystemCoreClock / 2;    //168000000/2=84000000 Hz

        if (_ulFreq < 3000)//采样频率小于3 KHz
        {
            usPrescaler = 100 - 1;                    /* 分频比 = 10 */
            usPeriod =  (uiTIMxCLK / 100) / _ulFreq  - 1;        /* 自动重装的值 */
        }
        else    /* 大于4K的频率,无需分频 */
        {
            usPrescaler = 0;                    /* 分频比 = 1 */
            usPeriod = uiTIMxCLK / _ulFreq - 1;    /* 自动重装的值 */
        }

        /* Time base configuration */
        TIM_TimeBaseStructure.TIM_Period = usPeriod;
        TIM_TimeBaseStructure.TIM_Prescaler = usPrescaler;
        TIM_TimeBaseStructure.TIM_ClockDivision = 0;
        TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;

        TIM_TimeBaseInit(TIM12, &TIM_TimeBaseStructure);
        
        /* PWM1 Mode configuration: Channel1 */
        TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;                             //PWM调试模式1
        TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;    //比较输出使能
        TIM_OCInitStructure.TIM_Pulse = 4;                                                        //设置占空比为4个时钟周期
        TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low;            //输出极性低

        TIM_OC2Init(TIM12, &TIM_OCInitStructure);

        TIM_OC2PreloadConfig(TIM12, TIM_OCPreload_Enable);

        TIM_ARRPreloadConfig(TIM12, ENABLE);

        TIM_Cmd(TIM12, ENABLE);
    }

    /* 配置PB13, BUSY 作为中断输入口,下降沿触发 */
    {
        EXTI_InitTypeDef   EXTI_InitStructure;
        GPIO_InitTypeDef   GPIO_InitStructure;
        NVIC_InitTypeDef   NVIC_InitStructure;

        RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);

        /* Configure PB13 pin as input floating */
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;
        GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13;
        GPIO_Init(GPIOB, &GPIO_InitStructure);

        /* Connect EXTI Line13 to PB13 pin */
        SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOB, EXTI_PinSource13);

        /* Configure EXTI Line13 */
        EXTI_InitStructure.EXTI_Line = EXTI_Line13;
        EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
        EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;

        //EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;
        EXTI_InitStructure.EXTI_LineCmd = ENABLE;
        EXTI_Init(&EXTI_InitStructure);

        /* Enable and set EXTI Line6 Interrupt to the lowest priority */
        NVIC_InitStructure.NVIC_IRQChannel = EXTI15_10_IRQn;
        NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x00;
        NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x00;
        NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
        NVIC_Init(&NVIC_InitStructure);
    }
}

/*------------------------------------------------------------------------------------------------------------------------------
*****-----功能介绍:定时采集中断服务程序
*****-----函数  名:AD7606_ISR()
*****-----入口参数:无
*****-----返回  值:无
*****-----备    注:
------------------------------------------------------------------------------------------------------------------------------*/
void AD7606_ISR(void)
{
    uint8_t i;

    AD7606_ReadNowAdc();

    for (i = 0; i < 8; i++)
    {
        g_tAdcFifo.sBuf[g_tAdcFifo.usWrite] = g_tAD7606.sNowAdc;
        if (++g_tAdcFifo.usWrite >= ADC_FIFO_SIZE)
        {
            g_tAdcFifo.usWrite = 0;
        }
        
        if (g_tAdcFifo.usCount < ADC_FIFO_SIZE)
        {
            g_tAdcFifo.usCount++;
        
//            SEGGER_RTT_Write(1, &g_tAD7606.sNowAdc[0], 2);
//            SEGGER_RTT_Write(1, &g_tAD7606.sNowAdc[1], 2);
//            SEGGER_RTT_Write(1, &g_tAD7606.sNowAdc[2], 2);
//            SEGGER_RTT_Write(1, &g_tAD7606.sNowAdc[3], 2);
//            SEGGER_RTT_Write(1, &g_tAD7606.sNowAdc[4], 2);
//            SEGGER_RTT_Write(1, &g_tAD7606.sNowAdc[5], 2);
//            SEGGER_RTT_Write(1, &g_tAD7606.sNowAdc[6], 2);
//            SEGGER_RTT_Write(1, &g_tAD7606.sNowAdc[7], 2);
            
            SEGGER_RTT_Write(1, &g_tAD7606.sNowAdc[3], 2);
        }
        else
        {
            g_tAdcFifo.ucFull = 1;        //FIFO 满,主程序来不及处理数据
        }
    }
}

/*------------------------------------------------------------------------------------------------------------------------------
*****-----功能介绍:外部中断服务程序入口
*****-----函数  名:EXTI15_10_IRQHandler()
*****-----入口参数:无
*****-----返回  值:无
*****-----备    注:PB13/AD7606_BUSY 下降沿中断触发
------------------------------------------------------------------------------------------------------------------------------*/
void EXTI15_10_IRQHandler(void)
{
    if (EXTI_GetITStatus(EXTI_Line13) != RESET)
    {
        AD7606_ISR();
        EXTI_ClearITPendingBit(EXTI_Line13);//Clear the EXTI line 13 pending bit
    }
}

main.c里的调用函数
int main(void)
{
    u8 ucFifoMode=0;
    int16_t sNowAdc3=0;
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);    //设置系统中断优先级分组2
    delay_init(168);                                                                //延时初始化
    uart_init(115200);                                                            //串口初始化波特率为115200
    LED_Init();                                                                          //初始化与LED连接的硬件接口  
    ucFifoMode = 1;     
    AD7606_Init();                                                                    //配置AD7606所用的GPIO
    AD7606_SetOS(AD_OS_X4);                                                    //无过采样
    AD7606_SetInputRange(0);                                                //±5V
    AD7606_StartConvst();                                                        //启动1次转换
    //SEGGER_RTT_ConfigUpBuffer(1, "JScope_i2i2i2i2i2i2i2i2", g_tAD7606.sNowAdc, 2048, SEGGER_RTT_MODE_NO_BLOCK_SKIP);
    SEGGER_RTT_ConfigUpBuffer(1, "JScope_i2", g_tAD7606.sNowAdc, 2048, SEGGER_RTT_MODE_NO_BLOCK_SKIP);
   
    while(1)
    {               
        if(ucFifoMode == 0)//AD7606 普通工作模式
        {
            if(CONV_FLAG !=0 )//每隔500ms 进来一次. 由软件启动转换
            {
                AD7606_ReadNowAdc();        //读取采样结果
                AD7606_StartConvst();        // 启动下次转换
                CONV_FLAG=0;
                 SEGGER_RTT_Write(1, &g_tAD7606.sNowAdc[3], 2);
            }
        }
        else
        {
            AD7606_StartRecord(1000);//启动  采样速率
            AD7606_SetOS(AD_OS_NO);   
        }   
    }
}


1.png
2.jpg
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
106757
QQ
发表于 2024-4-9 08:54:35 | 显示全部楼层
估计是FIFO处理不及时,缓存数据损坏了。当前配置速度多少采集的。
回复

使用道具 举报

1

主题

8

回帖

11

积分

新手上路

积分
11
 楼主| 发表于 2024-4-9 09:54:49 | 显示全部楼层
eric2013 发表于 2024-4-9 08:54
估计是FIFO处理不及时,缓存数据损坏了。当前配置速度多少采集的。

感谢您的回复。图片中我配置的采集速度是1KHz。但采用50Hz-100KHz任意值结果都是差不多,无论是采集正弦波还是方波,结果都是不正常的,但能看出输入波形是方波还是正弦波。
此外,我这边缓冲大小最大只能配置为4096,启动文件中的堆栈大小也是修改了的。
SEGGER_RTT_ConfigUpBuffer(1, "JScope_i2", g_tAD7606.sNowAdc, 4096, SEGGER_RTT_MODE_NO_BLOCK_SKIP);
如果超过该值,就会提示图片中的内容“找不到RTT控制块”。
3.png
回复

使用道具 举报

1

主题

8

回帖

11

积分

新手上路

积分
11
 楼主| 发表于 2024-4-9 15:50:38 | 显示全部楼层
问题应该是由于我是用的老版本的库函数配置的FSMC,其中没有:
hsram.Init.ContinuousClock    = FSMC_CONTINUOUS_CLOCK_SYNC_ONLY; /* 仅同步模式才做时钟输出 */
hsram.Init.WriteFifo          = FSMC_WRITE_FIFO_ENABLE;          /* 使能写FIFO */
这两项相关的配置。
不过目前暂时还没有找到库函数如何使用FIFO
回复

使用道具 举报

1

主题

8

回帖

11

积分

新手上路

积分
11
 楼主| 发表于 2024-4-9 22:42:25 | 显示全部楼层
确认了,就是上面的问题。感谢硬汉哥的指点
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
106757
QQ
发表于 2024-4-10 08:34:54 | 显示全部楼层
习惯了寂寞 发表于 2024-4-9 09:54
感谢您的回复。图片中我配置的采集速度是1KHz。但采用50Hz-100KHz任意值结果都是差不多,无论是采集正弦 ...

缓存些数据,串口打印即可
回复

使用道具 举报

0

主题

1

回帖

1

积分

新手上路

积分
1
发表于 2024-4-18 16:22:40 | 显示全部楼层
兄弟,我最近也在做这个ad7606数据采集,然后将数据通过串口发送到上位机,请问你调试好了吗,可以借鉴一下吗
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2024-5-4 21:36 , Processed in 0.196080 second(s), 29 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

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