我在裸机上使用的 Delay 是用 systick timer 实现的
/**
* @brief Microsecond delay
* @param us specifies the delay time length, in microseconds.
* @retval None
*/
void Delay_us(uint32_t us)
{
if (us > 0)
{
SysTick->LOAD = SYSTICK_LOAD * us; // Set systick reload value
SysTick->VAL = 0x00; // Set SysTick Current Value to 0
SysTick->CTRL = 0x00000005; // Set SysTick clock source to use processor clock and enable timer
while (!(SysTick->CTRL & 0x00010000)) // Wait for the timer to count to 0
{
}
// SysTick->CTRL = 0x00000004; // Disable timer
}
}
所以会和 FreeRTOS 产生冲突,所以采用了 TIM2:
void Delay_Init(void)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
TIM_TimeBaseInitStructure.TIM_Prescaler = 72 - 1;
TIM_TimeBaseInitStructure.TIM_Period = 1;
TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Down;
TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStructure);
}
/**
* @brief Microsecond delay
* @param us specifies the delay time length, in microseconds.
* @retval None
*/
void Delay_us(uint32_t us)
{
if (us > 0)
{
TIM2->CNT = us - 1; // 向计数器装要递减的数,减到0后会触发定时器的TIM_FLAG_UpDate标志位
TIM2->CR1 |= TIM_CR1_CEN; // 使能计数器, 计数器开始递减
while ((TIM2->SR & TIM_FLAG_Update) != SET)
{
// 等到计数器减到0
}
TIM2->CR1 &= (~TIM_CR1_CEN); // 关闭计数器
TIM2->SR &= (~TIM_FLAG_Update); // 清除定时器变为0的标志位
}
}
请问还有其他方法么?比如还是利用 SysTick 来delay,只读不修改。
创建任务时,usStackDepth 最好设置大一点儿,例如 128
如果你使用任何通信,请把通信函数添加到 `portENTER_CRITICAL()` 和 `portEXIT_CRITICAL()` 之间,这是为了确保时间片结束不会被打断通信
void vSHT30Task(void *pvParameters)
{
SHT30_TypeDef sht30 = {0};
for (;;)
{
portENTER_CRITICAL();
SHT30_Measure_Periodic_Mode(&sht30);
OLED_ShowNum(3, 1, sht30.temp, 4);
OLED_ShowNum(4, 1, sht30.hum, 4);
printf("sht30_task:%f\n", sht30.hum);
portEXIT_CRITICAL();
vTaskDelay(1000);
}
}
p.s. 为什么论坛不支持 markdown 呢,写文章好麻烦。
最近编辑记录 shiinakaze (2024-10-01 10:56:10)
离线
RTOS使用systick溢出中断的分辨率是毫秒,其计数器VAL的分辨率小于微秒。两者结合可以得到微秒分辨率的计时
好的,谢谢大佬指点。
离线