Zynq ADC数据采集和UDP传输测试

Zynq ADC数据采集和UDP传输测试

摘要

运行于Zybo开发板petalinux的应用程序,参考了黑金的教程。实现了从AD9238读出数据,再通过UDP传输至服务器,主要进行了传输速度测试。

main.c

#include <stdio.h>
#include <fcntl.h>
#include <linux/fb.h>
#include <sys/mman.h>
#include <stdlib.h>
#include "adc_capture.h"
//#include "frame_buffer.h"
//#include "wave.h"

#define ADC_CAPTURELEN     1920           /* ADC capture length */
#define ADC_COE            16             /* ADC coefficient */
#define ADC_BYTE           2              /* ADC data byte number */
#define ADC_BITS           12
/*
 *Wave defines
 */
#define CANVAS_LEN          1920*1080*3    /* Canvas total length in byte */
#define WAVE_START_ROW      150             /* Grid and Wave start row in frame */
#define WAVE_START_COLUMN   0              /* Grid and Wave start column in frame */
#define WAVE_HEIGHT         256   		   /* Grid and Wave height */


#include <time.h> 
#include <sys/time.h> 
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

#define SERVER_PORT 8080
#define BUFF_LEN 512
#define SERVER_IP "192.168.1.30"
int client_fd;
struct sockaddr_in ser_addr;
int init_udp()
{
    client_fd = socket(AF_INET, SOCK_DGRAM, 0);
    if(client_fd < 0)
    {
        printf("create socket fail!\n");
        return -1;
    }

    memset(&ser_addr, 0, sizeof(ser_addr));
    ser_addr.sin_family = AF_INET;
    ser_addr.sin_addr.s_addr = inet_addr(SERVER_IP);
   // ser_addr.sin_addr.s_addr = htonl(INADDR_ANY);  //注意网络序转换
    ser_addr.sin_port = htons(SERVER_PORT);  //注意网络序转换

    return 0;
}

int main(int argc, char *argv[])
{
	st_fb_info fb_info;
	u8 CanvasBuffer[CANVAS_LEN];
    int fd0,fd1;
    int wave_width;
    short CH0DmaRxBuffer[ADC_CAPTURELEN];
    short CH1DmaRxBuffer[ADC_CAPTURELEN];
    int dma_flag0=0;
    int dma_flag1=0;

    struct timeval  tv; 
    struct timeval  tv0;
    struct timeval  tv1;
    struct timezone tz;   
    float time_use=0;  
    float rate=0;
    int pkg0_cnt=0;
    int pkg1_cnt=0;

    /* Open video memory */
    if (fb_init(&fb_info)) {
    	printf("fb inint error \n");
        exit(1);
    }

    adc_capture_init(&fd0,"/dev/adc0",ADC_CAPTURELEN,ADC_CAPTURELEN*2);
    adc_capture_init(&fd1,"/dev/adc1",ADC_CAPTURELEN,ADC_CAPTURELEN*2);
    wave_width = fb_info.width;

    init_udp();

    gettimeofday(&tv0, NULL);

    while(1){
    	if(adc_capture(fd0,ADC_CAPTURELEN,(unsigned char *)CH0DmaRxBuffer,&dma_flag0))
    	{
    		exit(1);
    	}

    	if(adc_capture(fd1,ADC_CAPTURELEN,(unsigned char *)CH1DmaRxBuffer,&dma_flag1))
    	{
    	    exit(1);
    	}
        if(dma_flag0==1)
        {
            //use UDP send read data to PC
	        sendto(client_fd, (void *)CH0DmaRxBuffer, ADC_CAPTURELEN, 0, (struct sockaddr*)&ser_addr, sizeof(ser_addr));
            pkg0_cnt++;
            if((pkg0_cnt%10000) == 0) {
                gettimeofday(&tv, NULL);    
                time_use = (tv.tv_sec-tv0.tv_sec)*1000000+(tv.tv_usec-tv0.tv_usec);
                rate = ADC_CAPTURELEN*10000/time_use;
                // printf("adc0_capture[%d]:%ld.%ld\n", pkg0_cnt, tv.tv_sec, tv.tv_usec);
                printf("adc0 data rate: %.2fMbps \n", rate);
                tv0=tv;
            }
        }
        if(dma_flag1==1)
        {
            if((pkg1_cnt%10000) == 0) {
                gettimeofday(&tv, &tz);    
                printf("adc1_capture[%d]:%ld.%ld\n", pkg1_cnt, tv.tv_sec, tv.tv_usec);
            }
            //use UDP send read data to PC
	        sendto(client_fd, (void *)CH1DmaRxBuffer, ADC_CAPTURELEN, 0, (struct sockaddr*)&ser_addr, sizeof(ser_addr));
            pkg1_cnt++;
        }
        dma_flag0=0;
        dma_flag1=0;
		// /* Grid Overlay */
		// draw_grid(wave_width, WAVE_HEIGHT,CanvasBuffer);
		// /* channel 0 Overlay */
		// draw_wave(wave_width, WAVE_HEIGHT, CH0DmaRxBuffer, CanvasBuffer, UNSIGNEDSHORT, ADC_BITS, YELLOW, ADC_COE);
		// /* channel 1 Overlay */
		// draw_wave(wave_width, WAVE_HEIGHT, CH1DmaRxBuffer, CanvasBuffer, UNSIGNEDSHORT, ADC_BITS, RED, ADC_COE) ;
		// /* Copy Canvas to frame buffer */
		// frame_copy(wave_width, WAVE_HEIGHT, WAVE_START_COLUMN, WAVE_START_ROW, &fb_info, CanvasBuffer);
    	// usleep(500*1000);
    }

}

adc_capture.h

#ifndef ADC_CAPTURE_H
#define ADC_CAPTURE_H
/* IOCTL defines */

/* IOCTL defines */
#define AXI_ADC_IOCTL_BASE		        'W'
#define AXI_ADC_SET_SAMPLE_NUM	        _IO(AXI_ADC_IOCTL_BASE, 0)
#define AXI_ADC_SET_DMA_LEN_BYTES		_IO(AXI_ADC_IOCTL_BASE, 1)
#define AXI_ADC_DMA_INIT		        _IO(AXI_ADC_IOCTL_BASE, 2)
#define AXI_ADC_DMA_START		        _IO(AXI_ADC_IOCTL_BASE, 3)
#define AXI_ADC_DMA_DEINIT		        _IO(AXI_ADC_IOCTL_BASE, 4)

int adc_capture_init(int *fd,char *adc_dev,int adc_sample_num,int dma_len_bytes);
int adc_capture(int fd, int samples_num, unsigned char *buf, int *dma_flag);
void convert_to_u8(int samples_num, short *src_buf,unsigned char *dst_buf);
#endif

adc_capture.c

#include <termios.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/ioctl.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include "adc_capture.h"

/* Thread capture ADC samples and put it to Circular buffer */
int adc_capture_init(int *fd,char *adc_dev,int adc_sample_num,int dma_len_bytes) {

	//Open ADC dev node
	*fd = open(adc_dev, O_RDONLY);
	if (*fd < 0) {
		return -1;
	}
	if (ioctl(*fd, AXI_ADC_SET_SAMPLE_NUM, adc_sample_num)) {
		printf("ADC DMA AXI_ADC_SET_SAMPLE_NUM failed: %s\n", strerror(errno));
		return -2;
	}

	if (ioctl(*fd, AXI_ADC_SET_DMA_LEN_BYTES, dma_len_bytes)) {
		printf("ADC DMA AXI_ADC_SET_DMA_LEN_BYTES failed: %s\n", strerror(errno));
		return -2;
	}

	if (ioctl(*fd, AXI_ADC_DMA_INIT)) {
		printf("ADC DMA INIT failed: %s\n", strerror(errno));
		return -2;
	}


	return 0;
}
int adc_capture(int fd, int samples_num, unsigned char *buf, int *dma_flag) {

	if (ioctl(fd, AXI_ADC_DMA_START) == 0) {
		read(fd, buf, samples_num * 2);
		*dma_flag = 1;
	} else {

		printf("XADC DMA START  failed: %s\n", strerror(errno));
		return -1;
	}
	return 0;
}

makefile

CC = arm-linux-gnueabihf-gcc
LIBS := -lm

main:main.o adc_capture.o frame_buffer.o wave.o
	$(CC) main.o adc_capture.o frame_buffer.o wave.o -o main  -lm -L /usr/lib -L /lib
main.o:main.c
	$(CC) -c main.c -o main.o
adc_capture.o:adc_capture.c
	$(CC) -c adc_capture.c -o adc_capture.o
frame_buffer.o:frame_buffer.c
	$(CC) -c frame_buffer.c -o frame_buffer.o
wave.o:wave.c
	$(CC) -c wave.c -o wave.o 

clean:
	rm -rf *.o

测试结果

因为在main.c文件的主循环中没有开启HDMI显示,所以能测试出数据采集和传输的最大速度。
实际测试的速度达到每通道7.75MB/Sec,两通道加起来都不到USB 2.0最大速度的一半。初步推测是因为DMA应用不合理导致速度上不去,解决的办法是改写FPGA和Linux相关代码。

  • 0
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值