找回密码
 注册
关于网站域名变更的通知
查看: 421|回复: 1
打印 上一主题 下一主题

转——高速数据采集之数据传输(2) 

[复制链接]

该用户从未签到

跳转到指定楼层
1#
发表于 2019-4-15 16:32 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式

EDA365欢迎您登录!

您需要 登录 才可以下载或查看,没有帐号?注册

x
转——高速数据采集之数据传输(2)
1、  硬件环境
       硬件平台: Embest SoC --LarkBoard
       软件平台:开发板-linux-3.10.31
                       Quartus 14.0

6 Y  R( o) V; I; ^& h: p' ^$ u
2、系统概述
在上一篇文章已经成功进行了这样的测试,每中断一次,ARMFPGA的ROM中取一次数据,这边文章主要是测试一下,ADC的数据经过双口RAM传递给ARM的过程,设计框图如下所示:

+ |( q  j: o( g+ d1 H. {
3、Qsys设计
下图是qsys的设计和连接关系如下图所示:
- b" I) b7 t- r
1)  如图所示adc_origin_data挂载在HPS-to-FPGA bridge上,偏移地址为20040000(这个地址是可以任意改动的,注意和驱动对应就行了)
2)  增加了adc_spi_pio的控制接口,实现对ADC的配置和初始化,这个前面的测试中是没有注意的

; Q. f) G! t& i/ }, O+ `
quartus工程文件见附件:
游客,如果您要查看本帖隐藏内容请回复

6 ]; Z" |/ N  |1 a/ q% V
4、ADC驱动设计
这里测试驱动主要使用了Embest自带的驱动,位于drivers\char\adc9628.c,具体代码可见附件:
游客,如果您要查看本帖隐藏内容请回复
这是一个很好的参考用例,实际使用的时候还需要进一步的修改。上面qsys中偏移地址的设置就是为了和驱动相对应的。

7 _# ]! J" v" ~
主要完成以下功能:
1)通过模拟SPI接口完成ADC9628的初始化
  • /*
  • *init the registers of ADC9628,
  • *write to Altera's PIO IP core to operate the gpio as spi pins
  • */
  • static void bsp_adc_init(struct adc_priv_data *adc_data)
  • {
  •     int iadc_val  ;
  •     writew( 0x7,adc_data->regbase + (0x1*4));                                                 /* pio_dir = 0x7 */
  •         writew( 0x6,adc_data->regbase + (0x4*4));                                                 /* cs = 1  */
  •         writew( 0x2,adc_data->regbase + (0x4*4));                                                 /* sclk=0 */
  •         mdelay(2);
  •     iadc_val = ad9628_read(0x1 );                                                                          /*  chip ID, 0x89 */
  •     printk(KERN_INFO"current id = %x \n", iadc_val);
  •     iadc_val = ad9628_read(0x2 );                                                                          /*  chip grade */
  •         iadc_val = ad9628_read(0x0b );                                                                         /* clock divide */
  •         iadc_val = 0x0;
  •         ad9628_write(0x0b, iadc_val);
  •         iadc_val = ad9628_read(0x0b );
  •     iadc_val = ad9628_read(0x09 );                                                                  /* DUTY stabilty */
  •         iadc_val = ad9628_read(0x0b );                                                                  /* clock ratio */
  •         ad9628_write(0x05, 0x03);                                                                             /*  Channel a b */
  •     iadc_val = ad9628_read(0x5 );
  •         ad9628_write(0x0d, 0x0);                                                                                  /*  normal mode */
  •     iadc_val = ad9628_read(0xd );
  •         iadc_val = ad9628_read(0x101 );
  •         iadc_val |= (0x1<<7);
  •         ad9628_write(0x101, iadc_val);
  •         iadc_val = ad9628_read(0x101 );
  •         bsp_adc_cmos();
  •         iadc_val = ad9628_read(0x14 );
  • }
    ) c! ~! H' r8 F' F9 U/ V
4 R1 y* Z2 w  T$ U2 O+ C

5 |, L5 w' v- O. `) n6 \/ h. @7 L* r
2)完成读双口RAM的操作
  • static const struct file_operations adc_fops = {
  •         .read                = adc_read,
  •         .open                = adc_open,
  •         .release                = adc_release,
  •         .owner                = THIS_MODULE,
  • };! S' x: q8 R( m

+ O' ^# Y& k* X# e2 D

" y0 j) y' Z/ Q
4 j6 i  a# V9 g8 Y) @/ S
3)把ADC注册成一个char型设备
  • static int __init adc9628_init(void)
  • {
  •         dev_t dev = MKDEV(LARK_ADC_MAJOR, 0);
  •         int ret;
  •         ret = register_chrdev_region(dev, max_adc_minors, "adc");
  •         if (ret)
  •                 goto error;
  •         cdev_init(&adc_cdev, &adc_fops);
  •         ret = cdev_add(&adc_cdev, dev, max_adc_minors);
  •         if (ret) {
  •                 goto error_region;
  •         }
  •         adc_class = class_create(THIS_MODULE, "adc");
  •         if (IS_ERR(adc_class)) {
  •                 printk(KERN_ERR "Error creating adc class.\n");
  •                 cdev_del(&adc_cdev);
  •                 ret = PTR_ERR(adc_class);
  •                 goto error_region;
  •         }
  •         adc_class->devnode = adc_devnode;
  •         device_create(adc_class, NULL, MKDEV(LARK_ADC_MAJOR, 0), NULL, "adc");
  •         if (!request_mem_region(BSP_ADC_ADDR,sizeof(u32),"adc9628")) {
  •                 printk( "Memory region busy\n");
  •                 return  -EBUSY;
  •         }
  •         gRegbase = ioremap_nocache(BSP_ADC_ADDR, sizeof(u32));
  •         if(!gRegbase) {
  •             printk( KERN_INFO" ioremap failed\n");
  •                 return -EIO;
  •         }
  •         if (!request_mem_region(BSP_FIFO_BASE,sizeof(u32)*1024,"adc9628_fifo")) {
  •                 printk( KERN_INFO"Memory region busy\n");
  •                 return  -EBUSY;
  •         }
  •         gFifobase = ioremap_nocache(BSP_FIFO_BASE, sizeof(u32)*1024);
  •         if(!gFifobase) {
  •             printk( KERN_INFO" ioremap failed\n");
  •                 return -EIO;
  •         }
  •         return 0;
  • error_region:
  •         unregister_chrdev_region(dev, max_adc_minors);
  • error:
  •         return ret;
  • }
    0 q+ E5 \( H- `. H8 c7 d) y7 N9 Y/ I
+ n6 _. Y9 |. s/ y; L
: _. @5 S! J  G
至此ADC驱动介绍完毕,记得在编译系统的时候把驱动编译进去就行了
' N0 p- P$ T8 W: {
5、应用程序设计
这里使用的也是Embest提供的测试程序,详细程序可见附件: adc_test.zip (1.62 KB, 下载次数: 88)
测试程序主要完成了FFT计算,我也没有深入的研究,因为并不是我想要的东西,只是用它做个测试吧,有兴趣的自行研究吧,这里就不分析代码了;

' J! o7 |1 z: K! y8 |. G9 ]

$ W& }# X- X0 K& u9 a1 g' J. a
6、测试结果
. w7 D" ~* t4 ~
1) 环境搭建
把信号发生器的两个输出口,分别接ADC9628 的两个输入端,如下图所示:
  P! O( M+ k) R2 ~: G

. }* c. A/ x6 e1 T, n
2)设置信号发生器
2 d+ U5 @. V! S- F; t3 A( K( ~
/ c. m, q5 D4 v! y. F# r2 U, w) r
3)运行测试程序
  • root@arm:~/adc# ./adc_test
  • current id = 89
  • dong fft
  • caculate real valule
  • 146:chanel0 frequency = 14.970703, amplitude=2185
  • 293:chanel1 frequency = 30.043945, amplitude=1806! T* o1 Z. t3 W" y2 w

, Z& f, B$ t% e2 W8 q

- H4 K) y, H% {2 v6 f" R
( g" g4 [: d, C- x/ f/ ?$ B4 }
从测试结果看chanel0的频率测量是14.970703Mhz,chanel1的频率测量是30.043945Mhz,和实际设置值相似,且可以按照设定频率进行准确的跟踪,说明数据传输应该没有问题
! B% R5 }7 v3 i' R9 j' c
7、小结
1) 本次主要测试ADC的采集数据通过双口RAM传递给ARM的过程,测试结果一切正常,为下一步的工作打下了基础;
2)HPS-to-FPGA bridge接口传输的性能还有待进一步的测试,目前优先完成系统设计;
3)下一步准备把前面设计的中断,加入到驱动中去,这样驱动就更加实用了;
4)同时准备移植web服务器,把采集的数据能够在web上进行展示,这方面不擅长,有大侠可帮忙吗?非常感谢!
  O, L, i& V  F

& C# A" d0 R% d% P1 Y7 p. B2 ^3 a, o3 j0 J% j( D$ n5 S
您需要登录后才可以回帖 登录 | 注册

本版积分规则

关闭

推荐内容上一条 /1 下一条

EDA365公众号

关于我们|手机版|EDA365电子论坛网 ( 粤ICP备18020198号-1 )

GMT+8, 2025-10-8 23:03 , Processed in 0.171875 second(s), 27 queries , Gzip On.

深圳市墨知创新科技有限公司

地址:深圳市南山区科技生态园2栋A座805 电话:19926409050

快速回复 返回顶部 返回列表