• ZYNQ之简易流水灯(EMIO、AXI GPIO)


    目录

    一、vivado

    二、vitis

    1.LED

    2.Key

    3.定时器

    4.中断

    三、代码


    一般来说ZYNQ可以有三种方式实现流水灯:MIO,EMIO,AXI GPIO。但是由于赛灵思的ZYNQ开发板MIO资源没有LED,所以实现流水灯只能EMIO或者AXI GPIO。这里使用AXI GPIO实现流水灯,为了更多的使用板子资源,在流水灯的基础上增加了按键,中断,定时器,串口等功能可以实现流水灯的方向的切换,精准定时等功能。同时也会给出AXI GPIO和EMIO实现流水灯的代码。 

    一、vivado

    创建一个工程,添加ZYNQ IP核

    点击自动连线

     完成后双击打开,配置EMIO

    配置EMIO位宽为2

    然后添加AXI GPIO 

     点击自动连线

    左边全勾上,接口选择led

     然后点击ZYNQ核上的GPIO,刚刚才配置的,设置将引脚扩展处来,为后面PL分配引脚做准备。

     然后删除USB端口,不然后面会报错

    然后验证当前设计,出现如下弹窗,说明设计结果正确。

     在 Sources 窗口中,选中 Design Sources 下的 .bd文件生成HDL 模块

     

    然后进行分析与综合

     分配引脚为刚刚我们设置的两个EMIO

    按键原理图

     设置按键引脚和电源值

    保存引脚约束文件

    然后生成字节流,因为用到了PL部分

     将硬件导出

    启动vitis进入软件编程部分

    二、vitis

    这里工程的建立就不说了,具体的可以参考前面的

    1.LED

    主要是初始化LED和设置LED的输入输出方向

    1. int led_init(void)
    2. {
    3. int Status;
    4. //初始化GPIO
    5. Status = XGpio_Initialize(&Axi_Gpio, GPIO_DEVICE_ID);
    6. if (Status != XST_SUCCESS) //判断是否初始化成功
    7. {
    8. return XST_FAILURE;
    9. }
    10. //设置GPIO输入/输出模型 0:输出 1:输入
    11. XGpio_SetDataDirection(&Axi_Gpio, led_channel, 0x00);
    12. return XST_SUCCESS;
    13. }

    2.Key

    主要是初始化Key和设置Key的输入输出方向

    1. int key_init(void)
    2. {
    3. int Status;
    4. //查找器件的ID,查找器件的配置信息
    5. ConfigPtr = XGpioPs_LookupConfig(GPIO_DEVICE_ID);
    6. if (ConfigPtr == NULL)
    7. {
    8. return XST_FAILURE;
    9. }
    10. //初始化GPIO驱动
    11. Status = XGpioPs_CfgInitialize(&Key_Gpio, ConfigPtr,ConfigPtr->BaseAddr);
    12. if (Status != XST_SUCCESS) //判断是否初始化成功
    13. {
    14. return XST_FAILURE;
    15. }
    16. //设置输出使能(最后一个参数:0表示关闭使能,1表示打开)
    17. XGpioPs_SetOutputEnablePin(&Key_Gpio, EMIO_KEY0, 1);
    18. XGpioPs_SetOutputEnablePin(&Key_Gpio, EMIO_KEY1, 1);
    19. //把GPIO的方向设置为输入(最后一个参数:0表示输入,1表示输出)
    20. XGpioPs_SetDirectionPin(&Key_Gpio, EMIO_KEY0, 0);
    21. XGpioPs_SetDirectionPin(&Key_Gpio, EMIO_KEY1, 0);
    22. return XST_SUCCESS;
    23. }

    3.定时器

    初始化定时器并且设置定时器的周期和模式。定时器周期计算主要是要主要私有定时器的时钟频率为CPU工作频率的一半。

    1. int timer_init(void)
    2. {
    3. int Status;
    4. //私有定时器初始化
    5. XScuTimer_Config *timer_cfg_ptr;
    6. timer_cfg_ptr = XScuTimer_LookupConfig(TIMER_DEVICE_ID);
    7. if (timer_cfg_ptr == NULL)
    8. {
    9. return XST_FAILURE;
    10. }
    11. Status = XScuTimer_CfgInitialize(&Timer, timer_cfg_ptr,timer_cfg_ptr->BaseAddr);
    12. if (Status != XST_SUCCESS) //判断是否初始化成功
    13. {
    14. return XST_FAILURE;
    15. }
    16. XScuTimer_LoadTimer(&Timer, TIMER_LOAD_VALUE); // 加载计数周期
    17. XScuTimer_EnableAutoReload(&Timer); // 设置自动装载模式
    18. return XST_SUCCESS;
    19. }

    4.中断

    中断处理固定模式:

    ①初始化中断控制器

    ②初始化CPU异常功能、向CPU注册异常处理回调函数、使能异常处理功能

    ③使能中断控制器、设置中断的类型、使能对应引脚的中断

    ④设置中断的回调函数(用户自己设置)

    1. int interrupt_init()
    2. {
    3. int Status;
    4. //初始化中断控制器
    5. XScuGic_Config *gic_cfg; //中断控制器配置信息
    6. gic_cfg = XScuGic_LookupConfig(INTC_DEVICE_ID);
    7. if (gic_cfg == NULL)
    8. {
    9. return XST_FAILURE;
    10. }
    11. Status = XScuGic_CfgInitialize(&Intc,gic_cfg,gic_cfg->CpuBaseAddress);
    12. if (Status != XST_SUCCESS) //判断是否初始化成功
    13. {
    14. return XST_FAILURE;
    15. }
    16. //初始化异常处理
    17. Xil_ExceptionInit();
    18. //CPU中断异常注册
    19. Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,(Xil_ExceptionHandler)XScuGic_InterruptHandler,&Intc);
    20. //使能处理器中断
    21. Xil_ExceptionEnable();;
    22. //设置定时器中断: timer_intr_handler 中断处理函数
    23. XScuGic_Connect(&Intc, TIMER_IRPT_INTR,(Xil_ExceptionHandler)timer_intr_handler, &Timer);
    24. XScuGic_Enable(&Intc,TIMER_IRPT_INTR);//使能 GIC 中的定时器中断
    25. XScuTimer_EnableInterrupt(&Timer); //使能定时器中断
    26. return XST_SUCCESS;
    27. }

    三、代码

    EMIO代码:

    1. #include "stdio.h"
    2. #include "xparameters.h"
    3. #include "xgpiops.h"
    4. #include "sleep.h"
    5. #define GPIO_DEVICE_ID XPAR_XGPIOPS_0_DEVICE_ID
    6. //EMIO引脚从54开始算起
    7. #define EMIO_LED0 54
    8. #define EMIO_LED1 55
    9. #define EMIO_LED2 56
    10. #define EMIO_LED3 57
    11. #define EMIO_KEY0 58
    12. #define EMIO_KEY1 59
    13. int key_scan();
    14. XGpioPs_Config * ConfigPtr;
    15. XGpioPs Gpio; /* The driver instance for GPIO Device. */
    16. int main()
    17. {
    18. int key_value;
    19. //查找器件的ID,查找器件的配置信息
    20. ConfigPtr = XGpioPs_LookupConfig(GPIO_DEVICE_ID);
    21. //初始化GPIO驱动
    22. XGpioPs_CfgInitialize(&Gpio, ConfigPtr,ConfigPtr->BaseAddr);
    23. //LED:
    24. //把GPIO的方向设置为输出(最后一个参数:0表示输入,1表示输出)
    25. XGpioPs_SetDirectionPin(&Gpio, EMIO_LED0, 1);
    26. XGpioPs_SetDirectionPin(&Gpio, EMIO_LED1, 1);
    27. XGpioPs_SetDirectionPin(&Gpio, EMIO_LED2, 1);
    28. XGpioPs_SetDirectionPin(&Gpio, EMIO_LED3, 1);
    29. //设置输出使能(最后一个参数:0表示关闭使能,1表示打开)
    30. XGpioPs_SetOutputEnablePin(&Gpio, EMIO_LED0, 1);
    31. XGpioPs_SetOutputEnablePin(&Gpio, EMIO_LED1, 1);
    32. XGpioPs_SetOutputEnablePin(&Gpio, EMIO_LED2, 1);
    33. XGpioPs_SetOutputEnablePin(&Gpio, EMIO_LED3, 1);
    34. //KEY:
    35. //把GPIO的方向设置为输入(最后一个参数:0表示输入,1表示输出)
    36. XGpioPs_SetDirectionPin(&Gpio, EMIO_KEY0, 0);
    37. XGpioPs_SetDirectionPin(&Gpio, EMIO_KEY1, 0);
    38. while(1)
    39. {
    40. key_value = key_scan();
    41. if(key_value ==1)
    42. {
    43. //将按键的状态写入LED
    44. XGpioPs_WritePin(&Gpio, EMIO_LED1,1);
    45. }
    46. else if(key_value ==2)
    47. {
    48. XGpioPs_WritePin(&Gpio, EMIO_LED1,0);
    49. }
    50. }
    51. return 0;
    52. }
    53. int key_scan()
    54. {
    55. int val=0;
    56. if(XGpioPs_ReadPin(&Gpio, EMIO_KEY0) == 1)
    57. val = 1;
    58. if(XGpioPs_ReadPin(&Gpio, EMIO_KEY1) == 1)
    59. val = 2;
    60. return val;
    61. }

    AXI GPIO代码:

    1. #include "xparameters.h"
    2. #include "xgpiops.h"
    3. #include "xscugic.h"
    4. #include "xil_exception.h"
    5. #include "xplatform_info.h"
    6. #include
    7. #include "xgpio.h"
    8. #include "xscutimer.h"
    9. #include "xil_exception.h"
    10. #define GPIO_DEVICE_ID XPAR_XGPIOPS_0_DEVICE_ID //GPIO ID
    11. #define TIMER_DEVICE_ID XPAR_XSCUTIMER_0_DEVICE_ID //定时器 ID
    12. #define INTC_DEVICE_ID XPAR_SCUGIC_SINGLE_DEVICE_ID //中断控制器 ID
    13. #define TIMER_IRPT_INTR XPAR_SCUTIMER_INTR //定时器中断 ID
    14. static XScuGic Intc; //中断驱动程序实例
    15. static XScuTimer Timer; //定时器驱动程序实例
    16. #define TIMER_LOAD_VALUE 0x1EFE920 //定时器装载值 100ms中断 1EFE920
    17. //EMIO KEY
    18. static XGpioPs Key_Gpio; //gpio ps 驱动实例
    19. static XGpioPs_Config * ConfigPtr;
    20. #define EMIO_KEY0 54
    21. #define EMIO_KEY1 55
    22. //AXI GPIO
    23. #define led_channel 1 //LED灯引脚
    24. static XGpio Axi_Gpio; //GPIO设备的驱动实例
    25. static int key_val,key_down,key_up,key_old; //按键处理
    26. static int delay_cnt=0; //用于精准延时
    27. int led_init(void)
    28. {
    29. int Status;
    30. //初始化GPIO
    31. Status = XGpio_Initialize(&Axi_Gpio, GPIO_DEVICE_ID);
    32. if (Status != XST_SUCCESS) //判断是否初始化成功
    33. {
    34. return XST_FAILURE;
    35. }
    36. //设置GPIO输入/输出模型 0:输出 1:输入
    37. XGpio_SetDataDirection(&Axi_Gpio, led_channel, 0x00);
    38. return XST_SUCCESS;
    39. }
    40. int key_init(void)
    41. {
    42. int Status;
    43. //查找器件的ID,查找器件的配置信息
    44. ConfigPtr = XGpioPs_LookupConfig(GPIO_DEVICE_ID);
    45. if (ConfigPtr == NULL)
    46. {
    47. return XST_FAILURE;
    48. }
    49. //初始化GPIO驱动
    50. Status = XGpioPs_CfgInitialize(&Key_Gpio, ConfigPtr,ConfigPtr->BaseAddr);
    51. if (Status != XST_SUCCESS) //判断是否初始化成功
    52. {
    53. return XST_FAILURE;
    54. }
    55. //设置输出使能(最后一个参数:0表示关闭使能,1表示打开)
    56. XGpioPs_SetOutputEnablePin(&Key_Gpio, EMIO_KEY0, 1);
    57. XGpioPs_SetOutputEnablePin(&Key_Gpio, EMIO_KEY1, 1);
    58. //把GPIO的方向设置为输入(最后一个参数:0表示输入,1表示输出)
    59. XGpioPs_SetDirectionPin(&Key_Gpio, EMIO_KEY0, 0);
    60. XGpioPs_SetDirectionPin(&Key_Gpio, EMIO_KEY1, 0);
    61. return XST_SUCCESS;
    62. }
    63. int key_scan()
    64. {
    65. int val=0;
    66. if(XGpioPs_ReadPin(&Key_Gpio, EMIO_KEY0) == 1)
    67. val = 1;
    68. if(XGpioPs_ReadPin(&Key_Gpio, EMIO_KEY1) == 1)
    69. val = 2;
    70. return val;
    71. }
    72. //中断处理函数 100ms
    73. void timer_intr_handler(void *CallBackRef)
    74. {
    75. XScuTimer *timer_ptr = (XScuTimer *) CallBackRef;
    76. delay_cnt += 1;
    77. //处理按键
    78. key_val = key_scan();
    79. key_down = key_val & (key_old^key_val);
    80. key_up = ~key_val & (key_old^key_val);
    81. key_old = key_val;
    82. //清除定时器中断标志
    83. XScuTimer_ClearInterruptStatus(timer_ptr);
    84. }
    85. int interrupt_init()
    86. {
    87. int Status;
    88. //初始化中断控制器
    89. XScuGic_Config *gic_cfg; //中断控制器配置信息
    90. gic_cfg = XScuGic_LookupConfig(INTC_DEVICE_ID);
    91. if (gic_cfg == NULL)
    92. {
    93. return XST_FAILURE;
    94. }
    95. Status = XScuGic_CfgInitialize(&Intc,gic_cfg,gic_cfg->CpuBaseAddress);
    96. if (Status != XST_SUCCESS) //判断是否初始化成功
    97. {
    98. return XST_FAILURE;
    99. }
    100. //初始化异常处理
    101. Xil_ExceptionInit();
    102. //CPU中断异常注册
    103. Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,(Xil_ExceptionHandler)XScuGic_InterruptHandler,&Intc);
    104. //使能处理器中断
    105. Xil_ExceptionEnable();;
    106. //设置定时器中断: timer_intr_handler 中断处理函数
    107. XScuGic_Connect(&Intc, TIMER_IRPT_INTR,(Xil_ExceptionHandler)timer_intr_handler, &Timer);
    108. XScuGic_Enable(&Intc,TIMER_IRPT_INTR);//使能 GIC 中的定时器中断
    109. XScuTimer_EnableInterrupt(&Timer); //使能定时器中断
    110. return XST_SUCCESS;
    111. }
    112. int timer_init(void)
    113. {
    114. int Status;
    115. //私有定时器初始化
    116. XScuTimer_Config *timer_cfg_ptr;
    117. timer_cfg_ptr = XScuTimer_LookupConfig(TIMER_DEVICE_ID);
    118. if (timer_cfg_ptr == NULL)
    119. {
    120. return XST_FAILURE;
    121. }
    122. Status = XScuTimer_CfgInitialize(&Timer, timer_cfg_ptr,timer_cfg_ptr->BaseAddr);
    123. if (Status != XST_SUCCESS) //判断是否初始化成功
    124. {
    125. return XST_FAILURE;
    126. }
    127. XScuTimer_LoadTimer(&Timer, TIMER_LOAD_VALUE); // 加载计数周期
    128. XScuTimer_EnableAutoReload(&Timer); // 设置自动装载模式
    129. return XST_SUCCESS;
    130. }
    131. int main(void)
    132. {
    133. xil_printf("My test!\r\n");
    134. //led初始化
    135. int Status,key;
    136. int lval = 0x1,rval = 0x1;
    137. Status = led_init();
    138. if (Status != XST_SUCCESS)
    139. {
    140. xil_printf("LEDs init failed!\r\n");
    141. }
    142. //key初始化
    143. Status = key_init();
    144. if (Status != XST_SUCCESS)
    145. {
    146. xil_printf("Key init failed!\r\n");
    147. }
    148. //定时器初始化
    149. Status = timer_init();
    150. if (Status != XST_SUCCESS)
    151. {
    152. xil_printf("timer init failed!\r\n");
    153. }
    154. //中断初始化
    155. Status = interrupt_init(); //一定要先定时器初始化后再中断初始化
    156. if (Status != XST_SUCCESS)
    157. {
    158. xil_printf("interrupt init failed!\r\n");
    159. }
    160. XScuTimer_Start(&Timer); //启动定时器
    161. while(1)
    162. {
    163. if(key_down ==1) //右移
    164. {
    165. key = 1;
    166. }
    167. else if(key_down ==2)
    168. {
    169. key = 2;
    170. }
    171. if(key == 1)
    172. {
    173. if(delay_cnt >= 10) //1s
    174. {
    175. //将按键的状态写入LED
    176. XGpio_DiscreteWrite(&Axi_Gpio, led_channel, rval);
    177. rval = rval >>1;
    178. if(rval < 0x1)
    179. {
    180. rval = 0x8;
    181. }
    182. delay_cnt = 0;
    183. }
    184. }
    185. else if(key == 2)
    186. {
    187. if(delay_cnt >= 10)
    188. {
    189. //将按键的状态写入LED
    190. XGpio_DiscreteWrite(&Axi_Gpio, led_channel, lval);
    191. lval = lval <<1;
    192. if(lval > 0x8)
    193. {
    194. lval = 0x1;
    195. }
    196. delay_cnt = 0;
    197. }
    198. }
    199. }
    200. return 0;
    201. }

  • 相关阅读:
    c代码库(残篇)持续更新
    java毕业设计希望酒店信息管理系统mybatis+源码+调试部署+系统+数据库+lw
    java-net-php-python-ssm动漫论坛系统查重PPT计算机毕业设计程序
    SQL手工注入漏洞测试(Sql Server数据库)
    GIS数据漫谈(六)— 投影坐标系统
    【Unity开发实战】—— 2D项目1 - Ruby‘s Adventure 游戏世界中各个对象的交互(3-1)
    计算机毕业设计Python+Django的闲置物品交易系统+二手商城网站(源码+系统+mysql数据库+Lw文档)
    人工智能学习之机器人路径规划优化
    .NET应用系统的国际化-多语言词条服务
    上海亚商投顾: 市场调整分化 两市成交额再创阶段新低
  • 原文地址:https://blog.csdn.net/qq_53144843/article/details/126804953