数码之家

 找回密码
 立即注册
搜索
查看: 1185|回复: 5

[STM] 关于用SysTick进行微秒级延时的问题

[复制链接]
发表于 2023-8-23 07:53:52 | 显示全部楼层 |阅读模式

爱科技、爱创意、爱折腾、爱极致,我们都是技术控

您需要 登录 才可以下载或查看,没有账号?立即注册

x
本帖最后由 lmn2005 于 2023-8-23 07:55 编辑

CSDN博客的一篇文章( https://blog.csdn.net/m0_53904877/article/details/128375870
)详细介绍了SysTick的工作原理和如何用SysTick进行微秒级或毫秒级延时的方法,本人用STM32CubeMX初始化工程模板(芯片用GD32F103C8T6或STM32F401RCT8),用文章中介绍的延时方法进行延时,结果延时不太正常(比正常的时间长),不知道是什么原因,请各位大佬指教,谢谢!
附:int main代码:

  1. /* USER CODE BEGIN Header */
  2. /**

  3.   */
  4. /* USER CODE END Header */

  5. /* Includes ------------------------------------------------------------------*/
  6. #include "main.h"

  7. /* Private includes ----------------------------------------------------------*/
  8. /* USER CODE BEGIN Includes */
  9. #include <stdio.h>
  10. /* USER CODE END Includes */

  11. /* Private typedef -----------------------------------------------------------*/
  12. /* USER CODE BEGIN PTD */

  13. /* USER CODE END PTD */

  14. /* Private define ------------------------------------------------------------*/
  15. /* USER CODE BEGIN PD */

  16. /* USER CODE END PD */

  17. /* Private macro -------------------------------------------------------------*/
  18. /* USER CODE BEGIN PM */

  19. /* USER CODE END PM */

  20. /* Private variables ---------------------------------------------------------*/
  21. UART_HandleTypeDef huart1;

  22. /* USER CODE BEGIN PV */
  23. /* USER CODE END PV */

  24. /* Private function prototypes -----------------------------------------------*/
  25. void SystemClock_Config(void);
  26. static void MX_GPIO_Init(void);
  27. static void MX_USART1_UART_Init(void);
  28. /* USER CODE BEGIN PFP */

  29. /* USER CODE END PFP */

  30. /* Private user code ---------------------------------------------------------*/
  31. /* USER CODE BEGIN 0 */
  32. int32_t fac_us, fac_ms ;

  33. //STM32 printf重定义
  34. int fputc(int ch, FILE *f)
  35. {
  36.   HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 0xffff);
  37.   return ch;
  38. }

  39. int fgetc(FILE *f)
  40. {
  41.   uint8_t ch = 0;
  42.   HAL_UART_Receive(&huart1, &ch, 1, 0xffff);
  43.   return ch;
  44. }
  45. void delay_init()
  46. {
  47.     /* 配置时钟源 --> 48MHz         */
  48.         HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK  );//配置时钟源为HCLK  
  49.         /* fac_us 和 fac_ms 是定义的全局变量,是倍频因子*/
  50.         fac_us = SystemCoreClock / 1000000;        
  51.         fac_ms = 1000 * fac_us;
  52. }

  53. void delay_us(unsigned int us)
  54. {
  55.         unsigned int temp = 0;
  56.         SysTick->LOAD = fac_us * us;//设置重装载值.1us需要计数48次,计数初值为48
  57.         SysTick->VAL = 0x00;//当前值寄存器清0,即清空计数器
  58.         SysTick->CTRL |= 0x01;//滴答定时器控制寄存器,使能滴答定时器        
  59.         do
  60.         {
  61.                 temp = SysTick->CTRL;//获取控制寄存器的当前状态               
  62.         }while((temp & 0x01) && !(temp & (0x01 << 16)));
  63.         SysTick->CTRL &= 0x00;
  64.         SysTick->VAL = 0x00;
  65. }

  66. void delay_ms(unsigned int ms)
  67. {
  68.         unsigned int temp = 0;
  69.         /*设置重装载值*/
  70.     if(fac_ms * ms <= ((0x01 << 24) - 1))
  71.     {
  72.         SysTick->LOAD = fac_ms * ms;
  73.     }
  74.     else
  75.     {
  76.         return ;
  77.     }
  78.         /*设置重装载值*/
  79.         SysTick->VAL = 0x00;
  80.         /*滴答定时器控制寄存器,使能滴答定时器*/
  81.         SysTick->CTRL |= 0x01;
  82.         
  83.         do
  84.         {
  85.                 /*获取控制寄存器的当前状态*/
  86.                 temp = SysTick->CTRL;
  87.                
  88.         }while((temp & 0x01) && !(temp & (0x01 << 16)));
  89.         SysTick->CTRL &= 0x00;
  90.         SysTick->VAL = 0x00;
  91. }

  92. /* USER CODE END 0 */

  93. /**
  94.   * [url=home.php?mod=space&uid=247401]@brief[/url]  The application entry point.
  95.   * @retval int
  96.   */
  97. int main(void)
  98. {
  99.   /* USER CODE BEGIN 1 */
  100. //int32_t SysClk;        
  101.   /* USER CODE END 1 */
  102.   

  103.   /* MCU Configuration--------------------------------------------------------*/

  104.   /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  105.   HAL_Init();

  106.   /* USER CODE BEGIN Init */
  107.   /* USER CODE END Init */

  108.   /* Configure the system clock */
  109.   SystemClock_Config();

  110.   /* USER CODE BEGIN SysInit */
  111.         delay_init();
  112.   /* USER CODE END SysInit */

  113.   /* Initialize all configured peripherals */
  114.   MX_GPIO_Init();
  115.   MX_USART1_UART_Init();
  116.   /* USER CODE BEGIN 2 */
  117.   /* USER CODE END 2 */

  118.   /* Infinite loop */
  119.   /* USER CODE BEGIN WHILE */
  120.   while (1)
  121.   {
  122.                 HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_0);               
  123.                 //HAL_Delay(1000);
  124.                 delay_ms(1000);                        
  125.     /* USER CODE END WHILE */

  126.     /* USER CODE BEGIN 3 */
  127.   }
  128.   /* USER CODE END 3 */
  129. }
复制代码


 楼主| 发表于 2023-8-27 13:08:01 | 显示全部楼层
有哪位朋友用过32单片机微秒级软件延时的?请分享一下经验,谢谢!
回复 支持 反对

使用道具 举报

发表于 2023-8-28 11:32:09 | 显示全部楼层
定时器?
手推车的延时方法?
一直用的都是用8位片。。。32只会点灯
回复 支持 反对

使用道具 举报

发表于 2023-8-28 15:56:05 | 显示全部楼层
微秒级做不到精确,没什么意义; 毫秒级,用通用定时器+中断就能实现基本精确,比软件延时准多了
回复 支持 反对

使用道具 举报

发表于 2023-8-31 13:42:03 来自手机浏览器 | 显示全部楼层
原子哥的论坛有视频,延时就是估算向某个寄存器写数据的时间是多少,然后外层套一个循环,想想延时多少就循环多少次,但实际上我测试过,时好时坏,用原子哥的代码,凑或用得了
回复 支持 反对

使用道具 举报

发表于 2023-8-31 20:26:15 | 显示全部楼层
如果是简单的微秒级阻塞式延时,

还是用关中断+固定频率+抠指令。


回复 支持 反对

使用道具 举报

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

本版积分规则

APP|手机版|小黑屋|关于我们|联系我们|法律条款|技术知识分享平台

闽公网安备35020502000485号

闽ICP备2021002735号-2

GMT+8, 2025-5-3 09:29 , Processed in 0.218400 second(s), 11 queries , Redis On.

Powered by Discuz!

© 2006-2025 MyDigit.Net

快速回复 返回顶部 返回列表