×

如何通过SPI使用Raspberry PI零与FPGA通信

消耗积分:0 | 格式:zip | 大小:0.00 MB | 2023-06-13

李凤津

分享资料个

描述

概述

目标是使用 Raspberry PI 零(或 2W)和 RealTime Linux 补丁运行飞行计算机的 BaseFlight 修改版本。其中一个问题是生成 OneShot 协议以从 BaseFlight 控制 ESC(电机控制器)。那么,为什么不使用 FPGA 来生成 OneShot 信号,而不是使用 PI 上的资源来生成信号。

Buildroot 用于创建带有实时补丁 Linux 内核的发行版。(如果您需要有关如何操作的更多信息,请告诉我)

该项目不详细介绍如何逐步创建 Vivado 项目和使用 iverlog 验证设计。请在下面评论您想要更多详细信息,我会添加它。

如何与FPGA通信

PI有SPI、TTL串口、I2C、USB。该协议需要快速和简单,因此选择 SPI 作为物理传输。下一个问题是如何向FPGA发送简单的读写命令并进行处理。此外,如果有一种方法可以添加功能/外设,那就太好了。

FPGA通信设计

为了简单起见,让我们使用硬件总线,它有一个定义的方式来访问不同的内存块,例如:

  • 地址即32位:访问不同的寄存器或设备
  • 数据总线读写寄存器

Wishbone是为本设计选择的简单总线。 AXI Lite 本来可以用的,也许下次吧。AXI用于ARM处理器,规格详细,例子多。

下图是FPGA系统的基本框图:

poYBAGSAhNeAP806AAAxojbPQdM528.png
基本图
 

FPGA代码和外部库

下面提供了代码。

SPI 接口来自这里Wishbone 库来自这里MUX 是使用 wishbone 库中的 python 脚本生成的。

复杂性在于 Wishbone 库的使用方式,它使用两个 AXIS 端口,一个传输端口和一个接收端口。需要创建胶合逻辑以连接 SPI 接口和叉骨 AXIS 接口。

控制 LED 的示例

一种简单的测试方法是不使用 MUX 并将 LED 外围设备直接连接到 Wishbone 库。如下所示:

pYYBAGSAhNqATkgmAAD44-A01no836.png
Vivado 图
 

映射 FPGA 引脚

随板提供的约束文件被修改为映射 SPI 引脚、MISO、MOSI、CLK 和 CLK。此外,四个 LED 与 RGB LED 一起映射。

使用PI测试FPGA

spidev0.1 即 SPI0 MISO、SPI0 MOSI、SPI0 CLK 和 CE1 连接到 FPGA。

下面展示的是如何使用终端发送SPI字节序列来读写字节流。这是一个例子:

# printf '\xA2\x1\x2\x3\x0\x0\x4\x11\x22\x33\x44\0' | spi-pipe -m 0 -s 1000000 -d /dev/spidev0.1 | hexdump -C
00000000  44 44 a4 01 02 03 00 00  04 04 04 04              |DD..........|
0000000c
#

0xA2:是写命令字节

0x01020300 是要写入的地址

0x0004 是要写入的字节数

0x44332211 是要写入的字节(注意字节是颠倒的)

读书:

# printf '\xA1\x1\x2\x3\x0\x0\x4\x0\x0\x0\x0\0\0' | spi-pipe -m 0 -s 100000 -d /dev/spidev0.1 | hexdump -C
00000000  04 04 a3 01 02 03 00 00  04 11 22 33 44           |.........."3D|
0000000d
#

返回的是,0x04,0x04 是两个字节,是垃圾。接下来的字节是回复:

0xA3 是对读取的回复

0x01020300是地址

0x00 0x04 是长度

0x44332211 是写入的数据

使用 iverlog 进行单元测试

有几个测试平台,用于验证 pwm 解码的 tb_pwmdecoder_wb.v 应该使用 100Mhz 时钟。tb_spiwishbone.v 将 SPI 数据发送到读写寄存器。

证实

下面显示的是显示写命令序列的逻辑分析仪轨迹。在项目中有一个 python 脚本可以通过 spidev 设置 LED。SPI 频率为 3.2Mhz。在 PI 上下载ledTester.py并发出以下命令。

# python ledTester.py

该脚本将尽快编写命令。从跟踪中,命令以 2.6Khz 的速率发送。

pYYBAGSAhN6ACHexAAFkQTpXIhM893.png
 
poYBAGSAhOeAIPvGAAGf3WUvE2w664.png
 

 


声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

评论(0)
发评论

下载排行榜

全部0条评论

快来发表一下你的评论吧 !

'+ '

'+ '

'+ ''+ '
'+ ''+ ''+ '
'+ ''+ '' ); $.get('/article/vipdownload/aid/'+webid,function(data){ if(data.code ==5){ $(pop_this).attr('href',"/login/index.html"); return false } if(data.code == 2){ //跳转到VIP升级页面 window.location.href="//m.lene-v.com/vip/index?aid=" + webid return false } //是会员 if (data.code > 0) { $('body').append(htmlSetNormalDownload); var getWidth=$("#poplayer").width(); $("#poplayer").css("margin-left","-"+getWidth/2+"px"); $('#tips').html(data.msg) $('.download_confirm').click(function(){ $('#dialog').remove(); }) } else { var down_url = $('#vipdownload').attr('data-url'); isBindAnalysisForm(pop_this, down_url, 1) } }); }); //是否开通VIP $.get('/article/vipdownload/aid/'+webid,function(data){ if(data.code == 2 || data.code ==5){ //跳转到VIP升级页面 $('#vipdownload>span').text("开通VIP 免费下载") return false }else{ // 待续费 if(data.code == 3) { vipExpiredInfo.ifVipExpired = true vipExpiredInfo.vipExpiredDate = data.data.endoftime } $('#vipdownload .icon-vip-tips').remove() $('#vipdownload>span').text("VIP免积分下载") } }); }).on("click",".download_cancel",function(){ $('#dialog').remove(); }) var setWeixinShare={};//定义默认的微信分享信息,页面如果要自定义分享,直接更改此变量即可 if(window.navigator.userAgent.toLowerCase().match(/MicroMessenger/i) == 'micromessenger'){ var d={ title:'如何通过SPI使用Raspberry PI零与FPGA通信',//标题 desc:$('[name=description]').attr("content"), //描述 imgUrl:'https://'+location.host+'/static/images/ele-logo.png',// 分享图标,默认是logo link:'',//链接 type:'',// 分享类型,music、video或link,不填默认为link dataUrl:'',//如果type是music或video,则要提供数据链接,默认为空 success:'', // 用户确认分享后执行的回调函数 cancel:''// 用户取消分享后执行的回调函数 } setWeixinShare=$.extend(d,setWeixinShare); $.ajax({ url:"//www.lene-v.com/app/wechat/index.php?s=Home/ShareConfig/index", data:"share_url="+encodeURIComponent(location.href)+"&format=jsonp&domain=m", type:'get', dataType:'jsonp', success:function(res){ if(res.status!="successed"){ return false; } $.getScript('https://res.wx.qq.com/open/js/jweixin-1.0.0.js',function(result,status){ if(status!="success"){ return false; } var getWxCfg=res.data; wx.config({ //debug: true, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。 appId:getWxCfg.appId, // 必填,公众号的唯一标识 timestamp:getWxCfg.timestamp, // 必填,生成签名的时间戳 nonceStr:getWxCfg.nonceStr, // 必填,生成签名的随机串 signature:getWxCfg.signature,// 必填,签名,见附录1 jsApiList:['onMenuShareTimeline','onMenuShareAppMessage','onMenuShareQQ','onMenuShareWeibo','onMenuShareQZone'] // 必填,需要使用的JS接口列表,所有JS接口列表见附录2 }); wx.ready(function(){ //获取“分享到朋友圈”按钮点击状态及自定义分享内容接口 wx.onMenuShareTimeline({ title: setWeixinShare.title, // 分享标题 link: setWeixinShare.link, // 分享链接 imgUrl: setWeixinShare.imgUrl, // 分享图标 success: function () { setWeixinShare.success; // 用户确认分享后执行的回调函数 }, cancel: function () { setWeixinShare.cancel; // 用户取消分享后执行的回调函数 } }); //获取“分享给朋友”按钮点击状态及自定义分享内容接口 wx.onMenuShareAppMessage({ title: setWeixinShare.title, // 分享标题 desc: setWeixinShare.desc, // 分享描述 link: setWeixinShare.link, // 分享链接 imgUrl: setWeixinShare.imgUrl, // 分享图标 type: setWeixinShare.type, // 分享类型,music、video或link,不填默认为link dataUrl: setWeixinShare.dataUrl, // 如果type是music或video,则要提供数据链接,默认为空 success: function () { setWeixinShare.success; // 用户确认分享后执行的回调函数 }, cancel: function () { setWeixinShare.cancel; // 用户取消分享后执行的回调函数 } }); //获取“分享到QQ”按钮点击状态及自定义分享内容接口 wx.onMenuShareQQ({ title: setWeixinShare.title, // 分享标题 desc: setWeixinShare.desc, // 分享描述 link: setWeixinShare.link, // 分享链接 imgUrl: setWeixinShare.imgUrl, // 分享图标 success: function () { setWeixinShare.success; // 用户确认分享后执行的回调函数 }, cancel: function () { setWeixinShare.cancel; // 用户取消分享后执行的回调函数 } }); //获取“分享到腾讯微博”按钮点击状态及自定义分享内容接口 wx.onMenuShareWeibo({ title: setWeixinShare.title, // 分享标题 desc: setWeixinShare.desc, // 分享描述 link: setWeixinShare.link, // 分享链接 imgUrl: setWeixinShare.imgUrl, // 分享图标 success: function () { setWeixinShare.success; // 用户确认分享后执行的回调函数 }, cancel: function () { setWeixinShare.cancel; // 用户取消分享后执行的回调函数 } }); //获取“分享到QQ空间”按钮点击状态及自定义分享内容接口 wx.onMenuShareQZone({ title: setWeixinShare.title, // 分享标题 desc: setWeixinShare.desc, // 分享描述 link: setWeixinShare.link, // 分享链接 imgUrl: setWeixinShare.imgUrl, // 分享图标 success: function () { setWeixinShare.success; // 用户确认分享后执行的回调函数 }, cancel: function () { setWeixinShare.cancel; // 用户取消分享后执行的回调函数 } }); }); }); } }); } function openX_ad(posterid, htmlid, width, height) { if ($(htmlid).length > 0) { var randomnumber = Math.random(); var now_url = encodeURIComponent(window.location.href); var ga = document.createElement('iframe'); ga.src = 'https://www1.elecfans.com/www/delivery/myafr.php?target=_blank&cb=' + randomnumber + '&zoneid=' + posterid+'&prefer='+now_url; ga.width = width; ga.height = height; ga.frameBorder = 0; ga.scrolling = 'no'; var s = $(htmlid).append(ga); } } openX_ad(828, '#berry-300', 300, 250);