本文主要是讲:在不使用FPGA外接器件的情况下以最大速率传输端口数据到PC上位机
其实如果你翻看过我上一篇讲解的SLAVE FIFO模式,其实这一篇主要是在我们仅有一个CY7C68013芯片开发板的基础上实现数据的实时高速读取48M的速率。
实现方法如下:
- 将FX2设置成同步slavefifo模式
- 然后使能内部IFCLK(bit7 必须置1)和输出IFCLK(也可以关闭clk引脚的输出)
- 配置EP2OUT EP6IN 禁用ep4 和 ep8
- FLAGB 被配置为 EP2 OUT FIFO 的空标志 EP2EF 非空为1;FLAGC 被配置为 EP6 IN FIFO 的满标志 EP6FF 非满为1
- 分别将端点 2 FIFO 和端点 6 配置为自动输出模式和自动输入模式 同时使用8位接口
代码如下:
void TD_Init(void) // Called once at startup
{
//设置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 = 0x80; /* FLAGB 被配置为 EP2 OUT FIFO 的空标志 EP2EF 非空为1 PC发送数据到CY7C68013->FPGA(MCU) Check 此标志为1则按照时序进行读取 */
SYNCDELAY;
PINFLAGSCD = 0x0E; /* FLAGC 被配置为 EP6 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;
EP2CFG = 0xA0; // OUT, 512-bytes, 4x, bulk
SYNCDELAY;
EP6CFG = 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位接口
EP2FIFOCFG = 0x00; // AUTOOUT=0, WORDWIDE=0
// core needs to see AUTOOUT=0 to AUTOOUT=1 switch to arm endp's
SYNCDELAY; //
EP2FIFOCFG = 0x10; // AUTOOUT=1, WORDWIDE=0
SYNCDELAY; //
EP6FIFOCFG = 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;
}
对于周期函数TD_Poll可以设置为以下示例,也可以为空
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 & bmEP2EMPTY) /* 如果 INEP2FIFO 为空 PA1-LED就翻转 */
{
PA1 = ~PA1;
}
if(!(EP2468STAT & bmEP6FULL)) /* 如果 INEP6FIFO 不满 PA0-LED就翻转 */
{
PA0 = ~PA0;
}
}
}
接下来就是关键了,按照以下说明设置好对应引脚的电平:
- FIFOADR0 拉低 FIFOADR1 拉高
- SLRD 拉高关闭读
- SLOE 拉高关闭读数据总线
- SLWR 拉低使能写
SLWR和SLRD千万不要弄错了,弄错了我们测试就失败了。
接下来我们就可以使用上位机去不停地读取PB引脚端口的状态了,选择EP6端口,长度2048(其实多少都可以),然后不停地读如下图
这两个图数据不一样原因是我在外部使用S32K单片机将端口状态在每1ms变换一次,这里还有一个疑问就是为啥每次传进来的数据都是一样的,这是因为我的端口变化速率太慢了,其实按照48M的速率读取你可以发现2048个字节的时间就是T = (1/48M)*2048 = 42.67us,也就是说你的变化速率比这个快才有可能在一次读取时看到不一样的数据。
总结:这样的话我们就可以在外部不适用任何FPGA的情况下以最大的传输速率将端口的状态读取上来,这里使用的是8位你也可以尝试改成16位,那么我们每次获取的数据时16bit 两个字节就是16个通道。
其实在这里还有一个小小的问题就是我们不能总是去点击读取数据,那么我们需要制作一个上位机进行快速的读取ep6in端口的数据,代替我们手动点击效果。上位机代码中选择我们的USB设备。
public void setDevice()
{
cydevice = deviceList[0x04B4,0x1004] as CyUSBDevice;
if (cydevice != null)
Text = cydevice.FriendlyName;
else
Text = "There is no device";
}
设置读取端口86 启动线程读取 显示在RICHTEXTBOX中。
public void DataGetFromPoint()
{
if (cydevice != null)
{
bufDataIn = new byte[inlenth];
cyBulkPointIn = cydevice.EndPointOf(0x86) as CyBulkEndPoint;
Recevicefo = cyBulkPointIn.XferData(ref bufDataIn, ref inlenth);
CurrentState.Invoke(showState ,Recevicefo.ToString ());
}
if (Recevicefo == true)
{
DataProcess();
//Thread.Sleep();
Array.Clear(bufDataIn, 0, 512);
DataGetFromPoint();
}
else
DataDisplay.Text = "There is no data receiving";
}
上位机显示结果如下图
到此,我们就实现了简单的快速读取FX2的PB端口数据,并在上位机上快速刷新显示。
相关上位机请参考以下链接