拿到一个芯片,编写驱动前,我们需要仔细阅读芯片的使用手册,根据手册来编写驱动,当然了有些芯片厂家也是提供了驱动,但是你不明白其中的细节和使用方法,也会在引用之中出现大量BUG。这里主要针对AD7606的并行接口的使用,做些细节介绍,方便工程师在使用中的避雷。
只要看懂适应方法,避免误区,驱动程序也可直接引用,方便快捷,省去大量功夫。文章若有错误请指正。话不多说,我们首先来看一下,这个芯片手册。
AD7606具体有4、6和8通道采样,驱动可以做到兼容中无非改一下读取数据多少,电路中对应修改采样通道信息即可。
其他内容信息,也不做介绍,针对并行接口,下面我们来看一下写驱动需要我们重点关注的内容时序图:
转换前后时序图如下:
上图是对于数据的读取方式的时序说明,这里要详细说一下:
举例说明:如果你想要这个AD采样在最高200K下工作,而若想你的采样率真正的达到200K,你还需要在5us周期内调用它,这样你才能保证你的运行时间段内的采样是200K的。而这也需要你必须在5us内将数据读完,而这个5us又需要区分转换前和转换后数据(上图是两种读取数据的方法)。而根据实测,在5us的采样率下,转换时间差不多需要3us左右,即BUSY高电平时间。图二是在BUSY高电平时间内读取上次的转换数据,图三是在BUSY低电平时间内读取,即下次转换前。最高采样周期下,实际只有2us的时间。
上图中两种读取方法选择一种读取(根据自身MCU的时钟主频、采样周期)即可,如果要保证数据的准确性,最好能在低电平时间内读完数据。实测最高采样下,BUSY 高电平转换期间读取数据会出现窜通道现象。低采样周期使用可忽略。
以上时序图,是并行接口读数据,这个相当于看图写程序,配合管脚的说明,只要将对应管脚拉高或者拉低,然后读取数据就可以,很好理解。
芯片的初始化和读数据代码:PS:注意需要复位才有效。
void AD7606Initialization(u8 OverSampleRate)
{//初始化
delay_ms(1);
ADC_RESET_L; //初始复位管脚低电平
switch(OverSampleRate)//采样率选择
{
case 200:OS_NO;break;
case 100:OS_2;break;
case 50: OS_4;break;
case 25: OS_8;break;
default: OS_NO;break;
}
ADC_CS_H;
ADC_CONV_H;
ADC_RD_H;
delay_ms(1);
}
复位使能,初始化后调用即可。
void AD7606Reset(void)
{//脉冲50nS复位有效
ADC_RESET_H;
delay_us(1);
ADC_RESET_L;
delay_us(1);
}
读取数据代码(BUSY低电平时读取),对应采样率读取,定时器周期调用即可。注意:我这里为了压缩读取的时间,虽没有严格按照手册延时读取数据,却也能正常读取,这里不推荐使用for循环读取数据,循环中变量的执行也会有延时。无需最高频率采样的使用环境,可忽略。
void AD7606ReadSample(void)
{
//开启转换
ADC_CONV_L;
__NOP();// delay_ns(1);
ADC_CONV_H;
__NOP();// delay_ns(1);
//当前数据状态 低电平可读取新数据 高电平可读取上次结果
while(ADC_Busy_State)
{//高电平期间读取数据,过采样开启可用
}
ADC_CS_L;
__NOP();
//BUSY低电平读取新数据
ADC_RD_L;
__NOP(); //delay_ns(32);//低电平时间最少32ns
ADCHData.Ary16[0]=ADC_PDate;
ADC_RD_H;//高电平宽度为15个ns最少
__NOP();//delay_ns(32);//35个ns
ADC_RD_L;
__NOP(); //delay_ns(32);//低电平时间最少32ns
ADCHData.Ary16[1]=ADC_PDate;
ADC_RD_H;//高电平宽度为15个ns最少
__NOP();//delay_ns(35);//35个ns
ADC_RD_L;
__NOP(); //delay_ns(32);//低电平时间最少32ns
ADCHData.Ary16[2]=ADC_PDate;
ADC_RD_H;//高电平宽度为15个ns最少
__NOP();//delay_ns(35);//35个ns
ADC_RD_L;
__NOP(); //delay_ns(32);//低电平时间最少32ns
ADCHData.Ary16[3]=ADC_PDate;
ADC_RD_H;//高电平宽度为15个ns最少
__NOP();//delay_ns(35);//35个ns
ADC_RD_L;
__NOP();//delay_ns(32);//低电平时间最少32ns
ADCHData.Ary16[4]=ADC_PDate;
ADC_RD_H;//高电平宽度为15个ns最少
__NOP();//delay_ns(1);//35个ns
ADC_RD_L;
__NOP(); //delay_ns(1);//低电平时间最少32ns
ADCHData.Ary16[5]=ADC_PDate;
ADC_RD_H;//高电平宽度为15个ns最少
__NOP();//delay_ns(1);//35个ns
ADC_RD_L;
__NOP(); //delay_ns(1);//低电平时间最少32ns
ADCHData.Ary16[6]=ADC_PDate;
ADC_RD_H;//高电平宽度为15个ns最少
__NOP();//delay_ns(1);//35个ns
ADC_RD_L;
__NOP(); //delay_ns(1);//低电平时间最少32ns
ADCHData.Ary16[7]=ADC_PDate;
ADC_RD_H;//高电平宽度为15个ns最少
}
下面是头文件,使用时可以直接调用,修该对应映射的管脚即可:
//ADC7606——AD采集相关参数管脚定义//
//推挽输出模式
#define ADC_CONV_H (set_bit(GPIOA->ODR,0)) //通道转换开始
#define ADC_CONV_L (clr_bit(GPIOA->ODR,0))
#define ADC_RESET_H (set_bit(GPIOA->ODR,3)) //复位管脚使能
#define ADC_RESET_L (clr_bit(GPIOA->ODR,3))
#define ADC_RD_H (set_bit(GPIOA->ODR,6)) //
#define ADC_RD_L (clr_bit(GPIOA->ODR,6))
#define ADC_CS_H (set_bit(GPIOB->ODR,0)) //
#define ADC_CS_L (clr_bit(GPIOB->ODR,0))
//RD下降沿后读取,高电平可提供V1结果,下一个下降延
#define ADC_FSTDATA (GPIOC->IDR & GPIO_Pin_0) //配置为输入模式
//当前数据状态 低电平可读取新数据 高电平可读取上次结果
#define ADC_Busy_State (GPIOB->IDR & GPIO_Pin_1) //配置为输入模式
//并行数据采集
#define ADC_PDate (GPIOD->IDR & GPIO_Pin_All)
//000 200K 调节采样模式---推挽输出
#define ADC_OS0_H (set_bit(GPIOC->ODR,3))
#define ADC_OS0_L (clr_bit(GPIOC->ODR,3))
#define ADC_OS1_H (set_bit(GPIOB->ODR,2))
#define ADC_OS1_L (clr_bit(GPIOB->ODR,2))
#define ADC_OS2_H (set_bit(GPIOC->ODR,13))
#define ADC_OS2_L (clr_bit(GPIOC->ODR,13))
//采样率设置
#define OS_NO ADC_OS0_L;ADC_OS1_L;ADC_OS2_L;
#define OS_2 ADC_OS0_H;ADC_OS1_L;ADC_OS2_L;
#define OS_4 ADC_OS0_L;ADC_OS1_H;ADC_OS2_L;
#define OS_8 ADC_OS0_H;ADC_OS1_H;ADC_OS2_L;
typedef union
{//AD7606对应通道采集数据
u16 Ary16[8];
struct
{
u16 AD7606_1; //
u16 AD7606_2;
u16 AD7606_3;
u16 AD7606_4;
u16 AD7606_5;
u16 AD7606_6;
u16 AD7606_7;
u16 AD7606_8;
}REG;
}AD7606CHDataREG;
extern AD7606CHDataREG ADCHData;
void AD7606Initialization(u8 OverSampleRate);//初始采样率定义
void AD7606ReadSample(void);//周期采样
void AD7606ReadOnceSample(void);//单次数据采集
void AD7606Reset(void);//芯片复位函数
如有疑问,可探讨,错误和不足之处请指教。