TA的每日心情 | 开心 2020-7-25 10:37 |
---|
签到天数: 40 天 连续签到: 1 天 [LV.5]常住居民I
|
本帖最后由 武器哈12 于 2019-11-24 15:10 编辑
一起来看看实验结果:
定时器在嵌入式中非常常用,学习定时器是歇息任何一款芯片或者开发板的必经之路。
在 ZYNQ 嵌入式系统中,定时器的资源是非常丰富的,每个 Cortex-A9 处理器都有各自独立的 32 位私有定时器和 32 位看门狗定时器,这两个 CPU 同时共享一个 64 位的全局定时器(GT)。下图是ZYNQ定时器的系统框图:
从图中可以看出PS中具有看门狗定时器(SWDT)和两个 TTC(Triple Timer Counters)以及私有定时器(CPU Private Timer)。其中私有定时器较为常用,这次实验使用私有定时器来产生中断500ms,控制EMIO连接的LED闪烁,并同时控制串口输出消息。
私有定时器的时钟频率为 CPU 时钟频率的一半,可以在ZYNQ IP核定制的时候设置,一般ARM 的工作时钟频率为 666.666Mhz,则私有定时器的时钟频率为 333.333Mhz。私有定时器的特性如下:
1、32 位计数器,当计数器递减至 0 后产生中断;
2、8 位预分频计数器,可以更好的控制中断周期;
3、可以配置单次定时或者自动重载模式;
4、通过配置起始计数值来设置定时时间。
我们在helloword工程的基础上建立工程,因为这个工程包含了最基本的ZYNQ IP核定制,再此基础上修改可以少走弯路,节省大家的开发时间。
在ZYNQ IP定制中修改如下,增加一个EMIO口即可:
修改好后原理图中多出一个关键,如上边右图所示。
添加管脚约束如下:
- set_property PACKAGE_PIN U13 [get_ports {mygpio_tri_io[0]}]
- set_property IOSTANDARD LVCMOS33 [get_ports {mygpio_tri_io[0]}]
编译综合,生成bit文件。打开SDK,编写软件代码如下:
- #include "xparameters.h"
- #include "xscutimer.h"
- #include "xscugic.h"
- #include "xgpiops.h"
- #include "xil_exception.h"
- #include "xil_printf.h"
- #define TIMER_DEVICE_ID XPAR_XSCUTIMER_0_DEVICE_ID //定时器ID
- #define INTC_DEVICE_ID XPAR_SCUGIC_SINGLE_DEVICE_ID //中断ID
- #define TIMER_IRPT_INTR XPAR_SCUTIMER_INTR //定时器中断ID
- #define GPIO_DEVICE_ID XPAR_XGPIOPS_0_DEVICE_ID //宏定义 GPIO_PS ID
- #define MIO_LED 54 //led连接到 MIO0
- //私有定时器的时钟频率 = CPU时钟频率/2 = 333MHz
- //0.5s闪烁一次,0.5*1000_000_000/(1000/333) - 1 = 166499999
- #define TIMER_LOAD_VALUE 166499999 //定时器装载值
- XScuGic Intc; //中断控制器驱动程序实例
- XScuTimer Timer; //定时器驱动程序实例
- XGpioPs Gpio; //GPIO设备的驱动程序实例
- //MIO引脚初始化
- int mio_init(XGpioPs *mio_ptr)
- {
- int status;
- XGpioPs_Config *mio_cfg_ptr;
- mio_cfg_ptr = XGpioPs_LookupConfig(GPIO_DEVICE_ID);
- status = XGpioPs_CfgInitialize(mio_ptr, mio_cfg_ptr,mio_cfg_ptr->BaseAddr);
- XGpioPs_SetDirectionPin(&Gpio, MIO_LED, 1);//设置指定引脚的方向: 0 输入, 1 输出
- XGpioPs_SetOutputEnablePin(&Gpio, MIO_LED, 1);//使能指定引脚输出: 0 禁止输出使能, 1 使能输出
- return XST_SUCCESS;
- }
- //定时器初始化程序
- int timer_init(XScuTimer *timer_ptr)
- {
- int status;
- //私有定时器初始化
- XScuTimer_Config *timer_cfg_ptr;
- timer_cfg_ptr = XScuTimer_LookupConfig(TIMER_DEVICE_ID);
- if (NULL == timer_cfg_ptr)
- return XST_FAILURE;
- status = XScuTimer_CfgInitialize(timer_ptr, timer_cfg_ptr,timer_cfg_ptr->BaseAddr);
- if (status != XST_SUCCESS)
- return XST_FAILURE;
- XScuTimer_LoadTimer(timer_ptr, TIMER_LOAD_VALUE); // 加载计数周期
- XScuTimer_EnableAutoReload(timer_ptr); // 设置自动装载模式
- return XST_SUCCESS;
- }
- //定时器中断处理程序
- void timer_intr_handler(void *CallBackRef)
- {
- //LED状态,用于控制LED灯状态翻转
- static int led_state = 0;
- static int times = 1;
- XScuTimer *timer_ptr = (XScuTimer *) CallBackRef;
- if(led_state == 0)
- led_state = 1;
- else
- led_state = 0;
- XGpioPs_WritePin(&Gpio, MIO_LED,led_state); //向指定引脚写入数据: 0 或 1
- xil_printf("米尔科技 定时器中断测试 timer:%d \r\n",times++);
- XScuTimer_ClearInterruptStatus(timer_ptr); //清除定时器中断标志
- }
- //定时器中断初始化
- void timer_intr_init(XScuGic *intc_ptr,XScuTimer *timer_ptr)
- {
- //初始化中断控制器
- XScuGic_Config *intc_cfg_ptr;
- intc_cfg_ptr = XScuGic_LookupConfig(INTC_DEVICE_ID);
- XScuGic_CfgInitialize(intc_ptr, intc_cfg_ptr,
- intc_cfg_ptr->CpuBaseAddress);
- //设置并打开中断异常处理功能
- Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,
- (Xil_ExceptionHandler)XScuGic_InterruptHandler, intc_ptr);
- Xil_ExceptionEnable();
- //设置定时器中断
- XScuGic_Connect(intc_ptr, TIMER_IRPT_INTR,
- (Xil_ExceptionHandler)timer_intr_handler, (void *)timer_ptr);
- XScuGic_Enable(intc_ptr, TIMER_IRPT_INTR); //使能GIC中的定时器中断
- XScuTimer_EnableInterrupt(timer_ptr); //使能定时器中断
- }
- int main()
- {
- int status;
- xil_printf("SCU Timer Interrupt Test \r\n");
- mio_init(&Gpio); //MIO引脚初始化
- status = timer_init(&Timer); //定时器初始化
- if (status != XST_SUCCESS) {
- xil_printf("Timer Initial Failed\r\n");
- return XST_FAILURE;
- }
- timer_intr_init(&Intc,&Timer); //定时器中断初始化
- XScuTimer_Start(&Timer); //启动定时器
- while(1);
- return 0;
- }
附上我的工程:
MYiRtest1.zip
(4.16 MB, 下载次数: 5, 售价: 1 与非币)
|
|