fx2lafw逻辑分析仪KEIL源码

本文基于前面写的SLAVE FIFO模式,然后再根据fx2lafw官方开源码进行修改,得到我们fx2lafw-8ch的逻辑分析仪源码。

  硬件连接方法:FIFOADR0 拉低 FIFOADR1 拉低 SLRD 拉高关闭读 SLOE 拉高关闭读数据总线 SLWR 拉低使能写,记住此处的RDY0其实是真实的SLWR,丝印标记错误。

      

 需要修改Fw.c中的 void SetupCommand(void) 函数

void SetupCommand(void)
{
   
   switch(SETUPDAT[1])
   {
      case SC_GET_STATUS:                  // *** Get Status
         DR_GetStatus();
         break;
			
      case SC_CLEAR_FEATURE:                  // *** Clear Feature
         DR_ClearFeature();
         break;
      case SC_SET_FEATURE:                  // *** Set Feature
         DR_SetFeature();
			
      case SC_GET_DESCRIPTOR:                  // *** Get Descriptor
         DR_GetDescriptor();
         break;
			
      case SC_GET_CONFIGURATION:               // *** Get Configuration
         DR_GetConfiguration();
         break;
      case SC_SET_CONFIGURATION:               // *** Set Configuration
         DR_SetConfiguration();
         break;
			
      case SC_GET_INTERFACE:                  // *** Get Interface
         DR_GetInterface();
         break;
      case SC_SET_INTERFACE:                  // *** Set Interface
         DR_SetInterface();
         break;
      default:                     // *** Verdor Command
         DR_VendorCmnd();
            
   }

   EP0CS |= bmHSNAK;
}

外设文件periph.c,需要修改以下函数

BOOL DR_GetDescriptor(void);
BOOL DR_SetConfiguration(void);
BOOL DR_GetConfiguration(void);
BOOL DR_SetInterface(void);
BOOL DR_GetInterface(void);
BOOL DR_GetStatus(void);
BOOL DR_ClearFeature(void);
BOOL DR_SetFeature(void);
BOOL DR_VendorCmnd(void);


void TD_Poll(void)             // Called repeatedly while the device is idle
{
	if(G_u32_Cnt < 60000)
	{
		G_u32_Cnt ++;
	}
	else
	{
		G_u32_Cnt = 0;
		if(EP2468STAT & bmEP6EMPTY)	 /* 如果 INEP2FIFO 为空 PA1-LED就翻转 */
		{
			PA1 = ~PA1;
		}
		if(!(EP2468STAT & bmEP2FULL)) /* 如果 INEP6FIFO 不满 PA0-LED就翻转 */
		{
			PA0 = ~PA0;
		}
	}
}


void DSLogic_Init(void)
{
//设置8051的工作频率为48MHz
  CPUCS = 0x12; // CLKSPD[1:0]=10, for 48MHz operation, output CLKOUT
  SYNCDELAY;
  
  //Slave使用内部48MHz的时钟
  IFCONFIG = 0xE3; //对从设备 FIFO 接口进行配置,使之使用 48 MHz 的内部时钟
	SYNCDELAY;
	
	
	/***************************************************
	配置变址寻址方式
	PINFLAGSAB = 0x00
	PINFLAGSCD = 0x00
	报告当前FIFO数据端口(由FIFOADR[I:0]引脚选择)的的状态
	FLAGA报告"可编程级"状态
	FLAGB报告"满"状态为 0 非满为1		FLAGB 报告“已满”状态
	FLAGC报告"空"状态为 0 非空为1		FLAGC 报告“空”状态
	
	外部主服务器通常监视 
	OUT 端点的“空”标志 (EF)
	IN 端点的完整 (FF) 标志	
	***************************************************/
#if 0
	PINFLAGSAB = 0x00; 
	SYNCDELAY;
	PINFLAGSCD = 0x00; 
	SYNCDELAY;
#else
  PINFLAGSAB = 0xE0;			/* FLAGB 被配置为 EP6 OUT FIFO 的空标志 EP2EF  非空为1  PC发送数据到CY7C68013->FPGA(MCU) Check 此标志为1则按照时序进行读取 */
  SYNCDELAY;
  PINFLAGSCD = 0x08;			/* FLAGC 被配置为 EP2 IN  FIFO 的满标志 EP6FF  非满为1  PC从CY7C68013读取数据<-FPGA(MCU) Check 此标志为1则按照时序进行写入 */
  SYNCDELAY;
#endif
	
	
	
	FIFOPINPOLAR = 0x00;	//Slave FIFO标志位低电平有效
	PORTACFG |= 0x80; 	// FLAGD, set alt. func. of PA7 pin


	/*********************************************************************************
	从属FIFO控制引脚为
	SLOE(输出使能)
	SLRD(读)
	SLWR(写)
	PKTEND(包结束)

	"读"和"写"来自外部主控制器的外引线;外部主控制器从OUT端点读,向IN端点写。
	读:
	在同步方式下(IFCONFIG.3=0),当FIFO指针在SLRD有效时,IFCLK的每一个上升沿累加。
	在异步方式下(IFCoNFIG.3=1),FIFO指针在每次SLRD激活到撤销激活变化时累加。
	SLOE引脚提供FD输出使能信号。默认情况下,SLOE和SLRD低电平有效。
	写:
	在同步方式下(IFCONFIG.3=O),当SLWR被激活时,FD总线上的数据在每个时钟信号IFCLK上升沿来到时被写入FIFO(并且FIFO指针被加1)。
	在异步方式下(IFCONFIG.3=1),FD总路线上的数据在每次SLWR激活到撤销激活变化时被写入FIFO(并且FIFO指针被加1)。
	默认情况下,SLWR低电平有效。

	如果FIFO被设置为允许零长度包(EPXFIFOCFG.2=1),则可激活PKTEND脚,当FIFO为空时,提交零长度包。
	PKTEND默认为低电平有效
	*********************************************************************************/

	SYNCDELAY;
	EP6CFG = 0xA0; // OUT, 512-bytes, 4x, bulk
	SYNCDELAY;
	EP2CFG = 0xE0; // IN, 512-bytes, 4x, bulk
	SYNCDELAY;
	EP4CFG = 0x02; 	//禁止EP4
	SYNCDELAY;
	EP8CFG = 0x02;	//禁止EP8
	SYNCDELAY;
	
	
	
  //复位FIFO
  FIFORESET = 0x80;             // activate NAK-ALL to avoid race conditions
  SYNCDELAY;                    // see TRM section 15.14
  FIFORESET = 0x02;             // reset, FIFO 2
  SYNCDELAY;                    // 
  FIFORESET = 0x04;             // reset, FIFO 4
  SYNCDELAY;                    // 
  FIFORESET = 0x06;             // reset, FIFO 6
  SYNCDELAY;                    // 
  FIFORESET = 0x08;             // reset, FIFO 8
  SYNCDELAY;                    // 
  FIFORESET = 0x00;             // deactivate NAK-ALL
  SYNCDELAY;         
  
  // 分别将端点 2 FIFO 和端点 6 配置为自动输出模式和自动输入模式 同时使用8位接口
  EP6FIFOCFG = 0x00;            // AUTOOUT=0, WORDWIDE=0
  // core needs to see AUTOOUT=0 to AUTOOUT=1 switch to arm endp's
  SYNCDELAY;                    // 
  EP6FIFOCFG = 0x10;            // AUTOOUT=1, WORDWIDE=0
  SYNCDELAY;                    // 
  EP2FIFOCFG = 0x0C;            // AUTOIN=1, ZEROLENIN=1, WORDWIDE=0
  SYNCDELAY;
	


	
	
	OEA|=0x03; //Declare PA.1  PA.0 as output
	SYNCDELAY;
	IOA|=0x01; //output 0 on PA.1  1 on PA.0
	SYNCDELAY;
}

void DSLogic_Poll(void)
{
	struct cmd_start *cmd;
  switch(vendor_command)
  {
		case CMD_START:
		{
			if ((EP0CS & bmEPBUSY) != 0)
				break;
			if (EP0BCL == sizeof(struct cmd_start))
			{
				cmd = (struct cmd_start *)EP0BUF;
				if (cmd->flags & CMD_START_FLAGS_SAMPLE_16BIT)
					EP2FIFOCFG = bmAUTOIN | bmWORDWIDE;
				else
					EP2FIFOCFG = bmAUTOIN;
				SYNCDELAY;

				/* Set IFCONFIG to the correct clock source. */
				if (cmd->flags & CMD_START_FLAGS_CLK_48MHZ) 
				{
					IFCONFIG = bmIFCLKSRC | bm3048MHZ | bmIFCLKOE | bmBIT1 | bmBIT0;	 
				} 
				else 
				{
					IFCONFIG = bmIFCLKSRC | bmIFCLKOE | bmBIT1 | bmBIT0;	 
				}
			}
			vendor_command = 0;
			break;	
		}



	default:
	  vendor_command = 0;
	  break;
  }



  TD_Poll();  
}

//-----------------------------------------------------------------------------
// Device Request hooks
//   The following hooks are called by the end point 0 device request parser.
//-----------------------------------------------------------------------------

BOOL DR_GetDescriptor(void)
{
	void   *dscr_ptr;

	switch(SETUPDAT[3])         
	{
		 case GD_DEVICE:            				// Device
				SUDPTRH = MSB(pDeviceDscr);
				SUDPTRL = LSB(pDeviceDscr);
				break;
		 case GD_CONFIGURATION:         // Configuration
				SUDPTRH = MSB(pConfigDscr);
				SUDPTRL = LSB(pConfigDscr);
				break;
		 case GD_STRING:            // String
				if(dscr_ptr = (void *)EZUSB_GetStringDscr(SETUPDAT[2]))
				{
					 SUDPTRH = MSB(dscr_ptr);
					 SUDPTRL = LSB(dscr_ptr);
				}
				else 
					 EZUSB_STALL_EP0();   // Stall End Point 0
				break;
		 case GD_DEVICE_QUALIFIER:            // Device Qualifier
				SUDPTRH = MSB(pDeviceQualDscr);
				SUDPTRL = LSB(pDeviceQualDscr);
				break;

		 case GD_OTHER_SPEED_CONFIGURATION:  // Other Speed Configuration
				SUDPTRH = MSB(pOtherConfigDscr);
				SUDPTRL = LSB(pOtherConfigDscr);
				break;
		 default:            // Invalid request
				EZUSB_STALL_EP0();      // Stall End Point 0
	}
	
   return(TRUE);
}

BOOL DR_SetConfiguration(void)   // Called when a Set Configuration command is received
{
  Configuration = SETUPDAT[2];
  return(TRUE);            // Handled by user code
}

BOOL DR_GetConfiguration(void)   // Called when a Get Configuration command is received
{
   EP0BUF[0] = Configuration;
   EP0BCH = 0;
   EP0BCL = 1;
   return(TRUE);            // Handled by user code
}

BOOL DR_SetInterface(void)       // Called when a Set Interface command is received
{
   AlternateSetting = SETUPDAT[2];
   return(TRUE);            // Handled by user code
}

BOOL DR_GetInterface(void)       // Called when a Set Interface command is received
{
   EP0BUF[0] = AlternateSetting;
   EP0BCH = 0;
   EP0BCL = 1;
   return(TRUE);            // Handled by user code
}

BOOL DR_GetStatus(void)
{
	switch(SETUPDAT[0])
	{
		 case GS_INTERFACE:         // Interface
				EP0BUF[0] = 0;
				EP0BUF[1] = 0;
				EP0BCH = 0;
				EP0BCL = 2;
				break;
		 case GS_DEVICE:            // Device
				EP0BUF[0] = ((BYTE)Rwuen << 1) | (BYTE)Selfpwr;
				EP0BUF[1] = 0;
				EP0BCH = 0;
				EP0BCL = 2;
				break;

		 case GS_ENDPOINT:         // End Point
				EP0BUF[0] = *(BYTE xdata *) epcs(SETUPDAT[4]) & bmEPSTALL;
				EP0BUF[1] = 0;
				EP0BCH = 0;
				EP0BCL = 2;
				break;
		 default:            // Invalid Command
				EZUSB_STALL_EP0();      // Stall End Point 0
	}
	return(TRUE);
}

BOOL DR_ClearFeature(void)
{
	switch(SETUPDAT[0])
	{
		 case FT_DEVICE:            // Device
				if(SETUPDAT[2] == 1)
					 Rwuen = FALSE;       // Disable Remote Wakeup
				else
					 EZUSB_STALL_EP0();   // Stall End Point 0
				break;
		 case FT_ENDPOINT:         // End Point
				if(SETUPDAT[2] == 0)
				{
					 *(BYTE xdata *) epcs(SETUPDAT[4]) &= ~bmEPSTALL;
					 EZUSB_RESET_DATA_TOGGLE( SETUPDAT[4] );
				}
				else
					 EZUSB_STALL_EP0();   // Stall End Point 0
				break;
   default:
    return DR_VendorCmnd();
	}
   return(TRUE);
}

BOOL DR_SetFeature(void)
{
	switch(SETUPDAT[0])
	{
		 case FT_DEVICE:            // Device
				if(SETUPDAT[2] == 1)
					 Rwuen = TRUE;      // Enable Remote Wakeup
				else if(SETUPDAT[2] == 2)
					 break;
				else
					 EZUSB_STALL_EP0();   // Stall End Point 0
				break;
		 case FT_ENDPOINT:         // End Point
				*(BYTE xdata *) epcs(SETUPDAT[4]) |= bmEPSTALL;
				break;
		default:
			return DR_VendorCmnd();
	}
   return(TRUE);
}

BOOL DR_VendorCmnd(void)
{
  switch (SETUPDAT[1])
  {
		case CMD_GET_FW_VERSION:
		{
			EP0BUF[0] = FX2LAFW_VERSION_MAJOR;
			EP0BUF[1] = FX2LAFW_VERSION_MINOR;
			EP0BCH = 0;
			EP0BCL = 2;
			return TRUE;
			break;
		}
		case CMD_GET_REVID_VERSION:
		{
			EP0BUF[0] = REVID;
			EP0BCH = 0;
			EP0BCL = 1;
			return TRUE;
			break;
		}
		case CMD_START:
		{
			vendor_command = SETUPDAT[1];
			EP0BCL = 0;
			SYNCDELAY;
			return TRUE;
			break;
		}
		default:
			EZUSB_STALL_EP0();            // Stall End Point 0
			return FALSE;
			break;
  }
}

//-----------------------------------------------------------------------------
// USB Interrupt Handlers
//   The following functions are called by the USB interrupt jump table.
//-----------------------------------------------------------------------------

// Setup Data Available Interrupt Handler
void ISR_Sudav(void) interrupt 0
{
   GotSUD = TRUE;            // Set flag
   EZUSB_IRQ_CLEAR();
   USBIRQ = bmSUDAV;         // Clear SUDAV IRQ
}

// Setup Token Interrupt Handler
void ISR_Sutok(void) interrupt 0
{
   EZUSB_IRQ_CLEAR();
   USBIRQ = bmSUTOK;         // Clear SUTOK IRQ
}

void ISR_Sof(void) interrupt 0
{
   EZUSB_IRQ_CLEAR();
   USBIRQ = bmSOF;            // Clear SOF IRQ
}

void ISR_Ures(void) interrupt 0
{
   // whenever we get a USB reset, we should revert to full speed mode
   pConfigDscr = pFullSpeedConfigDscr;
   ((CONFIGDSCR xdata *) pConfigDscr)->type = CONFIG_DSCR;
   pOtherConfigDscr = pHighSpeedConfigDscr;
   ((CONFIGDSCR xdata *) pOtherConfigDscr)->type = OTHERSPEED_DSCR;
   
   EZUSB_IRQ_CLEAR();
   USBIRQ = bmURES;         // Clear URES IRQ
}

void ISR_Susp(void) interrupt 0
{
   EZUSB_IRQ_CLEAR();
   USBIRQ = bmSUSP;
}

void ISR_Highspeed(void) interrupt 0
{
   if (EZUSB_HIGHSPEED())
   {
      pConfigDscr = pHighSpeedConfigDscr;
      ((CONFIGDSCR xdata *) pConfigDscr)->type = CONFIG_DSCR;
      pOtherConfigDscr = pFullSpeedConfigDscr;
      ((CONFIGDSCR xdata *) pOtherConfigDscr)->type = OTHERSPEED_DSCR;
   }

   EZUSB_IRQ_CLEAR();
   USBIRQ = bmHSGRANT;
}

按照上述方法修改完成后再修改dscr.a51文件既可以完成fx2lafw_8CH_Firmware固件的修改。

测试如下:选择fx2lafw设备

板载小灯单灯闪烁,PA1引脚

选择48M采集,采集数据长度为1G:实际采集波形如下,由于实际硬件未连接任何接口所以都是高电平。

 

将PB引脚进行试触采集:

这里需要注意的是下载完源码后,接在电脑上会出现识别带叹号的问题,需要使用zadig-2.8.exe将驱动修改替换为通用usb总线既即可如下图

驱动替换完成后显示如下

其实也可以改成16通道的采集模式,只需要修改描述文件的VID PID,还有初始化部分的自动FIFO模式中的数据宽度。但是改成16通道后采集速率不知道为啥只能使用12M及以下的采集速率。高了提示错误。

源码链接:

https://download.csdn.net/download/zhye3690592/89480606

  • 9
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
### 回答1: STM32 PLC是一款基于STM32微控制器开发的可编程逻辑控制器。底层源码是指该PLC的底层驱动程序及相关功能模块的代码。而FX2N源码是指一款常见的PLC芯片型号,可能是与STM32 PLC兼容的芯片。下面我将从两方面分别说明这两部分的源码。 对于STM32 PLC的底层源码,它包含了该PLC的主要驱动程序,如各种外设的驱动代码、通信协议的实现以及各种功能模块的初始化和配置等。通过分析底层源码,我们可以了解该PLC所支持的硬件资源和功能,例如串口、SPI、I2C、ADC、PWM等,并可以根据需求进行相关配置和扩展。此外,底层源码还可以帮助开发人员理解PLC的工作原理,优化性能,提高稳定性和可靠性。 而针对FX2N源码,它是FX2N芯片的驱动程序,FX2N是一种广泛应用于工业自动化领域的PLC芯片,也可能是与STM32 PLC兼容的硬件芯片。FX2N源码包含了该芯片的底层驱动程序,例如IO口的配置、定时器、计数器的使用等。通过分析FX2N源码,我们可以了解芯片的工作原理和功能特性,为后续的应用程序开发提供基础。同时,借助FX2N源码,我们还可以对该芯片进行优化和适配,满足特定应用的需求。 综上所述,STM32 PLC底层源码是提供给开发人员的该PLC的底层驱动程序和功能模块的代码,而FX2N源码是指FX2N芯片的驱动程序。通过分析这两部分源码,我们可以深入了解硬件的工作原理和特性,为PLC的开发和应用提供基础支持和优化。 ### 回答2: stm32 plc底层源码-fx2n源码指的是使用stm32作为主控芯片的PLC(可编程逻辑控制器)系统的底层源码,其中fx2n是一种常见的可编程控制器型号。 PLC是一种常用于自动化控制系统的设备,其底层源码是指PLC系统的核心代码,包括底层硬件操作相关的代码和与外部设备通信的代码。 stm32是一款常用的ARM Cortex-M系列的微控制器,具有较强的处理能力和丰富的外设接口,非常适合用于开发PLC系统。底层源码中的stm32部分负责控制外设、处理中断,以及管理存储器等功能。 而fx2n则是一种常用的可编程逻辑控制器,在PLC系统中扮演着重要的角色。fx2n的底层源码负责实现PLC的逻辑控制功能,包括对输入输出模块的读写操作、模拟量的测量和控制、定时器和计数器的管理等。 在stm32 plc底层源码-fx2n源码中,通常会包含底层驱动代码,如GPIO驱动、串口驱动、定时器驱动等,用于控制外设。同时还会包含IO处理代码,用于实现PLC的输入输出功能。此外,还会有一些逻辑控制相关的代码,用于处理程序的执行流程和逻辑判断。 综上所述,stm32 plc底层源码-fx2n源码是一种基于stm32和fx2n的PLC系统的核心代码,负责控制外设、处理输入输出、逻辑控制等功能。这些源码的存在使得开发者可以根据需要进行定制和修改,实现各种自动化控制应用。 ### 回答3: STM32 PLC底层源码-FX2N源码是指在STM32平台上实现FX2N PLC相应功能的源程序代码。 FX2N是三菱(Mitsubishi Electric)公司的一款经济实惠的中小规模程序控制器,常用于工业自动化控制领域。而STM32是意法半导体(STMicroelectronics)公司推出的一款低功耗、高性能的32位微控制器,广泛应用于各种领域。 STM32 PLC底层源码-FX2N源码的主要目标是通过STM32平台实现FX2N PLC的功能,包括输入输出控制、定时器计数器、数据存储等。底层源码通常包括对外设寄存器的读写、中断处理、时钟管理等功能的实现。 在编写STM32 PLC底层源码-FX2N源码时,需要参考FX2N PLC的手册和相关技术文档,了解FX2N PLC的寄存器映射和硬件特性。然后结合STM32微控制器的开发环境和库函数,编写相应的代码来实现FX2N PLC的各项功能。 在FX2N源码中,可能会包含与输入输出模块通信的代码、控制定时器计数器的代码、处理中断的代码等。这些代码通常涉及对STM32的外设寄存器的读写,以及相应的算法和逻辑。 值得注意的是,实现STM32 PLC底层源码-FX2N源码需要对FX2N PLC的工作方式和功能有深入的理解,并且需要熟悉STM32平台的开发环境和相关工具。同时,由于FX2N PLC可能有不同的变种,对于每个具体的FX2N PLC型号,还需要针对性地进行源码开发和适配。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

滴水的风

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值