打印
[研电赛技术支持]

数模转换器(ADC):AD7606+GD32F407固件参考代码

[复制链接]
451|1
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
wakayi|  楼主 | 2024-10-30 14:37 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
项目上使用到该转换芯片,写点笔记,希望对大家有帮助。我接触这个芯片也就几天,整体来说,没寄存器,很好控制。但是我的代码仅提供思路,现在没有板子,不能验证。刚入职的硬件开发岗萌新,先写这么多,有机会再更新,如有错误地方请各位指正,谢谢。

1. 芯片关键参数介绍
        AD7606支持8通道模拟输入;7种过采样率设置;SPI/QSPI™/MICROWIRE™/DSP多种通信协议;模拟输入范围选择;参考电压选择。



  Pin OS0~PinOS2用于控制过采样率选择,OS2是MSB控制位,OS0是LSB控制位。可以根据需要选择硬件或者软件的方式控制过采样,真值表如下:



Pin6(PAR_N/SER/BYTE SEL)管脚用于选择通信方式,我这里用的是并行方式,直接将管脚接地即可。数据吞吐量大,GPIO口不够用则改用字节传输或者串行模式。
Pin7(STBY_N)用于选择省电模式,不在意功耗直接拉高即可,如果需要切换芯片工作模式,则需要配合使用RANG引脚。
Pin8(RANG)用于选择输入电压范围,RANG=0,输入电压范围是±5 V;RANG=1,输入电压范围是±10 V。
Pin9和Pin10(CONVST A, CONVST B)用于控制转换选择,A对应1234,B对应5678,通常直接将AB短接,一起控制,逻辑1表示开始转换,逻辑0表示未转换。
Pin12(RD_N/SCLK),并行模式下是读数据控制信号,低电平有效;串行模式下是时钟输出控制引脚。
Pin13(CS_N),片选引脚,并行模式下通常将其与Pin12短接,低电平有效。
Pin14(BUSY),在CONVST A, CONVST B的上升沿跳转为高电平,表示开始转换;所有通道转换结束后才转为低电平;下降沿表明数据已存储在输出寄存器。
Pin15(FRSTDATA):目前我觉得没用的引脚
    2. 时序分析
        首先是读数据的时机,可以在转换结束之后在读取本次转换结果,也可以在转换的过程中读取上一次的转换结果,分别对应下面图片中的Figure 2和Figure 3。区别在于前者在BUSY为低之后才拉低CS管脚开始读数据,而后者则是在BUSY期间就拉低了CS管脚进行读数据。注意:手册提到,在BUSY高时读取的任何数据必须在BUSY下降沿发生之前完成。当BUSY信号高时,CONVST A或CONVST B上的上升沿没有影响。



        下面是并行模式下读取数据的时序图,为了方便,直接将CS和RD管脚短接,一起控制数据读取过程。另外,根据该时序图和手册说明,FRSTDATA仅表示通道1的数据读取情况。



3. 参考代码
#管脚定义,根据自己的电路图做调整
uint16_t ADC_Data[8];

//尽量将控制Pins和数据Pins分别接到同名GPIO口
#define                ADC_DataPort                                        GPIOB                        //16 bits并行数据端口
#define                ADC_CtrlPort                                        GPIOC                        //其它的必要控制端口

//关键控制Pins
#define                ADC_RANG                                                GPIO_PIN_9                //输入电压范围选择;0:+-5V;1:+-10V
#define                ADC_STBY                                                GPIO_PIN_8                //下电模式选择;低电平有效;默认电平:1
#define                ADC_OS0                                                        GPIO_PIN_7      //默认电平:0
#define                ADC_OS1                                                        GPIO_PIN_6      //默认电平:0
#define                ADC_OS2                                                        GPIO_PIN_5      //默认电平:0
#define                ADC_RD                                                        GPIO_PIN_4      //读取和片选控制信号;低电平有效;默认电平:1
#define                ADC_RESET                                                GPIO_PIN_3      //复位信号;高电平有效;默认电平:0
//#define                ADC_FRSTDATA                                        GPIO_PIN_2      //低电平有效;默认电平:0
#define                ADC_BUSY                                                GPIO_PIN_1      //转换状态信号;输入0:转换结束;1:正在转换
#define                ADC_CONVST_AB                                        GPIO_PIN_0      //开始转换信号;高电平有效;默认电平:0

//用于设置over sampling率
#define                ADC_SetOS0()                                        gpio_bit_set(ADC_CtrlPort, ADC_OS0)
#define                ADC_SetOS1()                                        gpio_bit_set(ADC_CtrlPort, ADC_OS1)
#define                ADC_SetOS2()                                        gpio_bit_set(ADC_CtrlPort, ADC_OS2)
#define                ADC_ResetOS0()                                        gpio_bit_reset(ADC_CtrlPort, ADC_OS0)
#define                ADC_ResetOS1()                                        gpio_bit_reset(ADC_CtrlPort, ADC_OS1)
#define                ADC_ResetOS2()                                        gpio_bit_reset(ADC_CtrlPort, ADC_OS2)

#过采样率设置
/*!
    \brief        ADC过采样选择
    \param[in]    OS: 过采样率选择
                                  可选择参数:0、2、4、8、16、32、64
    \param[out]   无
    \retval       无
*/
void AD7606_SetOversampling(uint8_t OS)
{
    switch(OS)
    {
        case 0:  // 000
            ADC_ResetOS2();
            ADC_ResetOS1();
            ADC_ResetOS0();
            break;

        case 2:  // 001
            ADC_ResetOS2();
            ADC_ResetOS1();
            ADC_SetOS0();
            break;

        case 4:  // 010
            ADC_ResetOS2();
            ADC_SetOS1();
            ADC_ResetOS0();
            break;

        case 8:  // 011
            ADC_ResetOS2();
            ADC_SetOS1();
            ADC_SetOS0();
            break;

        case 16: // 100
            ADC_SetOS2();
            ADC_ResetOS1();
            ADC_ResetOS0();
            break;

        case 32: // 101
            ADC_SetOS2();
            ADC_ResetOS1();
            ADC_SetOS0();
            break;

        case 64: // 110
            ADC_SetOS2();
            ADC_SetOS1();
            ADC_ResetOS0();
            break;

        default: // default case
            ADC_ResetOS2();
            ADC_ResetOS1();
            ADC_ResetOS0();
            break;
    }
}

#AD7606初始化
/*!
    \brief        ADC初始化配置
    \param[in]    无
    \param[out]   无
    \retval       无
*/
void AD7606_Init(void)
{
        rcu_periph_clock_enable(ADC_DataPort | ADC_CtrlPort);
       
        //数据输入引脚配置
        gpio_mode_set(ADC_DataPort, GPIO_MODE_INPUT, GPIO_PUPD_NONE, GPIO_PIN_ALL);
       
        //输入反馈信号
        gpio_mode_set(ADC_CtrlPort, GPIO_MODE_INPUT, GPIO_PUPD_NONE, ADC_BUSY);
       
        //输出控制信号:默认低电平的信号
        gpio_mode_set(ADC_CtrlPort, GPIO_MODE_OUTPUT, GPIO_PUPD_PULLDOWN, ADC_RANG | ADC_OS0 | ADC_OS1 | ADC_OS2 | ADC_RESET | ADC_CONVST_AB);
        gpio_output_options_set(ADC_CtrlPort, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, ADC_RANG | ADC_OS0 | ADC_OS1 | ADC_OS2 | ADC_RESET | ADC_CONVST_AB);
       
        //输出控制信号:默认高电平的信号
        gpio_mode_set(ADC_CtrlPort, GPIO_MODE_OUTPUT, GPIO_PUPD_PULLUP, ADC_STBY | ADC_RD);
        gpio_output_options_set(ADC_CtrlPort, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, ADC_STBY | ADC_RD);
       
        //上电复位ADC芯片
        gpio_bit_set(ADC_CtrlPort, ADC_RESET);
        delay_1ms(1);
        gpio_bit_reset(ADC_CtrlPort, ADC_RESET);
}

#AD7606转换的开始和结束
/*!
    \brief        ADC开始转换
        \param[in]    无
    \param[out]   无
    \retval       无
*/
void AD7606_StartConv(void)
{
        gpio_bit_set(ADC_CtrlPort, ADC_CONVST_AB);
}

/*!
    \brief        ADC结束转换
        \param[in]    无
    \param[out]   无
    \retval       无
*/
void AD7606_StopConv(void)
{
        gpio_bit_reset(ADC_CtrlPort, ADC_CONVST_AB);
}

#省电模式选择
void AD7606_SwitchPowerDownMode(uint8_t Mode)
{
    switch(Mode)
    {
        case 1  :
            gpio_bit_reset(ADC_CtrlPort, ADC_STBY);
            gpio_bit_set(ADC_CtrlPort, ADC_RANG);
            break;

        case 0  :
            gpio_bit_reset(ADC_CtrlPort, ADC_STBY);
            gpio_bit_reset(ADC_CtrlPort, ADC_RANG);
            break;

        default :
            gpio_bit_reset(ADC_CtrlPort, ADC_STBY);
            gpio_bit_set(ADC_CtrlPort, ADC_RANG);
            break;
    }
}

#读取转换结果
uint16_t* AD7606_ReadData(void)
{       
        //开始单次转换
        AD7606_StartConv();
       
        //等待转换结束
        while(gpio_input_bit_get(ADC_CtrlPort, ADC_BUSY));
       
        //结束转换准备读取数据寄存器中的数据
        AD7606_StopConv();
       
        //读取数据:并行模式读取数据
        for(uint8_t i = 0; i < 8; i ++)
                {
            //这两个延时有点长了,或许不需要延时也许,30ns的时间内即可读完一个通道数据
                        gpio_bit_reset(ADC_CtrlPort, ADC_RD);
            //delay_1ms(1);
                        ADC_Data = gpio_input_port_get(ADC_DataPort);
                        delay_1ms(1);            
                        gpio_bit_set(ADC_CtrlPort, ADC_RD);                       
                }
       
        return ADC_Data;
}

/*!
        \brief        ADC复位
    \param[in]    无                                  
    \param[out]   无
    \retval       无
*/
void AD7606_Reset(void)
{
        gpio_bit_set(ADC_CtrlPort, ADC_RESET);
       
        delay_1ms(1);                        //最小50 ns
       
        gpio_bit_reset(ADC_CtrlPort, ADC_RESET);
}
————————————————

                            版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。

原文链接:https://blog.csdn.net/magicssss/article/details/143205014

使用特权

评论回复
沙发
星辰大海不退缩| | 2024-10-31 11:08 | 只看该作者
很不错的案例学习一下

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

88

主题

4087

帖子

1

粉丝