[使用实例] 树莓派驱动AD7606数据采集模块—SPI接口使用手记
本帖最后由 ky123 于 2018-3-2 09:25 编辑最近做项目,尝试着使用Raspberry Pi2来进行开发。Raspberry Pi2还是挺强大的,只是感觉可用的IO口很少。。项目中需要用到ADC模块,就去淘宝上淘一个安富莱德AD7606,感觉做工挺不错的还。不过价格也是贵哈,120大洋买的。
AD7606是8路、16位的AD,真双极性-5~+5或者-10~+10,采样率为200ksps(不可设定),可以选择使用并行模式、字节模式以及SPI模式。考虑到树莓派可怜的IO口数量,妥妥的选择用SPI模式。
板子默认是上图左边的并行模式,因此拿到手之后需要改动用一下电阻到右边的样子。再详细的资料大家可以去淘宝搜一下,上面讲的很详细。废话不多说,下面上接线图。
AD7606是带了数字滤波器的,可以通过OS1~OS3来配置,这里我接到了固定电平(000,不滤波)上。有需要的话也可以接到gpio上,我发的驱动程序里面已经预留好了接口。然后rage口是配置量程的,我也接的的固定电平(选择了-5~+5),同样的也可以接在gpio上。AD7606的时序还是很简单的,是标准的SPI接口。由于其所有配置都通过管教的电平来完成,所用的SPI只有SCLK和MISO。
下图即为AD7606串行模式下的时序图。转换时序选择了在转换后读取,比较方便配置(比较好写^_^),然后是下面的SPI
转换时序图
通信时序图
的时序图。SPI的通信有4种模式,如下图所示,对比可以知道是第二种,即CPOL = 1, CPHA = 0。根据linux/spi/spidev.h中的定
义可知为/*----- SET SPI MODE -----
SPI_MODE_0 (0,0) CPOL = 0, CPHA = 0, Clock idle low, data is clocked in on rising edge, output data (change) on falling edge
SPI_MODE_1 (0,1) CPOL = 0, CPHA = 1, Clock idle low, data is clocked in on falling edge, output data (change) on rising edge
SPI_MODE_2 (1,0) CPOL = 1, CPHA = 0, Clock idle high, data is clocked in on falling edge, output data (change) on rising edge
SPI_MODE_3 (1,1) CPOL = 1, CPHA = 1, Clock idle high, data is clocked in on rising, edge output data (change) on falling edge
spi_mode = SPI_MODE_0;应该为SPI_MODE_2。然而,当我在wiringPi的官网查看reference时却发现只提到有以下两个函数:int wiringPiSPISetup (int channel, int speed) ;
int wiringPiSPIDataRW (int channel, unsigned char *data, int len) ;并不能设置模式啊!!!这和说好不一样啊,坑爹的wiringPi为毛没有把mode接口留出来呢。不甘心之下就去github上查阅了wiringPiSPI.h的源文件,发现了猫腻:#ifdef __cplusplus
extern "C" {
#endif
int wiringPiSPIGetFd (int channel) ;
int wiringPiSPIDataRW (int channel, unsigned char *data, int len) ;
int wiringPiSPISetupMode (int channel, int speed, int mode) ;
int wiringPiSPISetup (int channel, int speed) ;
#ifdef __cplusplus
}
#endif原来如此,mode还是可选的,只是作者没有提而已。。再查阅一下wiringPiSPISetup函数原型可知,其默认选择了mode0,所以我们在使用时应该使用wiringPiSPISetupMode函数。
接下来直接上驱动的核心代码:(参考安富莱提供的8051程序进行移植)uint8_t ADC_val;
void AD7606_Init(){
AD7606_IOSet();
AD7606_SetDF(0); //default:OS2 OS1 OS0 = 000
AD7606_SetInputRange(0); //default:range = -5 ~ +5
AD7606_Reset();
}
//hook function,used to set input range.
void AD7606_SetInputRange(int _ucRange){
}
//hook function,used to set digital filter.
void AD7606_SetDF(uint8_t _ucMode){
}
//reset function
void AD7606_Reset(){
digitalWrite(CS , HIGH);
digitalWrite(CVAB , HIGH);
/* AD7606 is high level reset,at least 50ns */
digitalWrite(RST, LOW);
//delayMicroseconds(1);
digitalWrite(RST, HIGH);
//delayMicroseconds(1);
digitalWrite(RST, LOW);
}
void AD7606_IOSet(){
pinMode(RST , OUTPUT);
pinMode(CVAB, OUTPUT);
pinMode(CS, OUTPUT);
pinMode(BUSY, INPUT);
pullUpDnControl(BUSY, PUD_UP);
digitalWrite(RST, LOW);
digitalWrite(CS , HIGH);
digitalWrite(CVAB , HIGH);
}
void AD7606_StartConv(){
/* Conv in rising edge,at least 25ns*/
digitalWrite(CVAB, LOW);
//delayMicroseconds(1);
digitalWrite(CVAB, HIGH);
}
//Software Poll
bool AD7606_StartADC(){
if (digitalRead(BUSY) == 0){
digitalWrite(CS, LOW);
if (wiringPiSPIDataRW (SPI_CHANNEL_0, ADC_val, CH_NUM * 2) == -1){
printf("SPI failure: %s\n", strerror(errno));
}
digitalWrite(CS, HIGH);
AD7606_StartConv();
while(digitalRead(BUSY) == 0);
return true;
}
else{
printf("Value is not ready: %s\n", strerror(errno));
return false;
}
}这里为需要软件控制数字滤波器以及采样范围的留下了两个hook function,可以自己扩展。然后上电的reset函数,根据手册reset的时间不应少于50ns,而Raspberry Pi2的gpio口电平转换最快是4MHz左右,因此无需额外的延时。在AD7606_StartConv函数中进行了采样结果转换开始的操作。根据手册,我将CVA和CVB口并联起来,给一次信号接足够。按照安富莱提供的资料的说法,CVAB最好接到有pwm输出能力的口上,所以我选择了gpio1,不过后来发现没什么特别之处,换成别的口应该也没什么问题。最后就是AD7606_StartADC函数,由于本次的项目需要用到软件查询的方式采样,所以这里我仅仅写了软件查询,没有写中断的方式。根据函数可以知道,采样的第一组数据是无效的。最终的采样结果是8个16位的数,我保存在了一个extern变量extern uint8_t ADC_val;中,每个结果占数组的两个位置。因此,在调用AD7606_StartADC()后,从ADC_val数组中即可方便的获得采样结果。
接下来就是上电实测。使用稳压电源输出3.0000V,稳压电源本身测得输出为3.0037V,万用表测得为3.007V。使用
AD7606的通道1进行采样,通道2~7接地,通道8悬空,得到如下的测量结果:
第一组数据根据驱动文件的驱动方式可知是无效的。观察第二组之后的数据可知采集得到的数据是有效的。至此,驱动完毕。
**** Hidden Message *****
沙发自己坐 看着不错,顺便问一下,最高采样率实际可到多少? mark yu0405jie 发表于 2016-3-16 22:05 static/image/common/back.gif
看着不错,顺便问一下,最高采样率实际可到多少?
应该是可以到200Ksps 請問,可以附上實際 rpi 連結 ad7606 module 的圖嗎?
對硬體很不熟悉,希望可以對照著做。
謝謝~~ qqq1234567 发表于 2016-3-31 23:15 static/image/common/back.gif
請問,可以附上實際 rpi 連結 ad7606 module 的圖嗎?
對硬體很不熟悉,希望可以對照著做。
謝謝~~...
文章中已经给了连接图。 厲害!
正好需要此類經驗,謝謝! 樓主有個問題!
Raspberry Pi2的GPIO 28,29在哪里?
你確定有麽?
GPIO28,29衹有在PI 的Reversion 2.0才有啊!!
bajonetty 发表于 2016-4-15 15:32 static/image/common/back.gif
樓主有個問題!
Raspberry Pi2的GPIO 28,29在哪里?
我用的就是2B+