赞
踩
这两天用来个ad7606 的芯片,结果硬件出来个问题,花了不少时间看这个芯片手册,干脆分享一下。
OS0 OS1 OS2
这个三个引脚用于配置芯片的采样频率,只要不设置为111即可正常采样;
CONVSTA CONVSTB 这两个引脚用于启动芯片采集转换,默认高电平,上升沿后,采样芯片开始数据采集
RESET 用于开始采样前对芯片的复位,如果没有复位,后续采集的数据可能是乱码,只需要在开机的时候复位一次即可。
RD引脚即数据通讯时钟
CS引脚通讯使用,低电平有效
BUSY引脚,默认低电平,下降沿表示数据转换成功
DOUTA,DOUTB 使用spi通信只需要这两个引脚。
RANGE引脚,低电平表示转换的是5v的电压,高电平表示转换的是10v的电压,后续电压转换时后用到。
该芯片支持串行通讯和并行通讯,我使用的是串行通讯,即spi,时序图如下
其通讯的时序和spi一样,其中FRSTDATA引脚在串行通讯的时候可以忽略,没有明确说明spi的配置,但是根据时序图可以判断,sclk默认高电平,在下降沿读取数据,串行读取数据有两种方式,一种是如上的一条数据线(DOUTA 或者 DOUTB),直接读取八个数据,每个数据两个字节,另外一种是DOUTA 和 DOUTB 各读取四个数据,我使用的是第一种方式。
我们再看如何驱动AD7606芯片,如上时序,首先需要复位芯片,RESET引脚保持最少50ns的高电平,之后CONVSTA /B触发一个上升沿,开始数据转换,此时busy引脚拉高,表示在采集的数据的过程中,当busy引脚拉低,表示书采集结束,之后边可以通过spi通讯获取数据
以上是芯片的基本内容,介绍一下相关配置和代码
spi配置如上,需要注意的两点,通信的数据为16个字节,第二个使用的MSB模式。
代码部分,因为我的代码是使用了两个ad7606,所以我挑核心部分来讲解,以免混淆。
-
- #define AD7606Cs1_High() HAL_GPIO_WritePin(CARD1_CS_GPIO_Port, CARD1_CS_Pin, GPIO_PIN_SET)
- #define AD7606Cs1_Low() HAL_GPIO_WritePin(CARD1_CS_GPIO_Port, CARD1_CS_Pin, GPIO_PIN_RESET)
-
- #define AD7606Rst_High(GPIO,GPIO_PIN) HAL_GPIO_WritePin(GPIO, GPIO_PIN, GPIO_PIN_SET)
- #define AD7606Rst_Low(GPIO,GPIO_PIN) HAL_GPIO_WritePin(GPIO, GPIO_PIN, GPIO_PIN_RESET)
-
- #define AD7606CONVST_High(GPIO,GPIO_PIN) HAL_GPIO_WritePin(GPIO, GPIO_PIN, GPIO_PIN_SET)
- #define AD7606CONVST_LOW(GPIO,GPIO_PIN) HAL_GPIO_WritePin(GPIO, GPIO_PIN, GPIO_PIN_RESET)
-
- typedef enum
- {
- AD7606_OS_0 = 0,
- AD7606_OS_1,
- AD7606_OS_2,
- AD7606_OS_4,
- AD7606_OS_8,
- AD7606_OS_16,
- AD7606_OS_32,
- AD7606_OS_64,
- AD7606_OS_NULL,
-
- }AD7606_OS;
-
- static void AD7606_Set_Os(AD7606_OS os_type)
- {
- GPIO_TypeDef *GPIO_OS0;
- GPIO_TypeDef *GPIO_OS1;
- GPIO_TypeDef *GPIO_OS2;
-
- uint16_t GPIO_PIN_OS0;
- uint16_t GPIO_PIN_OS1;
- uint16_t GPIO_PIN_OS2;
-
- uint8_t type = (uint8_t)os_type;
-
-
- GPIO_OS0 = MCU_OS0_card1_GPIO_Port;
- GPIO_OS1 = MCU_OS1_card1_GPIO_Port;
- GPIO_OS2 = MCU_OS2_card1_GPIO_Port;
- GPIO_PIN_OS0 = MCU_OS0_card1_Pin;
- GPIO_PIN_OS1 = MCU_OS1_card1_Pin;
- GPIO_PIN_OS2 = MCU_OS2_card1_Pin;
-
-
-
- HAL_GPIO_WritePin(GPIO_OS0,GPIO_PIN_OS0,(GPIO_PinState)(type&0x01));
- type = type>>1;
- HAL_GPIO_WritePin(GPIO_OS1,GPIO_PIN_OS1,(GPIO_PinState)(type&0x01));
- type = type>>1;
- HAL_GPIO_WritePin(GPIO_OS2,GPIO_PIN_OS2,(GPIO_PinState)(type&0x01));
- type = type>>1;
-
-
- }
配置采样频率
-
- typedef enum
- {
- AD7606_5V = 0,
- AD7606_10V,
-
- }AD7606_RANGE;
-
- static void AD7606_Set_Range(AD7606_RANGE RANGE)
- {
- GPIO_TypeDef *GPIO_RAGE;
- uint16_t GPIO_PIN_RAGE;
-
-
- GPIO_RAGE = MCU_RANGE_card1_GPIO_Port;
- GPIO_PIN_RAGE = MCU_RANGE_card1_Pin;
-
-
- HAL_GPIO_WritePin(GPIO_RAGE,GPIO_PIN_RAGE,(GPIO_PinState)RANGE);
- }
配置采样范围
- void AD7606Reset()
- {
- GPIO_TypeDef *GPIO_RST;
- uint16_t GPIO_PIN_RST;
-
-
- GPIO_RST = MCU_RESET_card1_GPIO_Port;
- GPIO_PIN_RST = MCU_RESET_card1_Pin;
-
-
- AD7606Rst_Low(GPIO_RST,GPIO_PIN_RST);
- AD7606Rst_High(GPIO_RST,GPIO_PIN_RST);
- AD7606Rst_High(GPIO_RST,GPIO_PIN_RST);
- AD7606Rst_High(GPIO_RST,GPIO_PIN_RST);
- AD7606Rst_High(GPIO_RST,GPIO_PIN_RST);
- AD7606Rst_High(GPIO_RST,GPIO_PIN_RST);
- AD7606Rst_High(GPIO_RST,GPIO_PIN_RST);
- AD7606Rst_High(GPIO_RST,GPIO_PIN_RST);
- AD7606Rst_High(GPIO_RST,GPIO_PIN_RST);
- AD7606Rst_High(GPIO_RST,GPIO_PIN_RST);
- AD7606Rst_High(GPIO_RST,GPIO_PIN_RST);
- AD7606Rst_High(GPIO_RST,GPIO_PIN_RST);
- AD7606Rst_Low(GPIO_RST,GPIO_PIN_RST);
-
- }
复位芯片代码,其中的 AD7606Rst_High(GPIO_RST,GPIO_PIN_RST);事实上只是在凑时间,如果你的芯片时钟频率很高的话,建议量一下这边RESET引脚复位时间够不够。
- void AD7606Init(AD7606_CARD drv)
- {
- AD7606_Set_Os(AD7606_OS_0,drv);
- AD7606_Set_Range(AD7606_5V,drv);
- AD7606Cs1_High();
- AD7606CONVST_High(MCU_CONVST_card2_GPIO_Port,MCU_CONVST_card2_Pin);
- AD7606Reset(drv);
-
- }
初始化芯片,配置采样频率,采样范围,拉高对应的引脚,复位芯片。
- void AD7606Start(AD7606_CARD drv)
- {
-
- GPIO_TypeDef *GPIO_CONVST;
- uint16_t GPIO_PIN_CONVST;
-
-
- GPIO_CONVST = MCU_CONVST_card1_GPIO_Port;
- GPIO_PIN_CONVST = MCU_CONVST_card1_Pin;
-
- AD7606CONVST_High(GPIO_CONVST,GPIO_PIN_CONVST);
- AD7606CONVST_LOW(GPIO_CONVST,GPIO_PIN_CONVST);
- AD7606CONVST_LOW(GPIO_CONVST,GPIO_PIN_CONVST);
- AD7606CONVST_LOW(GPIO_CONVST,GPIO_PIN_CONVST);
- AD7606CONVST_LOW(GPIO_CONVST,GPIO_PIN_CONVST);
- AD7606CONVST_LOW(GPIO_CONVST,GPIO_PIN_CONVST);
- AD7606CONVST_LOW(GPIO_CONVST,GPIO_PIN_CONVST);
- AD7606CONVST_LOW(GPIO_CONVST,GPIO_PIN_CONVST);
- AD7606CONVST_High(GPIO_CONVST,GPIO_PIN_CONVST);
-
-
- }
启动芯片采样转换
- uint16_t AD7606_values[8];
-
- void AD7606BusyIrqCallback(uint16_t *ad7606Val,uint8_t ad7606Chl)
- {
-
-
- AD7606Cs1_Low();
- HAL_SPI_Receive(&hspi5,(uint8_t *)ad7606Val,ad7606Chl,0x100);
- AD7606Cs1_High();
-
-
- AD7606Start(drv);
-
- }
这边有两个注意点,ad芯片在转换期间也是可以读取数据,但是有相关的时序限制,我这边没有对busy进行判断是因为在实际使用的情况下,我是有延时的,足够芯片的数据转换,第二个注意点,我们是要读取16位的数据,所以需要定义uint16_t 类型的数组,在实际通过HAL_SPI_Receive读取的时候在强制转换成uint8类型的指针。
最后是数据转化,我简单说一下
简单来说,你采集的数值是 一个二级制补码,你需要将采集值转换成原码,再通过
Vin = RANGE * ADC_NUM / 32768;
这个式子中,Vin是我们要采集的电压,RANGE为我们设置的数值,为5v或者10v,ADC_NUM是我们采集的数值并且转换成源码。
在实际过程中,驱动代码倒是没有说明特别大的问题,但是,我卡了好几天,因为获取的数据是0x7fff,无论怎么样都是这个数据,最后发现是硬件原理图画的有问题,并且REFGNG也不对,如果有朋友遇到类似的情况,优先检查硬件,尤其是几个GND是否共地;
感谢大家看到这里,祝大家生活愉快。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。