一、DSView源码阅读笔记
主线任务 |
将源码成功编译运行 |
提取示波器功能代码 |
添加示波器通道数量 |
找到接收数据部分源码 |
在win平台上使用qt开发环境进行代码重构 |
以下笔记内容部分是猜测内容
DSView\
pv:
mainwindow.cpp:
void MainWindow::device_detach();//设备分离
void MainWindow::device_attach();//设备连接
void MainWindow::capture_state_changed(int state)//捕获状态改变
bool MainWindow::load_session_json(QJsonDocument json, bool file_dev);//
sigsession.h:
storesession.cpp:
注释部分代码,运行测试,结果显示逻辑分析仪功能下的波形显示一条直线
将读取到的一段数据存储在一个缓冲区,显示界面再读取缓冲区数据,将其显示在界面上
session
libsigrok4DSL\
dsdevice.c:
SR_API int sr_dev_probe_name_set(const struct sr_dev_inst *sdi,
int probenum, const char *name); //设置指定设备探针的名字
SR_API int sr_dev_probe_enable(const struct sr_dev_inst *sdi, int probenum,
gboolean state); //启动或者关闭指定设备 的探针
SR_API int sr_dev_trigger_set(const struct sr_dev_inst *sdi, uint16_t probenum,
const char *trigger); //向指定的设备(和指定的探针)添加一个触发器,如 果 这个设备上指定的探针已经有一个触发器,它将静态地被替换
#ifdef HAVE_LIBUSB_1_0
SR_PRIV struct sr_usb_dev_inst *sr_usb_dev_inst_new(uint8_t bus,
uint8_t address, struct libusb_device_handle *hdl);
SR_PRIV void sr_usb_dev_inst_free(struct sr_usb_dev_inst *usb);
SR_PRIV struct sr_serial_dev_inst *sr_serial_dev_inst_new(const char *port,
const char *serialcomm);
SR_PRIV void sr_serial_dev_inst_free(struct sr_serial_dev_inst *serial);
//这两个参数(pathname , serialcomm)都被复制到新分配的字符串中,并由sr_serial_dev_inst_free()自动释放。
hwdriver.c:(硬件驱动程序)
libsigrok.h:
关于如何连接到设备的规范。结合SR_CONF_SERIALCOMM,这是一个串行端口对操作系统有意义的形式(例如,/dev/ttyS0)。
libsigrokdecode4DSL\
二、涉及的知识
串口通讯
读取串口数据并处理(C语言)
读取串口数据程序的编程逻辑示意图:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lOvTsvf1-1629789294072)(C:\Users\jingwenwei\AppData\Roaming\Typora\typora-user-images\image-20210823133253144.png)]
c程序
//main.c
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include "openDev.h"
int main()
{
int fd;
int nread;
char buffer[MAX_BUFF_SIZE];
serial_parse phandle;
phandle.rxbuffsize = 0;
char *dev_name = "/dev/ttyUSB0";//根据实际情况选择串口
while(1)
{
fd = OpenDev(dev_name); //打开串口
if(fd>0)
{
set_speed(fd,9600); //设置波特率
printf("set speed success!\n");
}
else
{
printf("Can't Open Serial Port!\n");
sleep(1); //休眠1s
continue;
}
break;
}
if(set_Parity(fd,8,1,'N')==FALSE) //设置校验位
{
printf("Set Parity Error\n");
exit(1);
}
else
{
printf("Set Parity Success!\n");
}
while(1)
{
usleep(10000); //休眠1ms
nread = read(fd , phandle.buff + phandle.rxbuffsize, MAX_BUFF_SIZE - phandle.rxbuffsize);
phandle.rxbuffsize += nread;
phandle.buff[phandle.rxbuffsize] = '\0';
/*
处理 phandle.buff
*/
}
return 0;
}
//openDev.h
#ifndef OPENDEV_H
#define OPENDEV_H
#include <math.h>
#define TRUE 1
#define FALSE 0
#define MAX_BUFF_SIZE (256)
typedef struct _serial_parse
{
char buff[MAX_BUFF_SIZE];
int rxbuffsize;
}serial_parse;
int OpenDev(char *Dev);
void set_speed(int fd, int speed);
int set_Parity(int fd,int databits,int stopbits,int parity);
#endif
//openDev.c
#include <termios.h>
#include <sys/types.h>
#include <errno.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include "openDev.h"
#define TRUE 1
#define FALSE 0
int speed_arr[] = { B38400, B19200, B9600, B4800, B2400, B1200, B300, B38400, B19200, B9600, B4800, B2400, B1200, B300, };
int name_arr[] = {38400, 19200, 9600, 4800, 2400, 1200, 300, 38400, 19200, 9600, 4800, 2400, 1200, 300, };
int OpenDev(char *Dev)
{
int fd = open(Dev,O_RDWR | O_NOCTTY | O_NONBLOCK);
if(-1 == fd)
{
perror("Can't Open Serial PPPPort");
return -1;
}
else
{
printf("Open com success!\n");
return fd;
}
}
void set_speed(int fd, int speed)
{
int i;
int status;
struct termios Opt;
tcgetattr(fd, &Opt);
for ( i= 0; i < sizeof(speed_arr) / sizeof(int); i++)
{
if (speed == name_arr[i])
{
tcflush(fd, TCIOFLUSH);
cfsetispeed(&Opt, speed_arr[i]);
cfsetospeed(&Opt, speed_arr[i]);
status = tcsetattr(fd, TCSANOW, &Opt);
if (status != 0) perror("tcsetattr fd1");
return;
}
tcflush(fd,TCIOFLUSH);
}
}
int set_Parity(int fd,int databits,int stopbits,int parity)
{
struct termios options;
if ( tcgetattr( fd,&options) != 0)
{
perror("SetupSerial 1");
return(FALSE);
}
bzero(&options,sizeof(options));
options.c_cflag |= CLOCAL | CREAD;
options.c_cflag &= ~CSIZE;
switch (databits)
{
case 7:
options.c_cflag |= CS7;
break;
case 8:
options.c_cflag |= CS8;
break;
default: fprintf(stderr,"Unsupported data size\n");
return (FALSE);
}
switch (parity)
{
case 'n':
case 'N':
options.c_cflag &= ~PARENB;
options.c_iflag &= ~INPCK;
break;
case 'o':
case 'O':
options.c_cflag |= (PARODD | PARENB);
options.c_iflag |= (INPCK | ISTRIP);
break;
case 'e':
case 'E':
options.c_cflag |= PARENB;
options.c_cflag &= ~PARODD;
options.c_iflag |= (INPCK | ISTRIP);
break;
case 'S':
case 's':
options.c_cflag &= ~PARENB;
options.c_cflag &= ~CSTOPB;
break;
default: fprintf(stderr,"Unsupported parity\n");
return (FALSE);
}
switch (stopbits)
{
case 1:
options.c_cflag &= ~CSTOPB;
break;
case 2:
options.c_cflag |= CSTOPB;
break;
default: fprintf(stderr,"Unsupported stop bits\n");
return (FALSE);
}
if (parity != 'n')
options.c_iflag |= INPCK;
options.c_cc[VTIME] = 0;
options.c_cc[VMIN] = 0;
tcflush(fd,TCIFLUSH);
if (tcsetattr(fd,TCSANOW,&options) != 0)
{
perror("SetupSerial 3");
return (FALSE);
}
return (TRUE);
}
snapshoot快照
qt信号与槽函数
DSO数字存储示波器
两个重要参数:带宽、采样率
Oscilloscopes
这个页面记录了配置键是编写控制示波器的libsigrok前端所需的各种其他信息。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0pNzFEr5-1629789294074)(C:\Users\jingwenwei\AppData\Roaming\Typora\typora-user-images\image-20210816133721796.png)]
Frame-based
通常示波器的工作方式是触发被测信号或外部触发信号。然后,该设备测量尽可能多的它的内部缓冲区可以容纳。当缓冲区满时,设备停止测量并将其缓冲区发送到libsigrok驱动程序。这个传输代表了一帧数据的价值。驱动程序将这些数据转换为libsigrok内部模拟格式,然后像这样发送到前端:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1nHe3fME-1629789294075)(C:\Users\jingwenwei\AppData\Roaming\Typora\typora-user-images\image-20210816133747346.png)]
示波器然后重新开始采集,有时是在驱动程序刺激之后。因此,从示波器接收到的数据不是连续的从一帧到下一帧:在这之间有一个周期,该设备不进行测量。
Streaming
有些设备可以作为连续流示波器,不涉及帧。值得注意的是,具有模拟前端的基于fx2的设备,如Nexus-Computing ossciprime,就是这样工作的。
Config keys
一个用于示波器的libsigrok驱动程序实现了以下配置键的全部或部分。
SR_CONF_OSCILLOSCOPE
表示一种可以充当示波器的设备,即随时间测量一个或多个模拟通道上的电压,并将这些测量值作为模拟值发送到前端。
SR_CONF_LIMIT_FRAMES
基于帧的示波器实现了这个关键帧集,即在SR_DF_FRAME_BEGIN和SR_DF_FRAME_END包之间要捕获和发送的帧数。
它只用于设置这个值;获取它只会返回先前设置的值。默认值为0,表示连续抓取帧,直到被告知停止。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hNQ8jQB4-1629789294077)(C:\Users\jingwenwei\AppData\Roaming\Typora\typora-user-images\image-20210816134428465.png)]
SR_CONF_NUM_TIMEBASE
示波器在其水平(时间)轴上的分割数。这对应于设备显示的方格上的垂直线所标记的区域。即使在无头示波器上,这个概念仍然存在;例如,如果没有这个数字,SR_CONF_TIMEBASE设置就没有意义。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RQh6PpV5-1629789294077)(C:\Users\jingwenwei\AppData\Roaming\Typora\typora-user-images\image-20210816134513938.png)]
SR_CONF_TIMEBASE
采集过程中单个水平(时间)分割采样的持续时间。分割的数量由SR_CONF_NUM_TIMEBASE返回,因此将这个数字乘以这个持续时间就得到了对单个帧的有效采样的度量。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hZ1s29Up-1629789294078)(C:\Users\jingwenwei\AppData\Roaming\Typora\typora-user-images\image-20210816134602330.png)]
告知停止。
[外链图片转存中…(img-hNQ8jQB4-1629789294077)]
SR_CONF_NUM_TIMEBASE
示波器在其水平(时间)轴上的分割数。这对应于设备显示的方格上的垂直线所标记的区域。即使在无头示波器上,这个概念仍然存在;例如,如果没有这个数字,SR_CONF_TIMEBASE设置就没有意义。
[外链图片转存中…(img-RQh6PpV5-1629789294077)]
SR_CONF_TIMEBASE
采集过程中单个水平(时间)分割采样的持续时间。分割的数量由SR_CONF_NUM_TIMEBASE返回,因此将这个数字乘以这个持续时间就得到了对单个帧的有效采样的度量。
[外链图片转存中…(img-hZ1s29Up-1629789294078)]