第71章 内核定时器控制流水灯
第七十一章 内核定时器控制流水灯
1. 硬件设计
LED方面参考之前的章节
2. 软件设计
2.1 编程大纲
-
初始化时间戳
-
延时函数
-
主函数测试
2.2 代码分析
2.2.1 初始化时间戳
#if USE_DWT_DELAY // 宏定义,如果没有定义,则不使用DWT延时函数
#define DWT_CR *(__IO uint32_t *)0xE0001000 // DWT控制寄存器地址
#define DWT_CYCCNT *(__IO uint32_t *)0xE0001004 // DWT计数器地址
#define DEM_CR *(__IO uint32_t *)0xE000EDFC // 调试监视器控制寄存器地址
#define DEM_CR_TRCENA (1 << 24) // 调试监视器控制寄存器的位24,DWT使能位
#define DWT_CR_CYCCNTENA (1 << 0) // DWT控制寄存器的位0,CYCCNT使能位
// 初始化时间戳
void CPU_TS_TmrInit(void)
{
DEM_CR |= (uint32_t)DEM_CR_TRCENA; // 使能DWT外设
DWT_CYCCNT = (uint32_t)0u; // 清0计数器
DWT_CR |= (uint32_t)DWT_CR_CYCCNTENA; // 使能CYCCNT计数器
}
// 读取当前时间戳
uint32_t CPU_TS_TmrRd(void)
{
return ((uint32_t)DWT_CYCCNT);
}
2.2.2 延时函数
/ 采用CPU的内部计数实现精确延时,32位计数器
void CPU_TS_Tmr_Delay_US(__IO uint32_t us)
{
uint32_t ticks;
uint32_t told,tnow,tcnt=0;
/* 在函数内部初始化时间戳寄存器, */
#if (CPU_TS_INIT_IN_DELAY_FUNCTION)
/* 初始化时间戳并清零 */
CPU_TS_TmrInit();
#endif
ticks = us * (GET_CPU_ClkFreq() / 1000000); /* 需要的节拍数 */
tcnt = 0;
told = (uint32_t)CPU_TS_TmrRd(); /* 刚进入时的计数器值 */
while(1)
{
tnow = (uint32_t)CPU_TS_TmrRd();
if(tnow != told)
{
/* 32位计数器是递增计数器 */
if(tnow > told)
{
tcnt += tnow - told;
}
/* 重新装载 */
else
{
tcnt += UINT32_MAX - told + tnow;
}
told = tnow;
/*时间超过/等于要延迟的时间,则退出 */
if(tcnt >= ticks)break;
}
}
}
#endif
2.2.3 主函数测试
#include "stm32f10x.h"
#include "led.h"
#include "core_delay.h"
int main(void)
{
LED_Init();
CPU_TS_TmrInit();
while(1)
{
LED1_ON();
Delay_us(100000); // 100000 * 10us = 1000ms
LED1_OFF();
LED2_ON();
Delay_us(100000);
LED2_OFF();
LED3_ON();
Delay_us(100000);
LED3_OFF();
}
}
LED依次点亮,形成流水灯

浙公网安备 33010602011771号