[X]关闭

[米联客-XILINX-H3_CZ08_7100] FPGA_SDK入门篇连载-09 PS TTC定时器实验

文档创建者:FPGA课程
浏览次数:168
最后更新:2024-09-25
文档课程分类-AMD-ZYNQ
AMD-ZYNQ: ZYNQ-SOC » 1_SDK应用方案(仅旗舰型号) » 1-SDK基础入门方案
本帖最后由 FPGA课程 于 2024-9-25 17:30 编辑

​ 软件版本:VIVADO2021.1
操作系统:WIN10 64bit
硬件平台:适用 XILINX A7/K7/Z7/ZU/KU 系列 FPGA
实验平台:米联客-MLK-H3-CZ08-7100开发板
板卡获取平台:https://milianke.tmall.com/
登录“米联客”FPGA社区 http://www.uisrc.com 视频课程、答疑解惑!



1概述
ZYNQ有2个TTC定时器,每个TTC具有3个定时计数器,每个定时器都支持中断。TTC可以用于定时,也可以用于产生PWM。
实验目的:
1:了解ZYNQ TTC定时器的功能
2:了解TTC定时器的寄存器
3:使用SDK自带代码测试TTC定时器的定时中断、以及PWM输出。
2系统框图
如下系统框图所示,每个TTC具有3个定时计数器模块,每个模块都有自己的预分频器、16bit计数器、事件定时器、中断模块单元。支持的中断类型包括:计数间隔中断、计数匹配中断、计数溢出中断、事件定时器溢出中断。 每种类型都可以单独启用。
以TTC0为例,其全局中断GIC中断号分别为:#42 #43 #44。
TTC的工作模式可以分为一下两种:
间隔模式:计数器在 0 和间隔寄存器的值之间连续递增或递减,计数方向由计数器控制寄存器的 DEC 位决定。当计数器过零时产生一个间隔中断。当计数器值等于匹配寄存器之一时,会产生相应的匹配中断。
溢出模式:计数器在 0 到 0xFFFF 之间连续递增或递减,计数方向由计数器控制寄存器的 DEC 位决定。当计数器过零时产生溢出中断。当计数器值等于匹配寄存器之一时,会产生相应的匹配中断。

当TTC工作于事件模式,事件定时器通过内部的16bit定时计数器(该计数器的时钟就是CPU的系统时钟,并且用户不可见)计数。

5a5a8d97d7624225b03b88b0736f79bb.jpg
3TTC定时器的寄存器
TTC0的基地址为0xF8001000,TTC1的基地址为0xF8002000,每个TTC都有3个定时计数器,这里以TTC0的定时计数器1的寄存器作为说明。以下寄存器命名方法以软件方法命名,比如MACH0寄存器代表了硬件中的MACH1(因为硬件上不存在0的概念,而程序中第一个通常以0开始表示)

CLOCK_CONTROL寄存器XTTCPS_CLK_CNTRL_OFFSET (0x00U)
                        
Field Name
                        
                        
Bits
                        
                        
Type
                        
                        
Reset Value
                        
                        
Description
                        
                        
CLOCK_CONTROL
                        
                        
6:0
                        
                        
RW
                        
                        
0x0
                        
                        
6bit:
                        
设置外部输入时钟的计数边沿,默认是上升沿,当设置1采用下降沿。
                        
5bit:
                        
时钟源选择,默认是pclk,当设置1选择外部时钟ext_clk
                        
4~1bit:
                        
预分频,分频系数= 2^(N+1)
                        
0bits:
                        
预分频使能,设置1使能预分频
                        

CNT_CNTRL寄存器XTTCPS_CLK_CNTRL_OFFSET (0x0CU)
                        
Field Name
                        
                        
Bits
                        
                        
Type
                        
                        
Reset Value
                        
                        
Description
                        
                        
CNT_CNTRL
                        
                        
6:0
                        
                        
RW
                        
                        
0x0
                        
                        
6bit:
                        
波形极性:该位为高电平时,Match中断时波形输出由高电平变为低电平,溢出或间隔中断时返回高电平; 当低电平时,波形在 Match中断时从低电平变为高电平,并在溢出或间隔中断时返回低电平。
                        
5bit:
                        
输出波形使能,低电平有效。
                        
4bit:
                        
将该位设置为高电平会重置计数器值并重新开始计数; RST 位在重启时自动清除。
                        
3bit:
                        
寄存器匹配模式:当设置匹配时,当计数值与三个匹配寄存器之一匹配时产生中断,并且中断状态寄存器中的相应位被设置。
                        
2bit:
                        
当该位为高时,计数器递减计数。
                        
1bit:
                        
该位为高时,定时器处于间隔模式,计数器定期产生中断; 低电平时,定时器处于溢出模式。
                        
0bit:
                        
禁用计数器:当该位为高时,计数器停止,保持其最后一个值,直到复位、重新启动或再次启用。
                        

COUNT_VALUE寄存器XTTCPS_COUNT_VALUE_OFFSET (0x18U)
                        
Field Name
                        
                        
Bits
                        
                        
Type
                        
                        
Reset Value
                        
                        
Description
                        
                        
COUNT_VALUE
                        
                        
15:0
                        
                        
RO
                        
                        
0x0
                        
                        
当前计数器的值
                        

INTERVAL_VAL寄存器XTTCPS_INTERVAL_VAL_OFFSET (0x24U)
                        
Field Name
                        
                        
Bits
                        
                        
Type
                        
                        
Reset Value
                        
                        
Description
                        
                        
INTERVAL_VAL
                        
                        
15:0
                        
                        
RW
                        
                        
0x0
                        
                        
计数器,递增计数的最大值,或者递减计数的起始值
                        

MATCH_0寄存器XTTCPS_MATCH_0_OFFSET (0x30U)
                        
Field Name
                        
                        
Bits
                        
                        
Type
                        
                        
Reset Value
                        
                        
Description
                        
                        
MATCH_0
                        
                        
15:0
                        
                        
RW
                        
                        
0x0
                        
                        
比较匹配寄存器0,当计数器的值和比较匹配寄存器的值相等的时候,并且使能了比较匹配模式,就会产生比较匹配中断。每个计数器有3个比较匹配寄存器。
                        

MATCH_1寄存器XTTCPS_MATCH_1_OFFSET (0x34U)
                        
Field Name
                        
                        
Bits
                        
                        
Type
                        
                        
Reset Value
                        
                        
Description
                        
                        
MATCH_1
                        
                        
15:0
                        
                        
RW
                        
                        
0x0
                        
                        
比较匹配寄存器1,当计数器的值和比较匹配寄存器的值相等的时候,并且使能了比较匹配模式,就会产生比较匹配中断。每个计数器有3个比较匹配寄存器。
                        

MATCH_2寄存器XTTCPS_MATCH_2_OFFSET (0x38U)
                        
Field Name
                        
                        
Bits
                        
                        
Type
                        
                        
Reset Value
                        
                        
Description
                        
                        
MATCH_2
                        
                        
15:0
                        
                        
RW
                        
                        
0x0
                        
                        
比较匹配寄存器2,当计数器的值和比较匹配寄存器的值相等的时候,并且使能了比较匹配模式,就会产生比较匹配中断。每个计数器有3个比较匹配寄存器。
                        

ISR寄存器XTTCPS_ISR_OFFSET (0x54U)
                        
Field Name
                        
                        
Bits
                        
                        
Type
                        
                        
Reset Value
                        
                        
Description
                        
                        
ISR
                        
                        
5:0
                        
                        
clronrd
                        
                        
0x0
                        
                        
5bit:
                        
事件定时器溢出中断。
                        
4bit:
                        
计数器溢出中断。
                        
3bit:
                        
MACH 2寄存器比较匹配中断。
                        
2bit:
                        
MACH 1寄存器比较匹配中断。
                        
1bit:
                        
MACH 0寄存器比较匹配中断。
                        
0bit:
                        
    间隔中断
                        

IER寄存器XTTCPS_IER_OFFSET (0x60U)
                        
Field Name
                        
                        
Bits
                        
                        
Type
                        
                        
Reset Value
                        
                        
Description
                        
                        
IEN
                        
                        
5:0
                        
                        
RW
                        
                        
0x0
                        
                        
中断使能寄存器对应于ISR寄存器的中断位
                        

Event_Control_Timer_0寄存器XTTCPS_ Event_Control_Timer_0_VALUE_OFFSET (0x6CU)
                        
Field Name
                        
                        
Bits
                        
                        
Type
                        
                        
Reset Value
                        
                        
Description
                        
                        
Event_Control_Timer_0
                        
                        
2:0
                        
                        
RW
                        
                        
0x0
                        
                        
2bit:E_OV
                        
当该位为低时,事件定时器被禁用并在事件定时器寄存器溢出发生时设置为零;当设置为高时,溢出后定时器继续计数。
                        
1bit:E_Lo
                        
当该位为高时,以pclk计数ext_clk 的低电平持续时间; 低电平时,以pclk计数ext_clk 的高电平持续时间。
                        
0bit:E_En
                        
使能定时器,当该位设置1,事件定时器使能。
                        

Event_Register_0寄存器XTTCPS_IER_OFFSET (0x60U)
                        
Field Name
                        
                        
Bits
                        
                        
Type
                        
                        
Reset Value
                        
                        
Description
                        
                        
Event_Register_0
                        
                        
15:0
                        
                        
RO
                        
                        
0x0
                        
                        
以pclk计数的ext_clk高电平或者低电平的时间。
                        


4搭建SOC系统工程
详细的搭建过程这里不再重复,对于初学读者如果还不清楚如何创建SOC工程的,请学习“01Vitis Soc开发入门”这篇文章。
4.1SOC系统工程
bc3a6b0cc4a34307abedd30e239505ae.jpg
以上设计中,在ZYNQ IP中是设置了TTC0,并且增加了ILA IP用来观察波形
ZYNQ IP中设置TTC0
b79b4d9374974b358161ed141ec86537.jpg
设置TTC0使用外部50M时钟

c8c07d9fbc284f54b679116021675af3.jpg
由于产生的PWM周期短,所以把采样深度多设置一些,并且使用前面的1M时钟作为Capture 信号
dfb5768272cf472189fba9894785a2b6.jpg
演示程序只输出1路PWM但是依然用ILA检测多少有的PWM输出
ae5427cf7de5461cb3694781dbbd0eee.jpg
4.2编译并导出平台文件
以下步骤简写,有不清楚的看第一篇文章。
1:单击Block文件à右键àGenerate the Output ProductsàGlobalàGenerate。
2:单击Block文件à右键à Create a HDL wrapper(生成HDL顶层文件)àLet vivado manager wrapper and auto-update(自动更新)。
3:添加配套工程路径下uisrc/04_pin/fpga_pin.xdc约束文件
4:生成Bit文件。
5:导出到硬件: FileàExport HardwareàInclude bitstream
6:导出完成后,对应工程路径的soc_hw路径下有硬件平台文件:system_wrapper.xsa的文件。根据硬件平台文件system_wrapper.xsa来创建需要Platform平台。
726da567bad44be5861498fc46b43db9.jpg
5 搭建Vitis-sdk工程
创建soc_base sdk platform和APP工程的过程不再重复,如果不清楚请参考本章节第一个demo。
5.1创建SDK Platform工程
57cee77cb6d1495e939e70ee2c6eefc6.jpg

右击soc_base编译,编译的时间可能会有点长
5.2创建APP工程
本实验使用SDK自带的测试程序测试,并且对测试程序稍作修改。
4c3ea3a1f1ff431abd71f594f0d4b1aa.jpg
6程序分析
4b1c1e77cb8f42799e330088aee71d97.jpg
先看下上面的程序流程图,程序中使用了TTC0的Timer0和Timer1,其中Timer1工作于定时间隔模式,每1000HZ中断一次。Timer0工作于定时间隔和PWM波形模式,每2000hz中断 一次。Timer0每经过500次中断也就是0.5秒更新一次Timer0的比较匹配值。Timer0的PWM周期是2000HZ因此,每间隔0.5ms,Timer0中断一次,并且在中断中更新比较匹配寄存器。
1:TmrInterruptExample函数
  1. static int TmrInterruptExample(void)
  2. {
  3.         int Status;
  4.         Status = SetupInterruptSystem(INTC_DEVICE_ID, &InterruptController); //设置系统中断
  5.         if (Status != XST_SUCCESS) {
  6.                 return XST_FAILURE;
  7.         }
  8.         Status = SetupTicker();//设置TTC0的Timer1中断
  9.         if (Status != XST_SUCCESS) {
  10.                 return Status;
  11.         }

  12.         Status = SetupPWM();//设置TTC0的Timer0中断
  13.         if (Status != XST_SUCCESS) {
  14.                 return Status;
  15.         }
  16.         Status = WaitForDutyCycleFull();//设置TTC0的Timer1比较匹配值更新
  17.         if (Status != XST_SUCCESS) {
  18.                 return Status;
  19.         }
  20.         /*
  21.          * 由于修改了程序,以下代码不会执行,如果不修改代码以下代码停止定时器工作
  22.          */
  23.         XTtcPs_Stop(&(TtcPsInst[TTC_TICK_DEVICE_ID]));
  24.         XTtcPs_Stop(&(TtcPsInst[TTC_PWM_DEVICE_ID]));
  25.         return XST_SUCCESS;
  26. }
复制代码

2:SetupTicker函数
TTC0的Timer1通过该函数设置定时器的工作模式,时间间隔寄存器参数、中断回调函数等
  1. int SetupTicker(void)
  2. {
  3.         int Status;
  4.         TmrCntrSetup *TimerSetup;
  5.         XTtcPs *TtcPsTick;
  6. /* SettingsTable 参数中定义了定时中断频率、定时间隔寄存器的值、预分频参数、定时器工作模式*/
  7.         TimerSetup = &(SettingsTable[TTC_TICK_DEVICE_ID]);

  8.         /*设置定时器工作于间隔模式、不启用波形输出模式*/
  9.         TimerSetup->Options |= (XTTCPS_OPTION_INTERVAL_MODE |XTTCPS_OPTION_WAVE_DISABLE);

  10.         Status = SetupTimer(TTC_TICK_DEVICE_ID); //设置定时器参数,这个函数下面再看
  11.         if(Status != XST_SUCCESS) {
  12.                 return Status;
  13.         }

  14.         TtcPsTick = &(TtcPsInst[TTC_TICK_DEVICE_ID]); //指针重新指向

  15.         /*
  16.          * 设置定时器中断接入系统中断
  17.          */
  18.         Status = XScuGic_Connect(&InterruptController, TTC_TICK_INTR_ID,
  19.                 (Xil_ExceptionHandler)XTtcPs_InterruptHandler, (void *)TtcPsTick);
  20.         if (Status != XST_SUCCESS) {
  21.                 return XST_FAILURE;
  22.         }

  23.         /*
  24.          * 设置定时器全局中断指向的回调函数
  25.          */
  26.         XTtcPs_SetStatusHandler(&(TtcPsInst[TTC_TICK_DEVICE_ID]), &(TtcPsInst[TTC_TICK_DEVICE_ID]),
  27.                               (XTtcPs_StatusHandler)TickHandler);
  28.         /*
  29.          *使能定时器
  30.          */
  31.         XScuGic_Enable(&InterruptController, TTC_TICK_INTR_ID);
  32.         /*
  33.          * 使能定时器间隔中断
  34.          */
  35.         XTtcPs_EnableInterrupts(TtcPsTick, XTTCPS_IXR_INTERVAL_MASK);
  36.         /*
  37.          * 启动定时器
  38.          */
  39.         XTtcPs_Start(TtcPsTick);

  40.         return Status;
  41. }
复制代码

3:SetupPWM函数
TTC0的Timer0工作于定时中断和PWM波形输出模式
  1. int SetupPWM(void)
  2. {
  3.         int Status;
  4.         TmrCntrSetup *TimerSetup;
  5.         XTtcPs *TtcPsPWM;

  6.         TimerSetup = &(SettingsTable[TTC_PWM_DEVICE_ID]);

  7.         /*
  8.          * 定时间隔模式以及比较匹配波形输出模式
  9.          */
  10.         TimerSetup->Options |= (XTTCPS_OPTION_INTERVAL_MODE | XTTCPS_OPTION_MATCH_MODE);

  11.         Status = SetupTimer(TTC_PWM_DEVICE_ID); //设置定时器参数,这个函数下面再看
  12.         if(Status != XST_SUCCESS) {
  13.                 return Status;
  14.         }

  15.         TtcPsPWM = &(TtcPsInst[TTC_PWM_DEVICE_ID]); //指针重新指向

  16.         /*
  17.          * 设置定时器中断接入系统中断
  18.          */
  19.         Status = XScuGic_Connect(&InterruptController, TTC_PWM_INTR_ID,
  20.                 (Xil_ExceptionHandler)XTtcPs_InterruptHandler, (void *)TtcPsPWM);
  21.         if (Status != XST_SUCCESS) {
  22.                 return XST_FAILURE;
  23.         }

  24.         /*
  25.          * 设置定时器全局中断指向的回调函数
  26.          */
  27.         XTtcPs_SetStatusHandler(&(TtcPsInst[TTC_PWM_DEVICE_ID]), &(TtcPsInst[TTC_PWM_DEVICE_ID]),
  28.                               (XTtcPs_StatusHandler) PWMHandler);
  29.         /*
  30.          * Enable the interrupt for the Timer counter
  31.          */
  32.         XScuGic_Enable(&InterruptController, TTC_PWM_INTR_ID);

  33.         /*
  34.          *使能定时器间隔中断
  35.          */
  36.         XTtcPs_EnableInterrupts(TtcPsPWM, XTTCPS_IXR_INTERVAL_MASK);

  37.         /*
  38.          * 启动定时器
  39.          */
  40.         XTtcPs_Start(TtcPsPWM);

  41.         return Status;
  42. }
复制代码

4:SetupTimer函数
该函数设置定时器工作模式,计算合理的预分频参数以及时间间隔参数,至于具体的寄存器设置读者可以继续追踪分析,我们这里不再详细分析。
  1. int SetupTimer(int DeviceID)
  2. {
  3.         int Status;
  4.         XTtcPs_Config *Config;
  5.         XTtcPs *Timer;
  6.         TmrCntrSetup *TimerSetup;

  7.         TimerSetup = &SettingsTable[DeviceID];
  8.         Timer = &(TtcPsInst[DeviceID]);
  9.         /*
  10.          * 通过查表方式获取参数信息,这是SDK的通用方式
  11.          */
  12.         Config = XTtcPs_LookupConfig(DeviceID);
  13.         if (NULL == Config) {
  14.                 return XST_FAILURE;
  15.         }

  16.         /*
  17.          * 利用参数信息配置定时器的指针,这是SDK的通用方式
  18.          */
  19.         Status = XTtcPs_CfgInitialize(Timer, Config, Config->BaseAddress);
  20.         if (Status != XST_SUCCESS) {
  21.                 return XST_FAILURE;
  22.         }

  23.         /*
  24.          * 设置定时器工作模式
  25.          */
  26.         XTtcPs_SetOptions(Timer, TimerSetup->Options);

  27.         /*
  28.          * 以下函数计算定时器的间隔时间,以及预分频参数
  29.          */
  30.         XTtcPs_CalcIntervalFromFreq(Timer, TimerSetup->OutputHz,
  31.                 &(TimerSetup->Interval), &(TimerSetup->Prescaler));

  32.         /*
  33.          * 设置间隔寄存器以及预分频参数
  34.          */
  35.         XTtcPs_SetInterval(Timer, TimerSetup->Interval);
  36.         XTtcPs_SetPrescaler(Timer, TimerSetup->Prescaler);

  37.         return XST_SUCCESS;
  38. }
复制代码

5:WaitForDutyCycleFull函数
该函数中通过TTC0的Timer1每中断500次(0.5S)更新一次比较匹配值,TTC0的Timer0会在下次中断中更新最新的比较匹配寄存器的值。
  1. int WaitForDutyCycleFull(void)
  2. {
  3.         TmrCntrSetup *TimerSetup;
  4.         u8 DutyCycle;                /* The current output duty cycle */
  5.         XTtcPs *TtcPs_PWM;        /* Pointer to the instance structure */

  6.         TimerSetup = &(SettingsTable[TTC_PWM_DEVICE_ID]);
  7.         TtcPs_PWM = &(TtcPsInst[TTC_PWM_DEVICE_ID]);

  8.         /*
  9.          * Initialize some variables used by the interrupts and in loops.
  10.          */
  11.         DutyCycle = PWM_DELTA_DUTY;
  12.         PWM_UpdateFlag = TRUE;
  13.         ErrorCount = 0;

  14.         /*
  15.          * Loop until 100% duty cycle in the PWM output.
  16.          */
  17.         while (1) {

  18.                 /*
  19.                  * If error occurs, disable interrupts, and exit.
  20.                  */
  21.                 if (0 != ErrorCount) {
  22.                         return XST_FAILURE;
  23.                 }

  24.                 if (PWM_UpdateFlag) {//每次TTC0的Timer1中断500次设置PWM_UpdateFlag=TURE

  25.                         MatchValue = (TimerSetup->Interval * DutyCycle) / 100; //更新比较匹配值
  26.                         DutyCycle += PWM_DELTA_DUTY; //计算下次需要更新的值

  27.                         if(DutyCycle>100) //
  28.                                 DutyCycle = 0;
  29.                         /*
  30.                          * 使能中断
  31.                          */
  32.                         XTtcPs_EnableInterrupts(TtcPs_PWM,
  33.                                                  XTTCPS_IXR_INTERVAL_MASK);

  34.                         PWM_UpdateFlag = FALSE;

  35.                 }
  36.         }
复制代码

6:TickHandler函数
TTC0的timer1每1S中断1000次,每5000次(0.5S)设置PWM_UpdateFlag = TRUE。
  1. static void TickHandler(void *CallBackRef, u32 StatusEvent)
  2. {
  3.         if (0 != (XTTCPS_IXR_INTERVAL_MASK & StatusEvent)) {
  4.                 TickCount++;

  5.                 if (TICKS_PER_CHANGE_PERIOD == TickCount) {
  6.                         TickCount = 0;
  7.                         PWM_UpdateFlag = TRUE;
  8.                 }
  9.         }
  10.         else {
  11.                 ErrorCount++;
  12.         }
  13. }
复制代码

7:PWMHandler函数
TTC0的timer0每1S中断2000次,每次中断重新设置比较匹配寄存器。
  1. static void PWMHandler(void *CallBackRef, u32 StatusEvent)
  2. {
  3.         XTtcPs *Timer;

  4.         Timer = &(TtcPsInst[TTC_PWM_DEVICE_ID]);

  5.         if (0 != (XTTCPS_IXR_INTERVAL_MASK & StatusEvent)) {
  6.                 XTtcPs_SetMatchValue(Timer, 0, MatchValue);
  7.         }
  8.         else {
  9.                 /*
  10.                  * If it is not Interval event, it is an error.
  11.                  */
  12.                 ErrorCount++;
  13.         }

  14.         XTtcPs_DisableInterrupts(Timer, XTTCPS_IXR_ALL_MASK);
  15. }
复制代码

7方案演示
7.1硬件准备
实验需要用到JTAG下载器、USB转串口外设,另外需要把核心板上的2P模式开关设置到JTAG模式,即ON ON
85b7bac106d9405090698fcafc08af7b.jpg
7.2实验结果
本实验可以通过开发板上的LED观察亮度的变化,也可以通过在线逻辑分析仪查看波形
9f4e8b116f3d4783baba8b786952a660.jpg







您需要登录后才可以回帖 登录 | 立即注册

本版积分规则