1.AD7616介绍
1.1 概述:
1.2 产品特性:
1.3 引脚配置:
注: 引脚的功能配置详情需查看AD7616数据手册
1.4 时序图
本次学习只使用了AD7616硬件模式下并行接口读取数据,而对于AD7616软件模式、串行接口、并行接口写操作未作介绍。
2.解析数据手册
2.1 引脚连接
35 REFSEL | GND | DI | 使用外部基准电压 | |
36 RESET | PB11 | DI | 复位输入,低有效 | |
37 SEQEN | +3.3V | DI | 通道序列器使能 | |
38 HW_RNGSEL1 | GND | DI | 硬件模式 | 模拟输入范围±2.5V |
39 HW_RNGSEL0 | +3.3V | DI | ||
40 SER/PAR | GND | DI | 并行接口选择输入 | |
41-48 DB0-7 | PD0-PD7 | O/I | 并行输出 | |
53-60 DB8-15 | PD8-PD15 | |||
61 WR/BURST | +3.3V | DI | 突发模式使能 | |
62 SCLK/RD | PE9 | DI | 并行数据读取控制输入 | 如果CS,RD均为逻辑低电平,则使能输出总线 |
63 CS | PE10 | DI | 片选 | |
64-66 CHSEL0-2 | +3.3V | DI | ||
67
BUSY
|
PE12 | DO | 输出繁忙 |
CONVST 上升沿之后,此引脚变为逻辑高电平,表示转换过程已开始。 BUSY 输出保持高电平,直到当前选定通道的转换过程完成为止。BUSY 下降沿表示转换数据正被锁存至输出数据寄存器,稍后便可供读取。数据必须在 BUSY 变为低电平之后读取。当 BUSY 信号为高电平时,CONVST 的上升沿不起作用。 |
68 CONVST | PE11 | DI | 通道组A/B的转换开始输入 | 在序列器模式下,当突发模式或过采样模式使能时,为了执行所需数量的转换,只需 CONVST 从低电平变为高电平一次。 |
注意:未与GPIO连接的引脚,已经与开发板焊死,写代码时不需要为其配置。
2.2工作模式
2.3数字接口
2.4复位功能
2.5 *序列器
2.6 *突发序列器
3. 驱动代码编写
3.1 配置引脚功能
配置AD7616引脚功能时需要注意,BUSY引脚类型为DO(只具备输出功能),而对于主芯片(GD32)来说,只需要配置为输入模式即可。而AD7616数据总线DB0-DB15为数字输出,对于主芯片而言并非模拟输入,而是数字输入(因为AD7616通过模拟输入引脚采集模拟数据,芯片内部已经将模拟量转换为数字量)。
//GPIO引脚初始化
void AD7616_PinInit(void)
{
gpio_init(GPIOE,GPIO_MODE_OUT_PP,GPIO_OSPEED_50MHZ,GPIO_PIN_9|\
GPIO_PIN_10|GPIO_PIN_11);//通用推挽输出
gpio_init(GPIOE,GPIO_MODE_IN_FLOATING,GPIO_OSPEED_50MHZ,GPIO_PIN_12);//浮空输入
gpio_init(GPIOB,GPIO_MODE_OUT_PP,GPIO_OSPEED_50MHZ,GPIO_PIN_11);//通用推挽输出
gpio_init(GPIOD,GPIO_MODE_IPU|GPIO_MODE_IPD,GPIO_OSPEED_50MHZ,GPIO_PIN_ALL);//PD所有引脚为上下拉输入
}
//配置BUSY引脚外部中断
void AD7616_BUSY_ExtiConfig(void)
{
gpio_exti_source_select(GPIO_PORT_SOURCE_GPIOE,GPIO_PIN_SOURCE_12);//选择gpio引脚中断源
exti_init(EXTI_12,EXTI_INTERRUPT,EXTI_TRIG_FALLING);//下降沿触发
exti_interrupt_flag_clear(EXTI_12);//清除中断标志位
exti_interrupt_enable(EXTI_12);//启用中断线
}
3.2 AD7616初始化配置
本文使用的主芯片(GD32F10x)时钟频率为108MHZ,
而延时函数AD7616_Delay_9ns(uint32_t ns)只是通过while循环做空操作。
/*
\brief: AD7616复位功能配置
\param: mode : 复位模式
AD7616_ALL_RESER :完全复位
AD7616_PART_RESER :部分复位
\retval: none
*/
void AD7616_Reser(uint8_t mode)
{
switch(mode)
{
case AD7616_ALL_RESER: //完全复位
AD7616_RESET_0;
AD7616_Delay_9ns(140);
AD7616_RESET_1;
delay_1ms(15);
break;
case AD7616_PART_RESER: //部分复位
AD7616_RESET_0;
delay_1us(40);
AD7616_RESET_1;
AD7616_Delay_9ns(5);
break;
default:
break;
}
}
//AD7616初始化
void AD7616_Init(void)
{
AD7616_PinInit();//引脚初始化
AD7616_BUSY_ExtiConfig();//配置BUSY引脚外部中断
//AD7616_RESET_1;
//AD7616_Reser(AD7616_PART_RESER);//部分复位
AD7616_Reser(AD7616_ALL_RESER);//完全复位
//未使能输出总线
AD7616_RD_1;
AD7616_CS_1;
AD7616_CONVST_0;//拉低CONVST电平
}
3.3启动一次转换
//AD值转换为实际温度值
float AD7616_ad_TO_temp(uint16_t i,const uint16_t ad)
{
return (float)(AD7616_CH_member[i].A*ad*ad + AD7616_CH_member[i].B*ad + AD7616_CH_member[i].C);
}
/*
AD7616转换函数
*/
void EXTI10_15_IRQHandler(void)
{
if(RESET!=exti_interrupt_flag_get(EXTI_12))
{
exti_interrupt_flag_clear(EXTI_12);//清除中断标志位
uint16_t i;
AD7616_CONVST_0;
for(i=0;i<AD7616_CHANNEL_VAL;i++)
{
//printf("BUSY=%d\n",gpio_input_bit_get(GPIOE,GPIO_PIN_12));//启动转换后BUSY为低电平
AD7616_CS_0;
AD7616_RD_0; //低电平时间>30ns
AD7616_Data[i]=AD7616_GET_DATA();//读取数据
AD7616_RD_1; //高电平时间>10ns
AD7616_CS_1;
AD7616_Delay_9ns(3);
}
AD7616_READ_STATE=AD7616_STATE_READABLE;//可读
//AD7616_CONVST_0;
}
}
//启动转换
void AD7616_StartConvst(void)
{
memset(AD7616_Data,0,AD7616_CHANNEL_VAL);//清空缓存
//AD7616_CONVST_0;
//AD7616_Delay_9ns(1);
AD7616_CONVST_1;
//printf("BUSY=%d\n",gpio_input_bit_get(GPIOE,GPIO_PIN_12));//未启动转换时BUSY为高电平
}
/*
\brief: 启动多次转换,并求取各通道AD平均值
\param: *ad 接收AD值的地址
count 启动次数
\retval: ERROR 超时 SUCCESS 成功转换
*/
ErrStatus AD7616_Convst_Average(const uint32_t count)
{
uint32_t i,j;
uint32_t sum[AD7616_CHANNEL_VAL]={0};
for(i=0;i<count;i++)
{
AD7616_READ_STATE=AD7616_STATE_UNREADABLE;//不可读
AD7616_StartConvst();//开始转换
j=0;
while(AD7616_READ_STATE!=AD7616_STATE_READABLE)//等待转换完成
{
AD7616_Delay_9ns(1);
j++;
if(j==500000) return ERROR;//超时
}
for(j=0;j<AD7616_CHANNEL_VAL;j++)
{
sum[j]+=AD7616_Data[j];
}
}
//取平均值
for(i=0;i<AD7616_CHANNEL_VAL;i++)
{
AD7616_AD[i]=sum[i]/count;
AD7616_Temp[i]=AD7616_ad_TO_temp(i,AD7616_AD[i]);//转换温度
}
return SUCCESS;
}
3.4 头文件
#ifndef _AD7616_H_
#define _AD7616_H_
#include "gd32f10x.h"
#include "flash.h"
#include <string.h>
#include <stdlib.h>
/*
Pin:
RD -- PE9
CS -- PE10 片选
CONVST -- PE11
BUSY -- PE12
RESET -- PB11
DB0~DB15 -- PD0~PD15
*/
/* Pin define */
#define AD7616_RESET_0 gpio_bit_reset(GPIOB,GPIO_PIN_11)
#define AD7616_RESET_1 gpio_bit_set(GPIOB,GPIO_PIN_11)
#define AD7616_RD_0 gpio_bit_reset(GPIOE,GPIO_PIN_9)
#define AD7616_RD_1 gpio_bit_set(GPIOE,GPIO_PIN_9)
#define AD7616_CS_0 gpio_bit_reset(GPIOE,GPIO_PIN_10)
#define AD7616_CS_1 gpio_bit_set(GPIOE,GPIO_PIN_10)
#define AD7616_CONVST_0 gpio_bit_reset(GPIOE,GPIO_PIN_11)
#define AD7616_CONVST_1 gpio_bit_set(GPIOE,GPIO_PIN_11)
#define AD7616_BUSY_1 gpio_bit_set(GPIOE,GPIO_PIN_12)
#define AD7616_BUSY_LEVEL() gpio_input_bit_get(GPIOE,GPIO_PIN_12)
#define AD7616_INPUT_DB(x) gpio_input_bit_get(GPIOD,BIT(x))//数据引脚0-15
#define AD7616_GET_DATA() gpio_input_port_get(GPIOD) //获取PE端口值
#define AD7616_CHANNEL_VAL 16
#define AD7616_ALL_CH 16
#define AD7616_V0A 0
#define AD7616_V0B 1
#define AD7616_V1A 2
#define AD7616_V1B 3
#define AD7616_V2A 4
#define AD7616_V2B 5
#define AD7616_V3A 6
#define AD7616_V3B 7
#define AD7616_V4A 8
#define AD7616_V4B 9
#define AD7616_V5A 10
#define AD7616_V5B 11
#define AD7616_V6A 12
#define AD7616_V6B 13
#define AD7616_V7A 14
#define AD7616_V7B 15
#define AD7616_ALL_RESER 0 //完全复位
#define AD7616_PART_RESER 1 //部分复位
#define AD7616_AD_GET_COUNT 6//转换次数
#define AD7616_STATE_UNREADABLE 0 //转换开始
#define AD7616_STATE_READABLE 1 //可读
/* parameter */
/*
AD7616结构体参数
temp=A*x*x + B*x + C
*/
typedef struct
{
uint32_t number;//通道编号
float A;
float B;
float C;
}AD7616_parameter;
extern AD7616_parameter AD7616_CH_member[AD7616_CHANNEL_VAL];
extern uint16_t AD7616_Data[AD7616_CHANNEL_VAL];//AD值
extern uint16_t AD7616_AD[AD7616_CHANNEL_VAL];//AD平均值
extern float AD7616_Temp[AD7616_CHANNEL_VAL];//温度值
/* function */
void AD7616_Init(void);
void AD7616_StartConvst(void);//启动转换
ErrStatus AD7616_Convst_Average(const uint32_t count);//启动多次转换并取平均值
#endif
3.5实验结果
未接温度传感器时,所有通道输出最大值0x7FFF(第15位为符号位)。
接入一个热敏电阻时,采集到的AD值便随温度改变,可通过校准,把AD值转换为实际温度。
4.总结
本文为学习AD7616采集数据所做,数据手册很长,并不是单看时序图就能完成驱动编写,但看懂了数据手册之后,就会发现代码挺简单的。需要注意的便是BUSY引脚,它只有输出状态,不要被(手动模式)干扰。在CONVST引脚上升沿时,BUSY便会自动变为高电平,数据转换完成时,BUSY变为低电平。
本文中没有提供主函数代码,需要读取数据时,直接调用
ErrStatus AD7616_Convst_Average(const uint32_t count);启动多次转换函数,然后直接从数组中依次读取数据(AD值或温度值)即可。校准值需要自己实际测量写入。
最后,文章中可能存在着问题,欢迎各位大佬不吝赐教。文章来源:https://www.toymoban.com/news/detail-637128.html
2022年11月29日文章来源地址https://www.toymoban.com/news/detail-637128.html
到了这里,关于【GD32篇】驱动AD7616完成数据采集的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!