75a4cb24a56ec28cc200a093f8c386f1
前言本板引出了两路12bits ADC 模拟采集通道,加上之前测的串口的通讯,可以将ADC才机制发送到上位机,通过上位机进行曲线显示,即实现了简单的虚拟示波器。
过程代码两路的ADC对应设备如下,直接读对应的文件即可获取到ADC值。
代码如下
int adc_get(int ch)
{
int channel;
char cmd[128]={0};
FILE *stream = NULL;
char adc_v[1024] = {0};
snprintf(cmd, sizeof(cmd),"cat /sys/bus/iio/devices/iio\:device0/in_voltage%d_raw",ch);
stream = popen(cmd,"r");
fread(adc_v,1,sizeof(adc_v),stream);
pclose(stream);
//printf("adc_channel%d: %s",channel,adc_v);
return atoi(adc_v);
}
在上一篇测试串口的基础上完整代码如下
#include /* Standard input/output */
#include /* File control definitions */
#include
#include
#include /* POSIX terminal control definitions */
#include /* Time structures for select() */
#include /* POSIX Symbolic Constants */
#include
#include /* Error definitions */
#include
#include
#include
#define CMSPAR 010000000000
#define SERIAL_FLUSH_TX 1
#define SERIAL_FLUSH_RX 2
#define SERIAL_PARITY_NO 0
#define SERIAL_PARITY_ODD 1
#define SERIAL_PARITY_EVENT 2
#define SERIAL_PARITY_MARK 3
#define SERIAL_PARITY_SPACE 4
#define SERIAL_STOPBIT_ONE 1
#define SERIAL_STOPBIT_TWO 2
static int serial_fd = -1;
struct termios old_tios;
int uart_read(uint8_t* buffer,uint32_t len,uint32_t timeout);
int uart_write(uint8_t* buffer,uint32_t len);
static void serial_print_buf(unsigned char *buf,int len) /* 打印输出 */
{
int i;
for(i=0;i
printf("%02X ",buf);
printf("n");
}
char *get_serial_dev_name(char *serial_name) /* 获取串口名称 */
{
if (strcasecmp(serial_name, "COM2") == 0) /* 传入参函数是COM2(不区分大小写),则返回串口对应的设备节点/dev/ttymxc1 */
return "/dev/ttymxc1";
else if (strcasecmp(serial_name, "COM3") == 0)
return "/dev/ttymxc2";
else if (strcasecmp(serial_name, "COM4") == 0)
return "/dev/ttymxc3";
else if (strcasecmp(serial_name, "COM5") == 0)
return "/dev/ttymxc4 ";
else
//return NULL;
return serial_name;
}
static int termios_init(struct termios *tios,int baud,int parity,int data_bits,int stop_bits) //串口 传入波特率,校验位,数据位,停止位。
{
speed_t baud_rate;
if (tios == NULL)
return -1;
tios->c_line = 0;
tios->c_cc[VMIN ] = 0;
tios->c_cc[VTIME] = 0;
/* configure the input modes... */
tios->c_iflag = IGNBRK | IGNPAR | INPCK;
/* configure the output modes... */
tios->c_oflag = 0; /* enable implementation-defined output processing */
/* configure the control modes... */
tios->c_cflag = CREAD | CLOCAL;
if (data_bits == 5) //对传入的数据位进行判断
tios->c_cflag |= CS5;
else if (data_bits == 6)
tios->c_cflag |= CS6;
else if (data_bits == 7)
tios->c_cflag |= CS7;
else if (data_bits == 8)
tios->c_cflag |= CS8;
else
return -1;
if (stop_bits == 1) //对传入的停止位进行判断
tios->c_cflag &=~ CSTOPB;
else if (stop_bits == 2)
tios->c_cflag |= CSTOPB;
else
return -1;
if(parity == 0) //校验位: 0:无校验 1:奇校验 2:偶校验 3:mark parity 4:space parity
{ /* none */
tios->c_cflag &=~ PARENB;
tios->c_cflag &=~ PARODD;
}
else if(parity == 2)
{ /* even */
tios->c_cflag |= PARENB;
tios->c_cflag &=~ PARODD;
}
else if(parity == 1)
{ /* odd */
tios->c_cflag |= PARENB;
tios->c_cflag |= PARODD;
}
else if (parity == 3)/* 2008.12.17 add for support mark and space parity */
{
/* mark */
tios->c_cflag |= PARENB;
tios->c_cflag |= CMSPAR;
tios->c_cflag |= PARODD;
}
else if (parity == 4)
{
/* space */
tios->c_cflag |= PARENB;
tios->c_cflag |= CMSPAR;
}
else
return -1;
/* configure the local modes... */
tios->c_lflag = 0; /* enable implementation-defined input processing */
/* Set the baud rate */
switch(baud) //对传入的波特率进行判断
{
case 110:
baud_rate = B110;
break;
case 300:
baud_rate = B300;
break;
case 600:
baud_rate = B600;
break;
case 1200:
baud_rate = B1200;
break;
case 2400:
baud_rate = B2400;
break;
case 4800:
baud_rate = B4800;
break;
case 9600:
baud_rate = B9600;
break;
case 19200:
baud_rate = B19200;
break;
case 38400:
baud_rate = B38400;
break;
case 57600:
baud_rate = B57600;
break;
case 115200:
baud_rate = B115200;
break;
case 230400:
baud_rate = B230400;
break;
case 460800:
baud_rate = B460800;
break;
case 576000:
baud_rate = B576000;
break;
case 921600:
baud_rate = B921600;
break;
default:
return -1;
}
if ((cfsetispeed(tios, baud_rate) < 0) ||(cfsetospeed(tios, baud_rate) < 0))
return -1;
return 0;
}
//return serial fd, error return -1
int serial_open(char *serial_name, int baud,int parity,int data_bits,int stop_bits,int timeout) //打开串口
{
struct termios settings;
int fd;
char *serial_dev_name;
if (serial_fd >= 0)
return 0;
if (termios_init(&settings, baud,parity,data_bits,stop_bits) < 0)
return 0;
serial_dev_name = get_serial_dev_name(serial_name);
if (serial_dev_name == NULL)
{
fprintf(stderr, "invalid serial name:%sn", serial_name);
return 0;
}
if((fd = open(serial_dev_name, O_RDWR | O_NOCTTY | O_NDELAY))< 0)
return 0;
if(tcgetattr(fd, &old_tios) < 0)
{
close(fd);
return 0;
}
if(tcsetattr(fd, TCSANOW, &settings) < 0)
{
close(fd);
return 0;
}
serial_fd = fd;
return 1;
}
int serial_close() //关闭串口
{
if (serial_fd < 0)
return 0;
tcsetattr(serial_fd, TCSANOW, &(old_tios));
close(serial_fd);
serial_fd = -1;
return 1;
}
int serial_flush(int flag)
{
if (serial_fd < 0)
return 0;
if (flag == SERIAL_FLUSH_TX)
tcflush(serial_fd,TCOFLUSH);
else if (flag == SERIAL_FLUSH_RX)
tcflush(serial_fd,TCIFLUSH);
else if (flag == (SERIAL_FLUSH_RX|SERIAL_FLUSH_TX) )
tcflush(serial_fd,TCIOFLUSH);
return 1;
}
//return 1: poll ok, 0: timeout, -1: error
int serial_poll(int timeout)
{
int fd = serial_fd;
fd_set rfds;
struct timeval tv;
int sel_res;
FD_ZERO(&rfds);
FD_SET(fd, &rfds);
tv.tv_sec = timeout/1000;
tv.tv_usec = (timeout % 1000)*1000;
return select(fd + 1, &rfds, NULL,NULL,&tv);
}
int uart_read(uint8_t* buffer,uint32_t len,uint32_t timeout)
{
while(serial_poll(timeout)>0) //当另一端传入数据时会接收到数据
{
return read(serial_fd,buffer,len);
}
}
int uart_write(uint8_t* buffer,uint32_t len)
{
write(serial_fd,buffer,len);
}
int adc_get(int ch)
{
int channel;
char cmd[128]={0};
FILE *stream = NULL;
char adc_v[1024] = {0};
snprintf(cmd, sizeof(cmd),"cat /sys/bus/iio/devices/iio\:device0/in_voltage%d_raw",ch);
stream = popen(cmd,"r");
fread(adc_v,1,sizeof(adc_v),stream);
pclose(stream);
//printf("adc_channel%d: %s",channel,adc_v);
return atoi(adc_v);
}
int main(int argc, char *argv[])
{
int fd;
uint8_t recv_buffer[128];
int i, ret;
uint8_t send_buffer[128];
if (argc != 3) //需要传入串口对应的设备名
{
fprintf(stderr, "usage:serialtest com_port baudn");
return -1;
}
ret = serial_open(argv[1], atoi(argv[2]), SERIAL_PARITY_NO, 8, SERIAL_STOPBIT_ONE, 1000); //调用上面封装好的打开串口函数 传入设备名,波特率,校验位,数据位,停止位以及超时时间
if (ret == 0) //打开失败
{
fprintf(stderr, "open serial failedn");
return -1;
}
memset(recv_buffer,0x55,sizeof(recv_buffer));
while(1)
{
//int len = 0;
//if((len = uart_read(recv_buffer,sizeof(recv_buffer),100)) > 0)
//{
// uart_write(recv_buffer,sizeof(recv_buffer));
//}
int adc = adc_get(1);
snprintf(send_buffer,sizeof(send_buffer),"/* %d */rn",adc);
uart_write(send_buffer,strlen(send_buffer));
}
serial_close();
return 0;
}
上位机https://serial-studio.github.io/下下载安装Serial Studio 点击JSON编辑器按如下设置
点击添加组别
添加数据集
按如下设置点击申请
连接串口
控制台可以看到打印的值
仪表盘可以看到曲线
测试使用滑动变阻分压得到模拟电压,旋转旋钮可以看到电压变化曲线。
总结以上测试了ADC的采集,由于没有精度较高的DAC源和电压测量设备,所以就不测试其精度了。通过上位机的曲线显示,实现了简单的虚拟示波器的功能。
|