嵌入式STM32学习笔记(2)——点亮LED灯及用中断让其闪烁

这里直接开始码代码了,至于前期的准备工作比如配置MDK-keil,或配置IAR等,大家可以在网上找对应的教程,这里不赘述了;直接讲代码如何撸吧,代码里我做了详细注释:

1)编译器IAR8,系统win10;

2)板子:STM32F103C8T6核心板,如下:

嵌入式STM32学习笔记(2)——点亮LED灯及用中断让其闪烁

3)下载器:ST-LINK/V2仿真下载器;

4)板子上LED对应的引脚是GPIOC, GPIO_Pin_13;在IAR对应的stm32F103X模板DRIVER目录下添加:led.c,led.h,timer.c,timer.h文件,如下:

嵌入式STM32学习笔记(2)——点亮LED灯及用中断让其闪烁

5)led.c 代码如下:

#include "led.h"

/*LED_G 驱动 GPIO 初始化函数*/
void led_gpio_config(void)
{
  GPIO_InitTypeDef GPIO_InitStructure; //调用GPIO结构体
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE); //配置RCC时钟,使得引脚使能
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13; //设置的引脚
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //设置引脚速度
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //设置引脚模式,推挽式输出
  GPIO_Init(GPIOC, &GPIO_InitStructure); //初始化引脚
  
//  以下实验代码
//   GPIO_InitTypeDef  GPIO_InitStructure;
//	
//   /* Enable the GPIO_LED Clock */
//   RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB 
//	                  |RCC_APB2Periph_GPIOC
//			  |RCC_APB2Periph_GPIOD, ENABLE);//使能
//	
//   /* Configure the GPIO_LED pin */
//   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13;
//   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; 	//推挽输出
//   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;	
//  
//   GPIO_Init(GPIOA, &GPIO_InitStructure);
//   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_All;
//   GPIO_Init(GPIOB, &GPIO_InitStructure);
//   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_All ;
//   GPIO_Init(GPIOC, &GPIO_InitStructure);
   
}

6)led.h的代码:

#ifndef _LED_H
#define _LED_H

/*包含相关的头文件*/
#include "stm32f10x.h"
#include "stm32f10x_gpio.h"
#include "stm32f10x_rcc.h"

void led_gpio_config(void);//声明,初始化LED对应引脚

#endif

7)timer.c代码:

#include "timer.h"
__IO uint32_t TimingDelay; //计数变量,加要加“_IO”,不然会被编译优化
__IO uint32_t TimingDelay2; //计数变量2

/*SystemCoreClock / 1000000  -------   1us*/
/*SystemCoreClock / 100000   -------   10us*/
/*SystemCoreClock / 10000    -------   100us*/
/*SystemCoreClock / 1000     -------   1ms*/


//////////////////////////
//设置系统滴答中断延时程序//
/////////////////////////

void Systick_Init(void)
{
  //装载系统时钟中断计数值,系统时钟累计达到72000时候溢出产生中断
    if (SysTick_Config(72000))
    { 
      /* Capture error */ 
      while (1);
    }
}

//延时计数函数,如果不是0,每个系统滴答中断周期自减
void TimingDelay_Decrement(void)
{
    if (TimingDelay != 0x00)
    {
        TimingDelay--;
    }
}

//延迟函数,设置为 US
void delay_ms(__IO uint32_t nTime)
{
    TimingDelay = nTime;//自减初始值
    while(TimingDelay != 0);
}

//中断事件函数,原函数在stm32f10x_it.c里面,复制到这里后要将原位置里的注释掉,不然报错
void SysTick_Handler(void)
{
    TimingDelay_Decrement();
}

//////////////////////////
//设置定时器中断延时程序//
/////////////////////////

//配置嵌套中断控制器 NVCI
void tim2_nvic_config(void)
{
    NVIC_InitTypeDef NVIC_Init_Struct; //调用NVCI结构体
    
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0); //设置组优先级
    
    NVIC_Init_Struct.NVIC_IRQChannel = TIM2_IRQn; //设置定时器 2 中断
    NVIC_Init_Struct.NVIC_IRQChannelPreemptionPriority = 0; //设置抢占优先级
    NVIC_Init_Struct.NVIC_IRQChannelSubPriority = 0; //设置子优先级
    NVIC_Init_Struct.NVIC_IRQChannelCmd = ENABLE; //使能IRQ中断
    NVIC_Init(&NVIC_Init_Struct); //初始化NVIC
}


//定时器初始化配置
void tim2_config(void)
{
    TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct; //调用定时器结构体
    
    tim2_nvic_config(); //加载嵌套中断控制器 NVCI
    
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE); //配置RCC时钟,使得中断使能
    TIM_DeInit(TIM2); //将外设 TIMx 寄存器重设为缺省值,复位寄存器
    
    /*
	定时计数计算方法如下:
	发生中断时间 = (TIM_Prescaler+1)* (TIM_Period+1)/FLK
	以定时 1s 为例 TIM_Period=2000-1, TIM_Prescaler=(36000-1)
    */   
    TIM_TimeBaseInitStruct.TIM_Prescaler = 36000-1; //时钟预先分频数
    TIM_TimeBaseInitStruct.TIM_Period = 2-1;  //自动重装载寄存器的值
    TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up; //计数模式,向上计数方式
    TIM_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIV1; //采样分频
    TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStruct);    //初始化TIM2配置
    TIM_ClearFlag(TIM2,TIM_FLAG_Update); //清除溢出中断标志
    TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE); //使能或者失能指定的 TIM 中断
    TIM_Cmd(TIM2,ENABLE); //开启时钟
}


//延时计数函数2,如果不是0,每个系统滴答中断周期自减
void TimingDelay_Decrement2(void)
{
    if (TimingDelay2 != 0x00)
    {
        TimingDelay2--;
    }
}

//延迟函数,设置为 US
void delay_ms2(__IO uint32_t nTime2)
{
    TimingDelay2 = nTime2;//时钟滴答数
    while(TimingDelay2 != 0);
}


//定时器2,中断事件函数
void TIM2_IRQHandler(void)
{
    if(TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET)//固件库函数,判断是否发生TIM2中断
    {
      TimingDelay_Decrement2(); //调用延时计数函数
    }
    TIM_ClearITPendingBit(TIM2,TIM_FLAG_Update);//标志位清除,固件库函数
}

8)timer.h代码:

#ifndef __TIMER_H_
#define __TIMER_H_

#include "stm32f10x_tim.h"
#include "stm32f10x_rcc.h"
#include "stm32f10x_it.h"
#include "misc.h"

extern __IO uint32_t TimingDelay; //计数变量,加要加“_IO”,不然会被编译优化
void Systick_Init(void); //初始化系统滴答
void TimingDelay_Decrement(void); //计数函数
void delay_ms(__IO uint32_t nTime);//延迟函数,设置为 US


extern __IO uint32_t TimingDelay2; //计数变量2
void tim2_nvic_config(void); //初始化中断
void tim2_config(void); //初始化计数器
void delay_ms2(__IO uint32_t nTime2);//延迟函数2,设置为 US
void TimingDelay_Decrement2(void); //计数函数2

#endif

9)主函数main.c代码:

#include "led.h"
#include "timer.h"

int main(void)
{
    SystemInit();  //初始化系统时钟
    Systick_Init(); //配置系统时钟滴答参数
    led_gpio_config();  //配置GPIO
    tim2_config();//配置定时器
    
    while(1)
    {
      
      //调用系统滴答延时函数做LED灯的闪烁//
//        GPIO_SetBits(GPIOC, GPIO_Pin_13);    //将PB13设置成高电平
//        delay_ms(100);                    //调用系统滴答延时函数
//        GPIO_ResetBits(GPIOC, GPIO_Pin_13);    //将PB13设置成低电平
//        delay_ms(100);                       //调用系统滴答延时函数
      
        //调用定时器延时函数做LED灯闪烁//
        GPIO_SetBits(GPIOC, GPIO_Pin_13);    //将PB13设置成高电平
        delay_ms2(500);                     //调用定时器延时函数
        GPIO_ResetBits(GPIOC, GPIO_Pin_13);   //将PB13设置成低电平
        delay_ms2(100);                     //调用定时器延时函数      
    }
    return 0;
}

10)源码在我的资源里有上传,连接:https://download.csdn.net/download/abcvincent/11176669