找回密码
 立即注册
查看: 46|回复: 3

使用Ai8051模拟fx2lafw设备制作简易逻辑分析仪(抛砖引玉)

[复制链接]
  • 打卡等级:以坛为家II
  • 打卡总天数:494
  • 最近打卡:2025-07-14 00:38:42

3

主题

32

回帖

1533

积分

金牌会员

积分
1533
发表于 前天 23:14 | 显示全部楼层 |阅读模式
最近在学习USB通信相关的知识,联想到Ai8051有usb,也有40M主频,
能不能模拟网上24M那种赛普拉斯单片机的逻辑分析仪呢。
试了一下还真行,虽然性能差了不是一星半点,但是真能跑
先放张能跑的图,上位机使用的是开源的pulseView
QQ截图20250712215218.jpg
通过抓包和查看fx2lafw固件的源码可以知道,sigrok使用libusb,通过厂商描述符与下位机通信。
设备描述符,配置描述符和字符串照抄源码即可,由于成品逻辑分析仪是高速设备,所以对应的端点描述符最大包要从512改为64
setup相关配置照抄USBCDC官方例程即可。
需要添加的是厂商描述符的处理,
固件中相关源码
  1. BOOL handle_vendorcommand(BYTE cmd)
  2. {
  3.         /* Protocol implementation */
  4.         switch (cmd) {
  5.         case CMD_START:
  6.                 /* Tell hardware we are ready to receive data. */
  7.                 vendor_command = cmd;
  8.                 EP0BCL = 0;
  9.                 SYNCDELAY();
  10.                 return TRUE;
  11.         case CMD_GET_FW_VERSION:
  12.                 send_fw_version();
  13.                 return TRUE;
  14.         case CMD_GET_REVID_VERSION:
  15.                 send_revid_version();
  16.                 return TRUE;
  17.         }
  18.         return FALSE;
  19. }
复制代码

这里cmd是一个结构体
  1. struct cmd_start_acquisition {
  2.         uint8_t flags;
  3.         uint8_t sample_delay_h;
  4.         uint8_t sample_delay_l;
  5. };
复制代码

flags是为30M主频还是48M主频,sample_delay是主频/采样率-1,我这里固定主频为40M,将他的采样率转化为40M的定时器计数
  1. void cmd_start_over()
  2. {
  3.         //还原采样率
  4.         u32 u32Samplerate;
  5.         //接收采样率 单位Hz   定时器设置值
  6.         u16 u16Delay;
  7.         //未添加错误处理
  8.         u16Delay=cmdStartInfo.sample_delay_h;
  9.                 u16Delay<<=8;
  10.                 u16Delay+=cmdStartInfo.sample_delay_l;
  11.                 u16Delay++;
  12.         //1<<6
  13.         if(cmdStartInfo.flags==0x40)//48M基准
  14.         {
  15.                 //delay = SR_MHZ(48) / samplerate - 1;
  16.                 u32Samplerate=48000000UL/u16Delay;
  17.         }
  18.         else//30M基准  0<<6
  19.         {
  20.                 u32Samplerate=30000000UL/u16Delay;
  21.         }
  22.                 //初始化缓存
  23.         Buffer_Init();
  24.         //启动定时器
  25.         Timer0_Start(u32Samplerate);
  26. }
  27. //启动定时器
  28. void Timer0_Start(uint32_t xHz)                //可配置频率@40.000MHz
  29. {
  30.     uint32_t reload;
  31.    
  32.     AUXR |= 0x80;                        //定时器时钟1T模式
  33.     TMOD &= 0xF0;                        //设置定时器模式
  34.    
  35.     // 计算重载值
  36.     // 系统时钟频率为40MHz,1T模式下每个时钟周期为1/40MHz = 0.025us
  37.     // 定时周期 = 1/xHz 秒 = (1/xHz)*1000000 us
  38.     // 需要的时钟周期数 = (定时周期)/0.025 = (1000000/xHz)/0.025 = 40000000/xHz
  39.     // 由于定时器是16位向上计数,重载值 = 65536 - (40000000/xHz)
  40.     reload = 65536UL - (40000000UL / xHz);
  41.    
  42.     TL0 = reload;                        //设置定时初始值低字节
  43.     TH0 = reload >> 8;                //设置定时初始值高字节
  44.    
  45.     TF0 = 0;                                //清除TF0标志
  46.     TR0 = 1;                                //定时器0开始计时
  47.     ET0 = 1;                                //使能定时器0中断
  48. }
复制代码


定时器启动后就开始进行采样,采样数据8通道占1个字节,0通道是bit0,7通道是bit7。
Ai8051有一个32K大小的xdata内存,尽可能分一个大的环形缓冲区,一个指针读,一个指针写,到达末尾就返回初始,这样可以最大限度利用缓冲区。
  1. //定时器中断,填入数据
  2. void Timer0_Isr(void) interrupt 1
  3. {
  4.         BYTE xdata *nextPtr = wPtr + 1;
  5.     if (nextPtr >= bufferEnd) {  // 指针回绕
  6.         nextPtr = RxBuffer;
  7.     }
  8.     if (nextPtr == rPtr) {  // 缓冲区满
  9.         //memOver=1;
  10.                 Timer0_Stop();
  11.     }
  12.     *wPtr = P1;
  13.         u16Remain--;//剩余空间-1
  14.         u16Available++;
  15.     wPtr = nextPtr;//指针+1
  16. }
  17. 在主循环中,只需要不停的发送这些数据就可以了。
  18. //判断usb空闲
  19.                 if(!UsbInBusy)
  20.                 {
  21.                         //已用空间达到64
  22.                         if(u16Available>=64)
  23.                         {
  24.                                 //发送数据
  25.                                 EUSB =0;
  26.                                 UsbInBusy=1;
  27.                                 usb_write_reg(INDEX, 2);
  28.                                 for(i=0;i<64;i++)
  29.                                 {
  30.                                         usb_write_reg(FIFO2, *rPtr);  //发送接收到的数据
  31.                                         rPtr++;
  32.                                         if (rPtr >= bufferEnd) {  // 指针回绕
  33.                                                 rPtr = RxBuffer;
  34.                                         }
  35.                                 }
  36.                                 u16Remain+=64;//剩余空间+64
  37.                                 u16Available-=64;
  38.                                 usb_write_reg(INCSR1, INIPRDY);
  39.                                 while (usb_read_reg(INCSR1) & INIPRDY);
  40.                                 usb_write_reg(INCSR1, INIPRDY);  
  41.                                 EUSB = 1;
  42.                         }
  43.                 }
复制代码

               
代码比较简单,基本上就是拿官方例程改了改,不过现在的版本还有很大问题
可能是有丢包或者其他情况,500K和1M采的数据完全不可用,降到250K才可用,并且受到通信速度和算法垃圾的影响,1M采样率只能采30ms,500K采样率可采120ms,250K及以下可以长时间采集
就这样吧,抛砖引玉,等一个感兴趣的大佬来优化了

最后,使用方法参考网上卖的20左右的逻辑分析仪,源码见附件

25.7.13
调整了定时器0的中断优先级
在P01增加了一个100K占空比50%的pwm测试波形
修复了P35没有时钟输出的bug
目前来说500K虽然只能112ms,还比较稳定,可用
fx2lafw模拟.7z (78.75 KB, 下载次数: 3)


参考文档、视频
Ai8051产品规格书
https://www.stcaimcu.com/data/download/Datasheet/AI8051U.pdf

USB拓展库及使用示例 | 本贴 咨询 USB,基本帮您把USB程序开发完成
https://www.stcaimcu.com/thread-16791-1-1.html


STCAI 官方usb课程
视频教学:【USB 原理及实战,16课时】,大学标准课程,有配套书籍 - USB:USB-CDC虚拟串口/就是串口,一箭双雕之USB转双串口,[鼠标+键盘]的HID复合设备 国芯技术交流网站 - AI32位8051交流社区

上位机通信源码
https://github.com/sigrokproject ... rc/hardware/fx2lafw
下位机固件源码
https://github.com/sigrokproject ... fx2lafw/tree/master












4 喜欢他/她就送朵鲜花吧,赠人玫瑰,手有余香!
回复

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:494
  • 最近打卡:2025-07-14 00:38:42

3

主题

32

回帖

1533

积分

金牌会员

积分
1533
发表于 前天 23:51 | 显示全部楼层
忘了说了p10-p17是0-7通道,p35是定时器输出端
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:485
  • 最近打卡:2025-07-14 01:23:04
已绑定手机

38

主题

2272

回帖

2882

积分

荣誉版主

积分
2882
发表于 昨天 00:55 | 显示全部楼层
精神可嘉,值得鼓励!
虽然cy7c68013A是51核,而且是20年前的老产品,但它的USB接口是2.0高速接口,支持480Mbps,USB单元设置了一个GPIF接口,通过外部EEPROM配置为IO映射GPIPF的方式通信,完全不需要单片机核的介入,类似纯物理搬运IO状态,所以能到24MHz采样速率。
而这种模拟的方式受限因素就多了,软件参与过多,而且缓冲机制也会造成一定的数据延迟,做USB接口的高速IO板卡还算是能实用,但做逻辑分析仪的话瓶颈就放在那,优化空间也不是很大。
睁开眼睛做场梦~~~
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:494
  • 最近打卡:2025-07-14 00:38:42

3

主题

32

回帖

1533

积分

金牌会员

积分
1533
发表于 昨天 11:10 | 显示全部楼层
晓*** 发表于 2025-7-13 00:55
精神可嘉,值得鼓励!
虽然cy7c68013A是51核,而且是20年前的老产品,但它的USB接口是2.0高速接口,支持480 ...

是的,看了固件的源码,那个芯片io单独编程直连USB-DMA发送,这个主要还是学习usb的作品,本来想着能识别出来就完事了,没想到还真能跑
回复 支持 反对

使用道具 举报 送花

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|手机版|深圳国芯人工智能有限公司 ( 粤ICP备2022108929号-2 )

GMT+8, 2025-7-14 03:40 , Processed in 0.113909 second(s), 68 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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