3回答

0收藏

领航者ZYNQ开发板试用3:PS I2C外设读写RTC模块

FPGA/DSP FPGA/DSP 8442 人阅读 | 3 人回复 | 2020-02-19

领航者ZYNQ开发板的底板上带有一个RTC实时时钟芯片和后备电池,实时时钟芯片型号是NXP的PCF8563, 该芯片还提供可编程时钟输出、一个定时器、一个报警器和一个掉电检测器,定时器和报警器都可以通过中断脚进行输出,但领航者ZYNQ开发板没有连接中断信号和时钟输出到Zynq芯片,只有连接I2C总线到Zynq芯片实现对实时时钟芯片的读写控制,原理图如下所示:


注意这里I2C总线是3.3V,并且是连接到Zynq芯片的PL侧,具体的实时时钟芯片功能请参考正点原子提供的【正点原子】领航者 ZYNQ开发板光盘资料\领航者ZYNQ开发板资料盘(A盘)\7_硬件资料\2_芯片资料目录下PCF8563.pdf数据手册,另外《领航者ZYNQ之FPGA开发指南_V1.1.pdf》文档的第21章RTC实时时钟LCD显示实验(第407页~428页)需要先学习下,配套的实验源码工程可以在【正点原子】领航者 ZYNQ开发板光盘资料\领航者ZYNQ开发板资料盘(A盘)\4_SourceCode\ZYNQ_7010目录下的1_FPGA_Design.rar压缩包内找到,压缩包的16_rtc_lcd文件夹就是,该工程完全是用PL逻辑实现,解压后编译下载得到验证结果应该不难,具体步骤就不再描述了,我们知道Zynq芯片的PS侧是ARM Cortex-A9内核,并且带有两个I2C外设,使用ARM编程的方法较PL要灵活,故接下我设计的实验任务是用PS(ARM)的I2C外设来访问RTC模块,并通过串口打印出时间日期,具体实验步骤如下:

1、我们解压【正点原子】领航者 ZYNQ开发板光盘资料\领航者ZYNQ开发板资料盘(A盘)\4_SourceCode\ZYNQ_7010\2_Embedded_System.rar压缩包内的1_hello_world文件夹,我们将在这个工程基础上修改。
2、用vavido2018.3工具打开hello_world.xpr工程,然后点工程左侧Flow Navigator内的Open Block Design, 双击Zynq7 Processing System出现IP配置界面,按下图使能I2C_0外设,这里是通过EMIO输出:


3、点击IIC_0信号后按CRTL+T建立外部连接,然后Create HDL Wrapper和Generate Output Product, 因为是通过EMIO输出I2C信号,所以还需要编译PL下载比特流,并要添加约束文件按原理图指定正确的脚位,用下面的管脚约束语句:

set_property -dict {PACKAGE_PIN M17 IOSTANDARD LVCMOS33}[get_ports IIC_0_0_scl_io]

set_property -dict {PACKAGE_PIN M18 IOSTANDARD LVCMOS33}[get_ports IIC_0_0_sda_io]

4、工程主界面选择File—Export—Export Hardware..., 这里要勾选上Includebitstream。
5、工程主界面选择File—Launch SDK,然后在SDK软件先删除原来的工程,重新新建一个hello world工程,注意在BSP包要勾选上裸机库,如下图所示:


最后大家可以先下载到开发板验证下是否可以在串口上打印出hello world。

6、修改软件工程下helloworld.c为如下所示代码,使用PS的I2C驱动读写RTC芯片:
  1. <div align="left"></div>
  2. <div align="left">#include <stdio.h></div>
  3. <div align="left">#include "platform.h"</div>
  4. <div align="left">#include "xil_printf.h"</div>
  5. <div align="left">#include "xiicps.h"</div>
  6. <div align="left">#include "sleep.h"</div>
  7. <div align="left"> </div>
  8. <div align="left">#define IIC_DEVICE_ID         XPAR_XIICPS_0_DEVICE_ID</div>
  9. <div align="left">#define IIC_SLAVE_ADDR           0x51</div>
  10. <div align="left">#define IIC_SCLK_RATE       100000</div>
  11. <div align="left">#define TEST_BUFFER_SIZE 10</div>
  12. <div align="left">u8 SendBuffer[TEST_BUFFER_SIZE];</div>
  13. <div align="left">u8 RecvBuffer[TEST_BUFFER_SIZE];</div>
  14. <div align="left">XIicPs Iic;       /**<Instance of the IIC Device */</div>
  15. <div align="left"> </div>
  16. <div align="left">typedef struct RtcTime</div>
  17. <div align="left">{</div>
  18. <div align="left">  u8 sec;</div>
  19. <div align="left">  u8 min;</div>
  20. <div align="left">  u8 hour;</div>
  21. <div align="left">  u8 day;</div>
  22. <div align="left">  u8 mon;</div>
  23. <div align="left">  u8 year;</div>
  24. <div align="left">}RtcTime;</div>
  25. <div align="left"> </div>
  26. <div align="left">int IicPsInitSetTime(RtcTime *Time)</div>
  27. <div align="left">{</div>
  28. <div align="left">       int Status;</div>
  29. <div align="left">       XIicPs_Config*Config;</div>
  30. <div align="left"> </div>
  31. <div align="left">       /*</div>
  32. <div align="left">        * Initialize the IIC driver so that it's readyto use</div>
  33. <div align="left">        * Look up the configuration in the configtable,</div>
  34. <div align="left">        * then initialize it.</div>
  35. <div align="left">        */</div>
  36. <div align="left">       Config =XIicPs_LookupConfig(IIC_DEVICE_ID);</div>
  37. <div align="left">       if (NULL == Config){</div>
  38. <div align="left">              returnXST_FAILURE;</div>
  39. <div align="left">       }</div>
  40. <div align="left"> </div>
  41. <div align="left">       Status =XIicPs_CfgInitialize(&Iic, Config, Config->BaseAddress);</div>
  42. <div align="left">       if (Status !=XST_SUCCESS) {</div>
  43. <div align="left">              returnXST_FAILURE;</div>
  44. <div align="left">       }</div>
  45. <div align="left"> </div>
  46. <div align="left">       /*</div>
  47. <div align="left">        * Perform a self-test to ensure that thehardware was built correctly.</div>
  48. <div align="left">        */</div>
  49. <div align="left">       Status =XIicPs_SelfTest(&Iic);</div>
  50. <div align="left">       if (Status !=XST_SUCCESS) {</div>
  51. <div align="left">              returnXST_FAILURE;</div>
  52. <div align="left">       }</div>
  53. <div align="left"> </div>
  54. <div align="left">       /*</div>
  55. <div align="left">        * Set the IIC serial clock rate.</div>
  56. <div align="left">        */</div>
  57. <div align="left">       XIicPs_SetSClk(&Iic,IIC_SCLK_RATE);</div>
  58. <div align="left">       /*</div>
  59. <div align="left">        * Initialize the send buffer bytes with apattern to send.</div>
  60. <div align="left">        */</div>
  61. <div align="left">       SendBuffer[0] = 2;//address</div>
  62. <div align="left">       SendBuffer[1] =Time->sec;</div>
  63. <div align="left">       SendBuffer[2] =Time->min;</div>
  64. <div align="left">       SendBuffer[3] =Time->hour;</div>
  65. <div align="left">       SendBuffer[4] = 0;</div>
  66. <div align="left">       SendBuffer[5] =Time->day;</div>
  67. <div align="left">       SendBuffer[6] =Time->mon;</div>
  68. <div align="left">       SendBuffer[7] =Time->year;</div>
  69. <div align="left">       /*</div>
  70. <div align="left">        * Send the buffer using the IIC and ignore thenumber of bytes sent</div>
  71. <div align="left">        * as the return value since we are using it ininterrupt mode.</div>
  72. <div align="left">        */</div>
  73. <div align="left">       Status =XIicPs_MasterSendPolled(&Iic, SendBuffer, 8, IIC_SLAVE_ADDR);</div>
  74. <div align="left">       if (Status !=XST_SUCCESS) {</div>
  75. <div align="left">              returnXST_FAILURE;</div>
  76. <div align="left">       }</div>
  77. <div align="left"> </div>
  78. <div align="left">       /*</div>
  79. <div align="left">        * Wait until bus is idle to start anothertransfer.</div>
  80. <div align="left">        */</div>
  81. <div align="left">       while(XIicPs_BusIsBusy(&Iic)) {</div>
  82. <div align="left">              /* NOP */</div>
  83. <div align="left">       }</div>
  84. <div align="left"> </div>
  85. <div align="left">       return XST_SUCCESS;</div>
  86. <div align="left">}</div>
  87. <div align="left">int IicPsGetTime(RtcTime *Time)</div>
  88. <div align="left">{</div>
  89. <div align="left">       int Status;</div>
  90. <div align="left"> </div>
  91. <div align="left">       Status =XIicPs_MasterSendPolled(&Iic, SendBuffer, 1, IIC_SLAVE_ADDR);</div>
  92. <div align="left">       if (Status !=XST_SUCCESS) {</div>
  93. <div align="left">              returnXST_FAILURE;</div>
  94. <div align="left">       }</div>
  95. <div align="left"> </div>
  96. <div align="left">       Status =XIicPs_MasterRecvPolled(&Iic, RecvBuffer,</div>
  97. <div align="left">                       7, IIC_SLAVE_ADDR);</div>
  98. <div align="left">       if (Status !=XST_SUCCESS) {</div>
  99. <div align="left">              returnXST_FAILURE;</div>
  100. <div align="left">       }</div>
  101. <div align="left">       else{</div>
  102. <div align="left">              Time->sec  = RecvBuffer[0];</div>
  103. <div align="left">              Time->min  = RecvBuffer[1];</div>
  104. <div align="left">              Time->hour= RecvBuffer[2] & 0x3f;</div>
  105. <div align="left">              Time->day  = RecvBuffer[4];</div>
  106. <div align="left">              Time->mon  = RecvBuffer[5];</div>
  107. <div align="left">              Time->year= RecvBuffer[6];</div>
  108. <div align="left">              returnXST_SUCCESS;</div>
  109. <div align="left">       }</div>
  110. <div align="left">}</div>
  111. <div align="left"> </div>
  112. <div align="left">int main()</div>
  113. <div align="left">{</div>
  114. <div align="left">       int Status;</div>
  115. <div align="left">       RtcTime Time;</div>
  116. <div align="left"> </div>
  117. <div align="left">       init_platform();</div>
  118. <div align="left">    printf("Test Rtcmodule use ps i2c peripheral.\n\r");</div>
  119. <div align="left"> </div>
  120. <div align="left">    Time.sec  = 0x30;</div>
  121. <div align="left">    Time.min  = 0x59;</div>
  122. <div align="left">    Time.hour = 0x09;</div>
  123. <div align="left">    Time.day  = 0x31;</div>
  124. <div align="left">    Time.mon  = 0x01;</div>
  125. <div align="left">    Time.year = 0x20;</div>
  126. <div align="left">       Status =IicPsInitSetTime(&Time);</div>
  127. <div align="left">       if (Status !=XST_SUCCESS) {</div>
  128. <div align="left">              printf("IicPsInitSetTimeFail!\n\r");</div>
  129. <div align="left">       }</div>
  130. <div align="left">       else while(1)</div>
  131. <div align="left">       {</div>
  132. <div align="left">              Status =IicPsGetTime(&Time);</div>
  133. <div align="left">              if (Status !=XST_SUCCESS) {</div>
  134. <div align="left">             printf("IicPsGetTimeFail!\n\r");</div>
  135. <div align="left">              }</div>
  136. <div align="left">              else</div>
  137. <div align="left">              {</div>
  138. <div align="left">                printf("Rtc time:  %x : %x: %x\n\r", Time.hour, Time.min,Time.sec);</div>
  139. <div align="left">              }</div>
  140. <div align="left">              //delay 5s</div>
  141. <div align="left">              sleep(5);</div>
  142. <div align="left">       }</div>
  143. <div align="left"> </div>
  144. <div align="left">    cleanup_platform();</div>
  145. <div align="left">    return 0;</div>
  146. <div align="left">}</div>
复制代码

编译下载后可以看到每5秒在串口上打印一次时间,测试过程和结果如下视频所示:


最后提下,底板上有个8K字节的EEPROM芯片AT24C64也是通过同一个I2C总线连接,可以直接通过软件修改从机地址为0x50后用相同驱动来访问(已验证过)。


分享到:
回复

使用道具 举报

回答|共 3 个

倒序浏览

沙发

megamind

发表于 2020-9-2 23:48:02 | 只看该作者

你好,我调试这段代码的时候,程序每次进入XIicPs_MasterSendPolled都没有应答信号,总是停在Check for completion of transfer.
回复 支持 反对

使用道具 举报

板凳

1号哨兵

发表于 2020-12-1 11:52:04 | 只看该作者

megamind 发表于 2020-9-2 23:48
你好,我调试这段代码的时候,程序每次进入XIicPs_MasterSendPolled都没有应答信号,总是停在Check for com ...

我也遇到同样的问题,不知道您解决了没,能否指点一下
回复 支持 反对

使用道具 举报

地板

eefocus_3940577

发表于 2023-9-6 19:59:34 来自手机 | 只看该作者

1号哨兵 发表于 2020-12-1 11:52
我也遇到同样的问题,不知道您解决了没,能否指点一下

2023年了,依然还是这个问题
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 注册/登录

本版积分规则

关闭

站长推荐上一条 /3 下一条