标题: STM32 SysTick定时器使用(非常适合初学者) [打印本页]

作者: wylyhz999    时间: 2021-8-2 12:39
标题: STM32 SysTick定时器使用(非常适合初学者)
作为一名stm32的初学者,无人指导自学还是很困难的,网络上虽热资料很多,但是对于基础薄弱的人来说还是很难理解各个外设的使用,初次发帖,以最简单明了的方式解说使用SysTick定时器,没有专业术语,简单粗暴。(专业的大佬请视而不见,哈哈哈)下面的程序是使用Systick定时2秒实现led间隔2秒亮灭(stm32f103c8t6芯片)
#include"stm32f10x.h"
uint32_t count;               //定义了一个全局变量,stm32f10x_it.h也声明这个全局变量
void led_config()             //引脚PB8的配置
{
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_8;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOB,&GPIO_InitStructure);
}
void delay(uint16_t ntime)  //延时函数,ntime就是次数
{
count=ntime;                   //ntime这个值由我们自己设定,就是进入SysTick中断的次数,ntime赋值给全局变量count
while(count!=0);              //进入Systick中断一次,count就减1,这边判断count是否减到零,跳出while
}
int main()
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);   //开启GPIOB时钟,先开启时钟,GPIO引脚参数才能有效配置
led_config();                                                                  //引脚PB8配置写入
SysTick_Config(72000);                                                  //SysTick的时钟源是72MHz, 72000就是定时1ms进入中断函数
while(1)
{
  GPIO_SetBits(GPIOB,GPIO_Pin_8);
  delay(2000);                                                        //延时2s,进入中断2000次,每次减1,最后得到0,跳出while,执行下一语句ResetBits
  GPIO_ResetBits(GPIOB,GPIO_Pin_8);
  delay(2000);
}
}

*******************以下是需要配置的一些东西********************************

在stm32f10x_it.c文件中找到void SysTick_Handler(void)中断函数, 函数里面写入count--  如下:
void SysTick_Handler(void)
{
    count--;                                                   
}


在stm32f10x_it.h文件中一定要定义全局变量count,如下:
  extern uint32_t count;            

我看了很多帖子,都是把SysTick_Handler函数写的很累赘,我喜欢简单 count--,一句搞定,大家都很忙
新人第一次发帖,不好的地方多指导,感谢






作者: 1205551786    时间: 2021-8-2 15:20
void delay(uint16_t ntime)  //延时函数,ntime就是次数
{
count=ntime;                   //ntime这个值由我们自己设定,就是进入SysTick中断的次数,ntime赋值给全局变量count
while(count!=0);              //进入Systick中断一次,count就减1,这边判断count是否减到零,跳出while
}
这里怎么减少的呢?
作者: 黄youhui    时间: 2021-8-2 15:50
1205551786 发表于 2021-8-2 15:20
void delay(uint16_t ntime)  //延时函数,ntime就是次数
{
count=ntime;                   //ntime这个 ...

他这里没有减少,在滴答定时器中断里面减少,这里就是将他while锁住,等待定时器将count减少至0.
另外一般会在这里加一个标志位delay_flag
uint8_t delay_flag;
uint16_t delay_count;
void delay_ms(uint16_t ntime)
{

}
作者: 黄youhui    时间: 2021-8-2 16:06
1  你这里是将16进制数字直接赋值给32进制变量,最好进制一致,要么都用16要么都用32,虽然不报错,但是习惯要养好。 uint32_t count;               //定义了一个全局变量,stm32f10x_it.h也声明这个全局变量
void delay(uint16_t ntime)  //延时函数,ntime就是次数
{
count=ntime;  

2 就是你的滴答定时器不会因为你的delay函数计时结束就不进入中断,所以你最好加一个标志位,没有调用delay()函数时它不做任何处理直接退出
   {
if(delay_flag ==1){count--;}
else ;
   }  


作者: wylyhz999    时间: 2021-8-2 21:20
黄youhui 发表于 2021-8-2 16:06
1  你这里是将16进制数字直接赋值给32进制变量,最好进制一致,要么都用16要么都用32,虽然不报错,但是习 ...

感谢指正,我刚学,经验不足
作者: bigbigcong    时间: 2021-8-5 19:38
我昨天在论坛上看到了一个更高级的方法,你这里是每到2S时间就一直卡死,这样太浪费CPU资源了,可以设计成如果没到2S就跳过/忽略这个操作,然后继续下去执行别的操作。这样系统实时性就提高很多,CPU就能做到“负载均衡”了…………
作者: 黄youhui    时间: 2021-8-7 09:04
bigbigcong 发表于 2021-8-5 19:38
我昨天在论坛上看到了一个更高级的方法,你这里是每到2S时间就一直卡死,这样太浪费CPU资源了,可以设计成 ...

事事无绝对,有些地方是必须要卡主的,比如某些外设初始化需要延时1S启动。你说的那是标志位必须用在循环不停检测标志位才行,它不会运行到第一万行代码时,时间到了就突然跳到第一执行代码,必须在第一到第n行代码之间不停循环,确保时间一到立马能执行对应的函数




欢迎光临 (http://www.51hei.com/bbs/) Powered by Discuz! X3.1