一、创建 Vivado 工程
1-1 打开 Vivado ,进入 Vivado 界面后,点击“ Quick Start ”栏的 “ Create Project ”。然后在弹出的创
建 Vivado 工程向导界面,点击“Next”。
1-2 进入工程命名界面。设置工程名为“ hello_world” ,工程路径可使用任意路径,本章我们将该工程 放在 F:\ZYNQ\Embedded_System 文件夹下。注意, 工程名和路径只能由英文字母、数字和下划线组成 , 不 能包含中文、空格以及特殊字符!
确认已经勾选“ Create project subdirectory ” , 点击“ Next ”。
1-3 进入图 1.3.4 所示的界面,在此界面设置工程类型。此处我们选择 “ RTL Project ”。本次实验不需要添加源文件和约束文件,所以勾选“ Do not specify sources at this time ”。勾选之后会省略后面添加源文件和约束文件的步骤,点击“Next ”直接跳到器件选型界面。
1-4 器件选型界面。所选择的器件型号一定要跟领航者核心板上的 ZYNQ 芯片型号保持一致。 大家可以通过查看核心板上 ZYNQ 芯片的丝印来确认所使用的芯片型号。 XC7Z020 的为“-2”,这在器件选型的时候需要注意。此处以 XC7Z020 为例。 选择器件型号的方式有两种,一种是根据 Parts,另一种是根据 Boards ,此处我们使用 Parts 选择器件。 在 Family 栏里选择“ Zynq-7000 ” , Speed 栏选择“-2”,需要注意的是,在 Package 栏选择“ clg400 ”。然后根据所使用的领航者核心板上的 ZYNQ 芯片型号,在下面的器件列表中选择“ xc7z020clg400-2”。选中之后,点击“ Next ”。
1-5 工程摘要界面。这是创建工程的最后一步,显示工程摘要信息,如 图 1.3.6 所示。在此界面检查前面所设置的工程名称、所选择的器件型号等信息。如果发现工程设置有误,则可以通过 Back 按钮返回前面的步骤,重新设置。检查无误后点击“Finish ”,完成工程创建。
二、创建 Processing System
Vivado 开发套件中提供了一个图形化的设计开发工具 ——IP 集成器( IP Integrator ),在 IP 集成器中可以非常方便的插入各种功能模块(IP )。它支持关键 IP 接口的智能自动连接、一键式 IP 子系统生成、实时 DRC 等功能,能够帮助我们快速组装复杂系统,加速设计流程。接下来我们将在 IP 集成器中完成 ZYNQ 嵌入式系统的搭建。
2-1 在左侧导航栏( Flow Navigator )中,单击 IP Integrator 下的 Create Block Design 。然后在弹出的对话框中指定所创建的 Block Design 的名称,在 Design name 栏中输入“ system ”。如下图所示:
2-2 点击“ OK ”按钮,此时 Vivado 界面如下图所示。注意右侧的 Diagram 窗口,我们将在该窗口中以图形化的方式完成设计。
2-3 接下来在 Diagram 窗口中给设计添加 IP 。点击上图中箭头所指示的加号“ + ”,会打开 IP 目录( IP Catalog)。也可以通过快捷键 Ctrl + I ,或者右键点击 Diagram 工作区中的空白位置,然后选择“ ADD IP ”。
2-4 打开 IP 目录后,在搜索栏中键入“ zynq ”,找到并双击“ ZYNQ7 Processing System ”,将 ZYNQ7 处理系统 IP 添加到设计中。
2-5 添加完成后,ZYNQ7 Processing System 模块出现在 Diagram 中,如下图所示:
2-6 双击所添加的 ZYNQ7 Processing System 模块,进入 ZYNQ7 处理系统的配置界面。界面左侧为页 面导航面板,右侧为配置信息面板。如下图所示:
下面我们简要地介绍一下页面导航面板中各个页面的作用。
在 Zynq Block Design 页面,显示了 Zynq 处理系统( PS )的各种可配置块,其中灰色部分是固定的, 绿色部分是可配置的,按工程实际需求配置。可以直接单击各种可配置块(以绿色突出显示)进入相应的 配置页面进行配置,也可以选择左侧的页导航面板进行系统配置。
PS-PL Configuration 页面能够配置 PS-PL 接口,包括 AXI 、 HP 和 ACP 总线接口。
Peripheral IO Pins 页面可以为不同的 I/O 外设选择 MIO/EMIO 配置。
MIO Configuration 页面可以为不同的 I/O 外设具体配置 MIO/EMIO 。
Clock Configuration 页面用来配置 PS 输入时钟、外设时钟,以及 DDR 和 CPU 时钟等。
DDR Configuration 页面用于设置 DDR 控制器配置信息。
SMC Timing Calculation 页面用于执行 SMC 时序计算。
Interrupts 页面用于配置 PS-PL 中断端口。
三、配置ZYNQ7 Processing System
(1)配置 PS 的 UART
点击 Peripheral I/O Pins 页面,出现以下 IO 引脚配置界面。
PS 和外部设备之间的连接主要是通过复用的输入 / 输出( Multiplexed Input/Output , MIO )来实现的。PS的 54 个 MIO 引脚可以用于连接不同的外设接口,如图 中的 MIO14 和 MIO15 ,既可以配置成 UART0 的引脚接口,也可以配置成 I2C0 或 CAN0 的引脚接口。最终所选择的配置需要与开发板的原理图相对应。
点击左侧的 MIO Configuration 页面,在右侧展开 I/O Peripherals > UART0 ,可以看到更具体的引脚配置信息。其中 MIO14 作为 RX 引脚、 MIO15 作为 TX 引脚,如下图所示:
点击左侧的 PS-PL Configuration 页面,我们可以在这里设置 UART0 串口通信的波特率。在 General 目录下,可以看到 UART0 的波特率默认是 115200 。通过下拉按钮可以选择其他波特率,一般保持默认设置。
(2)配置 PS 的 GPIO MIO
点击左侧的 Peripheral I/O Pins ,在右侧的界面中勾选 GPIO_MIO ,另外开发板上的Bank1 即原理图中的 BANK501 为 1.8V ,所以我们选择 3 处的 Bank1 电压为 LVCOMS 1.8V 。勾选 GPIO_MIO 后,发现在 GPIO_MIO 这一栏 GPIO_MIO14 和 15 是灰色的,这是因为这两个 GPIO_MIO 用做 UART0 的接口引脚了。
(3)配置 PS 的 IIC
要勾选上Quad SPI Flash
配置I2C 0 为14 15
(4)配置 PS 的 DDR3 控制器
点击左侧的 DDR Configuration 页面,在右侧 DDR Controller Configuration 下的“ Memory Part ”一栏选择 DDR 的器件,课题组自己制作的zynq7020板子为MT41K128M16JT-125,DRAM为16Bit;领航者XC7Z020 的核心板选择 MT41J256M16RE-125 , XC7Z010 的核心板选择 MT41J128M16 HA-125 。领航者选择的型号并不是领航者核心板上的 DDR3 型号,而是参数接近的型号,或者说兼容的型号。其他的配置选项保持默认即可。
(5)配置 PS 的时钟
点击左侧的 Clock Configuration 页面,该界面主要是配置 ZYNQ PS 中的时钟频率。比如输入时钟默认 是 33.33333Mhz ,这与我们领航者核心板上的 PS 端输入时钟频率相同。对于 CPU 的时钟、 DDR 的时钟以及其它外设的时钟,我们直接保持默认设置即可。如下图所示:
(6)取消勾选没有用到的接口
因为本实验是搭建 ZYNQ 的嵌入式最小系统,只需要使用 ZYNQ 中的 PS 端。因此我们将 PS 中与 PL 端交互的接口信号移除。 同样是在 Clock Configuration 页面,展开 PL Fabric Clocks ,取消勾选 FCLK_CLK0 ,如下图所示:
点击左侧的 PS-PL Configuration 页面,然后在右侧展开 General 下的 Enable Clock Resets ,取消勾选其中的 FCLK_RESET0_N 。 另外在当前界面中展开 AXI Non Secure Enablement 下的 GP Master AXI Interface ,取消勾选其中的 MAXI GP0 interface。如下图所示:
配置 ZYNQ7 Processing System 完成,点击“OK”。
点击上图中箭头所指示的位置“Run Block Automation”,会弹出如下图所示的对话框:
在该界面中我们可以选择自动连接 IP 模块的接口,包括导出外部端口,甚至可以自动添加模块互联过程中所需的IP 。在我们本次设计中只有一个 IP 模块,在左侧确认勾选 processing_system7_0 ,然后点击“ OK ”。 此时 ZYNQ7 PS 模块引出了两组外部接口,分别是 DDR 和 FIXED_IO ,引出的接口将会被分配到 ZYNQ 器件具体的引脚上。大家也可以通过点击 ZYNQ7 PS 模块接口处的加号 “+” ,来展开这两组接口,观察其中都有哪些信号。如下图所示:
四、导出到SDK
(1)本次实验不需要添加其它 IP ,直接按快捷键 Ctrl+S 保存当前设计。接下来点击下图箭头所指示的按钮,验证当前设计。验证完成后弹出对话框提示没有错误或者关键警告,点击“OK”,如下图所示:
如果验证结果报出错误或者警告,大家需要重新检查自己的设计。
(2)在 Sources 窗口中,选中 Design Sources 下的 sysetm.bd, 这就是我们刚刚完成的 Block Design 设计。 右键点击 sysetm.bd ,在弹出的菜单栏中选择“ Generate Output Products ”,如下图所示:
在对话框中 Synthesis Options 选择 Global ; Run Setings 用于设置生成过程中要使用的处理器的线程数,进行多线程处理,保持默认或设置为个人电脑处理器最大可使用线程数都可以,一般选择最大可使用线程数的一般。然后点击“Generate ”来生成设计的综合、实现和仿真文件。
在“Generate ”过程中会为设计生成所有需要的输出结果。比如 Vivado 工具会自动生成处理系统的 XDC 约束文件,因此我们不需要手动对 ZYNQ PS 引出的接口(DDR 和 FIXED_IO)进行管脚分配。
Generate 完成后,在弹出的对话框中点击“OK ”。
在 Sources 窗口中,点击“ IP Source ”标签页,可以看到 Generate 过程生成的输出结果。
(3)在“ Hierarchy ”标签页再次右键点击 system.bd ,然后选择“ Create HDL Wrapper ”。
在弹出的对话框中确认勾选“Let Vivado manage wrapper and auto-update”,然后点击“ OK ”。
(4)在菜单栏选择 File > Export > Export hardware。
在弹出的对话框中,因为没有生成 bitstream 文件,所以无需勾选“ Include bitstream ”,直接点击“ OK ” 按钮。
在上图中,因为选择了“Exort to
(5)硬件导出完成后,在菜单栏中选择 File > Launch SDK ,启动 SDK 开发环境。如下图所示:
在弹出对话框中,直接点击“OK”,到这里,我们已经完成了 ZYNQ 嵌入式系统的硬件设计部分。接下来需要到 SDK 软件中进行应用程序开发,也就是软件设计部分。
五、SDK设计
(1)SDK 打开后,主页面会显示硬件描述文件 system.hdf 的内容。如下图所示:
system.hdf 标签页显示了整个 PS 系统的地址映射信息。大家应该还记得,在启动 SDK 之前,我们将硬件以一个 ZIP 压缩文件(system_wrapper.hdf)的形式导出到软件的工作空间。在 SDK 启动时,该文件会自动解压,大家可以在图 1.4.1 的左侧看到解压后的所有文件。其中,前四个文件(ps7_init_gpl.c、ps7_init_gpl.h、ps7_init.c 和 ps7_init.h)包含了 Zynq SOC 处理系统的初始化代码,以及 DDR、时钟、pll 和 MIO 的初始化设置信息。在初始化过程中,SDK 使用这些信息去配置相应的模块,使得应用程序能够在 PS 上运行。
(2)在菜单栏选择 File > New > Application Project, 新建一个 SDK 应用工程。
(2)在弹出的图 2.4.4 所示界面中,输入工程名“ gpio_mio ”,注意 2 处的硬件平台,如果我们没有删除 system_wrapper_hw_platform_0 ,该处可能是 system_wrapper_hw_platform_0 ,所以要注意选择正确。其它选项保持默认即可,点击“Next > ”按钮。
(3) 选择工程模版 Empty Application ,然后点击“Finish”按钮。
(4)可以看到 SDK 创建了一个 gpio_mio 目录和 gpio_mio_bsp 目录。我们打开 gpio_mio_bsp 目录下的system.mss 文件,找到 ps7_gpio_0,如下图 所示:
点击 Documentation 将在浏览器窗口打开 GPIO 的 API 文档,里面有关于 GPIO 的详细信息。
点击 Import Examples ,会弹出下图所示的导入示例界面,关于 GPIO 有两个示
例,如下图所示:
xgpiops_intr_example.c 包含有关如何直接使用 XGpiops 驱动程序的示例。此示例显示了中断模式下驱动程序的用法,并使用 GPIO 的中断功能检测按钮事件,根据输入控制 LED 输出。xgpiops_polled_example.c 同样包含有关如何直接使用 XGpiops 驱动程序的示例。此示例提供了用于读取/写入各个引脚的 API 的用法。从上面的介绍中,我们因为本实验暂未使用到中断,所以应该选择 xgpiops_polled_example 示例。选择好示例后,点击“OK”按钮。
(5)在 Project Explorer 中,新增了 gpio_mio_bsp_xgpiops_polled_example_1 目录,我们打开其 src 目录下的 xgpiops_polled_example.c 文件。
xgpiops_polled_example.c 文件有四个函数,其中 GpioInputExample 函数由于我们本实验只用 MIO 输出所以未用到。该文件代码虽然是为特定开发板使用的,不过我们稍作修改也可以拿来使用。我们看到有一 LED 接到 PS 的 MIO0 ,所以当我们修改该文件第 172 行的 Output_Pin 为 0 时,保存该文件,然后编译,编译完成后下载到领航者开发板会看到核心板上的 LED2 灯闪烁。
六、IIC设计
下面为LT8619C IIC的读写测试代码
#include
#include
#include
#include "xil_types.h"
#include "xil_cache.h"
#include "xparameters.h"
//#include "xgpio.h"
#include "xaxivdma.h"
#include "xaxivdma_i.h"
//#include "display_ctrl/display_ctrl.h"
#include "vdma_api/vdma_api.h"
//#include "xv_tpg.h"
#include "xcsi2txss.h"
//#include "xcsiss.h"
#include "xgpiops.h"
#include "xtime_l.h"
//#include "xvtc.h"
//#include "xvidc.h"
//#include "xvprocss.h"
//#include "xrgb2ycrcb.h"
//#include "xiicps.h"
#include "LT8619C.h"
#include "xiicps.h"
//宏定义
#define IIC_SLAVE_ADDR 0x55
//#define IIC_SCLK_RATE 400000
#define TEST_BUFFER_SIZE 132
#define FRAME_BUFFER_NUM 3 //帧缓存个数
#define BYTES_PIXEL 3 //像素字节数,RGB888占3个字节
//#define DYNCLK_BASEADDR XPAR_AXI_DYNCLK_0_BASEADDR //动态时钟基地址
#define VDMA_ID XPAR_AXIVDMA_0_DEVICE_ID //VDMA器件ID
//#define DISP_VTC_ID XPAR_VTC_0_DEVICE_ID //VTC器件ID
//#define AXI_GPIO_0_ID XPAR_AXI_GPIO_0_DEVICE_ID //PL端 AXI GPIO 0(lcd_id)器件ID
//#define AXI_GPIO_0_CHANEL 1 //PL按键使用AXI GPIO(lcd_id)通道1
#define GPIO_DEVICE_ID XPAR_XGPIOPS_0_DEVICE_ID
#define XRGB_DEVICE_ID XPAR_RGB2YCRCB_0_DEVICE_ID
//XGpioPs InstancePtr;
//XGpioPs* XGInstancePtr = &InstancePtr;
//函数声明
//void colorbar(u8 *frame, u32 width, u32 height, u32 stride);
//全局变量
XAxiVdma vdma;
//XGpio Gpio; /* The Instance of the GPIO Driver */
//DisplayCtrl dispCtrl;
//XGpio axi_gpio_inst; //PL端 AXI GPIO 驱动实例
//VideoMode vd_mode;
//frame buffer的起始地址
unsigned int const frame_buffer_addr = (XPAR_PS7_DDR_0_S_AXI_BASEADDR+0x1000000);
unsigned int lcd_id=0; //LCD ID
XCsi2TxSs csitx_inst;
XIicPs Iic; /**< Instance of the IIC Device */
//XCsiSs csirx_inst;
int Status;
u32 volatile *gpio_hlsIpReset;
u32 volatile *gpio_videoLockMonitor;
XGpioPs_Config * XGpio_Cif;
char * FUNCTION = "[XGpiops_Init]";
XCsi2TxSs_Config *mipiTxConfigPtr;
//XCsiSs_Config *mipiRxConfigPtr;
int driverInit();
int Rgb2YCrCb_Update_Example(u16 DeviceId);
int IicPsMasterPolledExample(u16 DeviceId);
/*
* The following buffers are used in this example to send and receive data
* with the IIC.
*/
u8 SendBuffer[TEST_BUFFER_SIZE]; /**< Buffer for Transmitting Data */
u8 RecvBuffer[TEST_BUFFER_SIZE]; /**< Buffer for Receiving Data */
int main(void)
{
driverInit();
int Status=0;
XIicPs_Config *Config;
//***********************************************************************************
//mipi tx
XCsi2TxSs_ReportCoreInfo(&csitx_inst);
XCsi2TxSs_Reset(&csitx_inst);
XCsi2TxSs_SetClkMode(&csitx_inst, 1); //non-continuous clock mode
usleep(300000);
XCsi2TxSs_Activate(&csitx_inst, XCSI2TX_ENABLE);
//***********************************************************************************
//配置VDMA
run_vdma_frame_buffer(&vdma, VDMA_ID, 1280, 1024,frame_buffer_addr,0, 0,BOTH);
// usleep(300000);
//*********************************************************************************
LT8619C_intial();
//*********************************************************************************
Config = XIicPs_LookupConfig(IIC_DEVICE_ID);
if (NULL == Config) {
return XST_FAILURE;
}
Status = XIicPs_CfgInitialize(&Iic, Config, Config->BaseAddress);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Perform a self-test to ensure that the hardware was built correctly.
*/
Status = XIicPs_SelfTest(&Iic);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
Status = XIicPs_SetSClk(&Iic, IIC_SCLK_RATE);
while(1)
{
SendBuffer[0]=0x60;
SendBuffer[1]=0x00;
Status = XIicPs_MasterSendPolled(&Iic, SendBuffer,2, 0x64>>1);
Status = XIicPs_MasterRecvPolled(&Iic, RecvBuffer,1, 0x64>>1);
SendBuffer[0]=0x60;
SendBuffer[1]=0x01;
Status = XIicPs_MasterSendPolled(&Iic, SendBuffer,2, 0x64>>1);
Status = XIicPs_MasterRecvPolled(&Iic, RecvBuffer+1,1, 0x64>>1);
SendBuffer[0]=0x60;
SendBuffer[1]=0x02;
Status = XIicPs_MasterSendPolled(&Iic, SendBuffer,2, 0x64>>1);
Status = XIicPs_MasterRecvPolled(&Iic, RecvBuffer+2,1, 0x64>>1);
SendBuffer[0]=0x60;
SendBuffer[1]=0x05;
SendBuffer[2]=0x65;
Status = XIicPs_MasterSendPolled(&Iic, SendBuffer,3, 0x64>>1);
usleep(1);
Status = XIicPs_MasterSendPolled(&Iic, SendBuffer,2, 0x64>>1);
Status = XIicPs_MasterRecvPolled(&Iic, RecvBuffer+3,1, 0x64>>1);
SendBuffer[0]=0x60;
SendBuffer[1]=0x07;
SendBuffer[2]=0x84;
Status = XIicPs_MasterSendPolled(&Iic, SendBuffer,3, 0x64>>1);
usleep(1);
Status = XIicPs_MasterSendPolled(&Iic, SendBuffer,2, 0x64>>1);
Status = XIicPs_MasterRecvPolled(&Iic, RecvBuffer+4,1, 0x64>>1);
}
/*
while(1)
{
usleep(300000);
XGpioPs_WritePin(&InstancePtr,7,1);
usleep(300000);
XGpioPs_WritePin(&InstancePtr,7,0);
}
*/
return 0;
}
int driverInit()
{
int status;
//***********************************************************************************
//GPIO
XGpio_Cif = XGpioPs_LookupConfig(GPIO_DEVICE_ID);
status = XGpioPs_CfgInitialize(&InstancePtr,XGpio_Cif,XGpio_Cif->BaseAddr);
if(status != 0) {
xil_printf("%s XGpioPs_CfgInitialize error status:%d \n\r",FUNCTION,status);
return -1;
}
//set MIO 0 as output & set MIO 13 as output
XGpioPs_SetDirectionPin(&InstancePtr,7,1);
XGpioPs_SetDirectionPin(&InstancePtr,10,1);
//Enable
XGpioPs_SetOutputEnablePin(&InstancePtr,7,1);
XGpioPs_SetOutputEnablePin(&InstancePtr,10,1);
//***********************************************************************************
//mipi tx
mipiTxConfigPtr = XCsi2TxSs_LookupConfig(XPAR_CSI2TXSS_0_DEVICE_ID);
if (!mipiTxConfigPtr) {
return XST_FAILURE;
}
status=XCsi2TxSs_CfgInitialize(&csitx_inst, mipiTxConfigPtr,mipiTxConfigPtr->BaseAddr);
if (status != XST_SUCCESS) {
xil_printf("MIPI CSI TX SS config initialization failed.\n\r");
return XST_FAILURE;
}
//***********************************************************************************
//lt8619C
LT8619_Config = XIicPs_LookupConfig(IIC_DEVICE_ID);
if (NULL == LT8619_Config) {
return XST_FAILURE;
}
status = XIicPs_CfgInitialize(&Iic, LT8619_Config, LT8619_Config->BaseAddress);
if (status != XST_SUCCESS) {
return XST_FAILURE;
}
status = XIicPs_SelfTest(&Iic);
if (status != XST_SUCCESS) {
return XST_FAILURE;
}
XIicPs_SetSClk(&Iic, IIC_SCLK_RATE);
}
int IicPsMasterPolledExample(u16 DeviceId)
{
int Status;
XIicPs_Config *Config;
int Index;
/*
* Initialize the IIC driver so that it's ready to use
* Look up the configuration in the config table,
* then initialize it.
*/
Config = XIicPs_LookupConfig(DeviceId);
if (NULL == Config) {
return XST_FAILURE;
}
Status = XIicPs_CfgInitialize(&Iic, Config, Config->BaseAddress);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Perform a self-test to ensure that the hardware was built correctly.
*/
Status = XIicPs_SelfTest(&Iic);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Set the IIC serial clock rate.
*/
XIicPs_SetSClk(&Iic, IIC_SCLK_RATE);
/*
* Initialize the send buffer bytes with a pattern to send and the
* the receive buffer bytes to zero to allow the receive data to be
* verified.
*/
for (Index = 0; Index < TEST_BUFFER_SIZE; Index++) {
SendBuffer[Index] = (Index % TEST_BUFFER_SIZE);
RecvBuffer[Index] = 0;
}
/*
* Send the buffer using the IIC and ignore the number of bytes sent
* as the return value since we are using it in interrupt mode.
*/
Status = XIicPs_MasterSendPolled(&Iic, SendBuffer,
TEST_BUFFER_SIZE, IIC_SLAVE_ADDR);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Wait until bus is idle to start another transfer.
*/
while (XIicPs_BusIsBusy(&Iic)) {
/* NOP */
}
Status = XIicPs_MasterRecvPolled(&Iic, RecvBuffer,
TEST_BUFFER_SIZE, IIC_SLAVE_ADDR);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Verify received data is correct.
*/
for(Index = 0; Index < TEST_BUFFER_SIZE; Index ++) {
/* Aardvark as slave can only set 64 bytes for output */
if (RecvBuffer[Index] != Index % 64) {
return XST_FAILURE;
}
}
return XST_SUCCESS;
}
用逻辑分析仪观测信号:
SendBuffer[0]=0x60;
SendBuffer[1]=0x05;
SendBuffer[2]=0x35;
Status = XIicPs_MasterSendPolled(&Iic, SendBuffer,3, 0x64>>1);//写操作
Status = XIicPs_MasterSendPolled(&Iic, SendBuffer,2, 0x64>>1); //读操作
Status = XIicPs_MasterRecvPolled(&Iic, RecvBuffer+3,1, 0x64>>1); //读操作
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/xiaoxian666/article/details/132210869