Systick_Ticker工程实现的功能是,使用ARM处理器的Systick定时器计时,在定时器中断服务程序中控制三个LED灯闪烁的频率。 需要考虑到几个设计要点: (1)应用Systick定时器,设定定时器的计时周期,并启用定时溢出中断。 (2)应用GPIO驱动程序调用底层硬件控制可编程LED引脚的电平。 (3)在Systick定时器中断服务程序中,使用软件实现的分频计数器,对Systick定时器的溢出频率进行分频,得到三个LED灯各自闪烁的频率。 在程序主循环中,通过在串口终端中输入按键(任何字符均可),触发Systick定时器的启动和关闭:当Systick定时器启动时,可以观察到三个LED灯各自闪烁;当Systick定时器关闭时,LED灯停止闪烁,保持状态。 开始编程:
步骤一:创建工程 考虑到要使用stdio的通信信道作为人机交互,同时要使用GPIO控制LED灯闪烁,在项目代码树的“\example”目录下,复制已经创建好的样例工程“GPIO_BlinkyLED”作为本工程的模板,改目录名为“Systick_Ticker”。Systick模块本身是ARM定义的一个标准模块,其相关的寄存器及操作函数被定义arm_cm3.h文件中,因此不需要额外引用外部驱动文件。 在Keil集成开发环境下组织工程代码如图1所示。
图1 Systick_Ticker工程组织 步骤二:添加应用代码 本工程基于GPIO_BlinkyLED,所以继承了关于控制LED灯的函数,包括: - /* LED. */
- void LED_Configuration(void);
- void LED_LightOn(uint32_t ledIdx);
- void LED_LightOff(uint32_t ledIdx);
- void LED_LightSwitch(uint32_t ledIdx);
复制代码在main.c文件中添加关于Systick定时器的程序代码如下: - void Ticker_Configuration(uint32_t tickersPerSecond)
- {
- SysTick_Config(SystemCoreClock / tickersPerSecond);
- NVIC_SetPriority(SysTick_IRQn, 0x00);
-
- SysTick->LOAD = (uint32_t)(SystemCoreClock / tickersPerSecond - 1UL); /* set reload register */
- NVIC_SetPriority (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /* set Priority for Systick Interrupt */
- SysTick->VAL = 0UL; /* Load the SysTick Counter Value */
- SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | /* Select the clock source. */
- SysTick_CTRL_TICKINT_Msk; /* Enable SysTick IRQ. */
- }
- void Ticker_Start(void)
- {
- SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk;
- }
- void Ticker_Pause(void)
- {
- SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk;
- }
复制代码其中,Ticker_Configuration()函数配置Systick定时器以传入参数tickersPerSecond为频率周期产生时钟滴答(Tick),并启用Systick中断在滴答到来之时被触发执行服务程序。Ticker_Start()和Ticker_Start()用于启动和暂停定时器。 特别设计Systick定时器中断服务程序如下:
- /*
- * Interrupt Service Routine.
- */
- volatile uint32_t gTickerCounter[3] = {0};
- const uint32_t gLedSwitchTickers[3] = {100U, 200U, 400U};
- void SysTick_Handler(void)
- {
- uint32_t i;
-
- for (i = 0U; i < 3U; i++)
- {
- if (gTickerCounter[i] >= gLedSwitchTickers[i])
- {
- gTickerCounter[i] = 0U;
- LED_LightSwitch(i); /* Switch the LED. */
- }
- gTickerCounter[i]++;
- }
- }
复制代码此时,使用gLedSwitchTickers[]数组为三个LED灯指定闪烁频率的分频因子,分别为100、200、400。在Systick的中断服务程序SysTick_Handler中,基于分频后的节奏分别控制三个LED灯。 最后,实现顶层的main函数如下: - /*
- * Application Entry.
- */
- int main(void)
- {
- BSP_InitStdioUART(115200U);
- printf("\r\n\r\n# Systick_TickerInterrupt Exampler #\r\n");
- /* Initialize the application. */
- printf("# Initializing ...\r\n");
-
- LED_Configuration();
- Ticker_Configuration(200U); /* 200 tickers per second. 1 ticker = 5ms. */
-
- printf("# Ready.\r\n");
-
- /* Print the user guide. */
- printf("Press any key to toggle the ticker ...\r\n");
-
- while (1)
- {
- getchar();
- Ticker_Start();
- printf("Ticker_Start()\r\n");
- getchar();
- Ticker_Pause();
- printf("Ticker_Pause()\r\n");
- }
- }
复制代码步骤三:下载程序,运行 编译工程,下载到开发板。在上位机启动串口通信终端界面后,复位开发板运行程序。此时,根据终端输出的提示信息,在终端界面中输入回车(或者其它任何字符均可)启动Systick定时器,观察开发板即可发现三个LED灯以“二进制编码”递增序列闪烁。再次输入回车暂停Systick定时器,LED灯保持最后状态停止闪烁。如此反复。上位机的串口通信终端输入信息如图2所示。
图2 Systick_Ticker终端界面输出
|