本方案是一个基于FPGA的二进制时钟,使用GPS作为时间参考。
历史上准确测量时间提出了许多挑战。只有约翰哈里森设计了一个可靠的时钟,它可以在格林威治子午线保持参考时间,从而能够在1700年代进行准确的导航以及绘制尚未开发的海洋和陆地的图表。
今天,我们生活在日益互联的世界中,准确的时间参考同样重要。如果没有一个共同的时间参考,当我们从一个信号塔传递到另一个信号塔时,信号塔就无法轻松同步代码和切换呼叫。同样,没有共同时间参考的时间戳业务和银行交易也可能具有挑战性,并成为事件顺序的仲裁噩梦。
当然,可用的最准确的时钟是原子钟,但遗憾的是,它们也是最昂贵的,这限制了机构使用它们的能力。
然而,有一个时间参考精确到+/-10ns,可以从空中免费提取,这就是全球导航卫星系统提供的时间参考。当然,其中最著名的是全球定位系统(GPS),尽管有几个,例如GLONASS和Galileo。
所有这些卫星都包含原子钟,这使我们能够实现跨系统的高度准确的时间参考。
在这个项目中,我们将使用GPS接收器Pmod接收GPS信号并对其进行处理,以便我们可以在二进制时钟上显示时间。
为此,我们将使用Vivado和SDK,这将是我们使用SDK的最后一个项目,因为Vitis可用。
维瓦多设计
要开始设计,我们需要做的第一件事是安装Digilent库,使我们能够配置PmodGPS/
该库支持在Vivado和SDK的硬件和软件开发中使用Pmod。
为此,请在我们的Vivado项目中选择、项目选项并选择IP并导航到新的IP存储库。
我们还需要一些东西来驱动NeoPixel显示器,同样对于之前的项目,我在这里将一个neopixelIP模块推送到我的github
然后我们就可以创建一个Vivado项目,该项目将利用这些IP模块与PmodGPS通信。
在新的Vivado项目中,我们需要以下IP
ZynqPS-为最小化配置
PmodGPS-将在软件控制下与PmodGPS通信
AXIBRAM控制器-使ZynqPS能够在PL中读取和写入BRAM
BRAM-双端口BRAM包含Neo像素值
NeoPixelIP-驱动NeoPixel驱动信号
处理器重置块-为系统提供重置
AXI互连-使多个AXI从设备能够连接到单个PS主设备
需要配置PS才能提供
50MHz时的结构时钟
20MHz的结构时钟-用于为NeoPixelIP提供时钟
GPMasterAXI接口
已启用结构中断
这应该会产生如下所示的框图
在生成和导出位流之前,我们还需要设置引脚的IO位置。
我将在PmodGPS的Minized上使用Pmod2,在NeoPixel驱动器上使用Pmod1我们在XDC文件中执行此操作,如下所示。
这样我们就可以实现设计并将硬件设计导出到SDK以生成所需的软件。
软件设计
在SDK中,我们需要根据刚刚从Vivado导出的硬件设计创建一个新的应用程序和BSP。
一旦在BSP中创建了它,我们应该会在BSPMSS文件中看到Pmod驱动程序。
对于更改,我们的软件应用程序将是中断驱动的。
我们的软件解决方案将遵循的架构是
配置和初始化PmodGPS
配置和初始化BRAM控制器
配置中断控制器并启用来自PmodGPSUART的中断。
等待PmodGPS锁定信号
从PmodGPS读取位置和时间数据
将时间转换为二进制元素进行显示
更新NeoPixel显示
为了使用PmodGPS和AXIBRAM控制器,我们可以使用PmodGPS.h和xbram.h中提供的API
虽然可以使用xscugic.h提供的API配置中断控制器
intSetupInterruptSystem(PmodGPS*InstancePtr,u32interruptDeviceID,u32interruptID){
intResult;
u16Options;
INTC*IntcInstancePtr=&intc;
XScuGic_Config*IntcConfig;
IntcConfig=XScuGic_LookupConfig(interruptDeviceID);
if(NULL==IntcConfig){
returnXST_FAILURE;
}
Result=XScuGic_CfgInitialize(IntcInstancePtr,IntcConfig,
IntcConfig-》CpuBaseAddress);
if(Result!=XST_SUCCESS){
returnXST_FAILURE;
}
XScuGic_SetPriorityTriggerType(IntcInstancePtr,interruptID,0xA0,0x3);
Result=XScuGic_Connect(IntcInstancePtr,interruptID,
(Xil_ExceptionHandler)XUartNs550_InterruptHandler,
&InstancePtr-》GPSUart);
if(Result!=XST_SUCCESS){
returnResult;
}
XScuGic_Enable(IntcInstancePtr,interruptID);
XUartNs550_SetHandler(&InstancePtr-》GPSUart,(void*)GPS_intHandler,
InstancePtr);
Xil_ExceptionInit();
Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,
(Xil_ExceptionHandler)INTC_HANDLER,IntcInstancePtr);
Xil_ExceptionEnable();
Options=XUN_OPTION_DATA_INTR|XUN_OPTION_FIFOS_ENABLE;
XUartNs550_SetOptions(&InstancePtr-》GPSUart,Options);
returnXST_SUCCESS;
}
我想做的第一件事是确保PmodGPS能够锁定信号并为我提供准确的位置。
当此代码在Pmod2连接到PmodGPS的Minized上执行时,我们会在终端上看到以下输出,为我提供了一个位置。
为了检查这是正确的位置,将它输入到谷歌地图中可以以合理的精度提供我办公室的位置。
由于能够锁定GPS信号,因此更新了代码以提供时间。这个时间被称为协调世界时或简称UTC,UTC参考格林威治标准时间,目前也恰好与英国的时间相同。
时间作为浮点数从PmodGPS输出,如下面的终端输出所示。
为了能够创建一个二进制时钟,我们需要将其分解为以下内容
小时几十
小时单位
分十
分钟单位
秒十
秒单位
这将使我们能够使用NeoPixelArray绘制时间。
二进制时钟显示时间如下
在NeoPixel上,我将在阵列中间使用6x4LED阵列。
但首先我们需要将UTC时间转换为所需的格式,我们可以使用以下方法将时间(例如153400)拆分为正确的小时、分钟和秒分组。
然后我们可以根据二进制时间显示的需要将每个元素分成十位和单位。
一旦我们分离了数字,我们就需要将值转换为二进制值,为此我创建了一个简单的子例程
这个函数返回一个代表二进制数的四位向量,对于这个例子,我们不需要超过4位。
由于NeoPixel阵列被视为一个长64NeoPixel元素,因此对于每个计数位置,我们只需要更改LED偏移位置。
根据该位是否已设置,LED的颜色是否会发生变化,设置的位为绿色,否则为蓝色。
我使用下面的代码来确定设置LED的值,因为二进制转换函数返回一个指针。
当我把所有这些放在一起时,一旦PmodGPS锁定信号,二进制时钟就会按预期运行。
确认
对于许多人来说,读取二进制时钟可能与传统时钟不同。因此,通过终端查看NeoPixel显示和UTC时间输出,我们可以验证显示是否正确。
解码后的时间看起来是正确的。
结论
该项目演示了我们如何轻松快速地将GPS用于导航以外的系统,并创建一个有趣的示例,该示例可用作显示器等。
这里还没有内容,您有什么问题吗?