STM32F407如何點亮一個呼吸燈(庫函式)

52017發表於2024-07-03
/**
   ******************************************************************************
   * @file    main.c 
   * @author  
   * @version 
   * @date    2024/07/03
   * @brief   實現利用基本定時器TIM14實現定時10ms,每隔10ms從滅到亮逐漸變亮,再隔10ms從
   			  亮到滅逐漸變暗,實現控制LED的呼吸燈設定

   ******************************************************************************
**/

#include "stm32f4xx.h"  //必須包含

//LED的初始化
void  LED_Config()
{
	//1.定義GPIO外設的結構體變數
	GPIO_InitTypeDef  GPIO_InitStructure;
	
	//2.開啟GPIOF埠的時鐘
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOF, ENABLE);
	
	//3.配置PF9引腳為輸出模式
	GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_9;
	GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_OUT;
	GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
	GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_NOPULL;
	
	//4.對GPIOF埠進行初始化
	GPIO_Init(GPIOF, &GPIO_InitStructure);
	
	GPIO_SetBits(GPIOF,GPIO_Pin_9);//LED不亮
}

//BEEP的初始化
void  BEEP_Config()
{
	//1.定義GPIO外設的結構體變數
	GPIO_InitTypeDef  GPIO_InitStructure;
	
	//2.開啟GPIOF埠的時鐘
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOF, ENABLE);
	
	//3.配置PF9引腳為輸出模式
	GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_8;
	GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_OUT;
	GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
	GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_NOPULL;
	
	//4.對GPIOF埠進行初始化
	GPIO_Init(GPIOF, &GPIO_InitStructure);
	
	GPIO_ResetBits(GPIOF,GPIO_Pin_8);//BEEP預設不響
}

//延時微秒 注意:Systick是24bit的遞減計數器  約等於798915us,所以引數不可以超過這個值
void delay_us(u32 nus)
{
	SysTick->CTRL = 0; 						 // 向控制狀態暫存器中寫入0,目的關閉系統嘀嗒定時器
	SysTick->LOAD = (nus * 21) - 1;// 指的是計數次數,定時時間 = 計數次數 * 計數週期
	SysTick->VAL  = 0; 						 // 清除當前數值暫存器的值
	SysTick->CTRL = 1; 						 // 開啟了定時器,並且定時器的時鐘源選擇了21MHZ--> 計數週期 = 1/21us
	while ((SysTick->CTRL & 0x00010000)==0);//等待延時時間到達
	SysTick->CTRL = 0; 						 // 向控制狀態暫存器中寫入0,目的關閉系統嘀嗒定時器

}

//延時毫秒 注意:Systick是24bit的遞減計數器  約等於798ms,所以引數不可以超過這個值
void delay_ms(u32 nms)
{
	SysTick->CTRL = 0; 						 			// 向控制狀態暫存器中寫入0,目的關閉系統嘀嗒定時器
	SysTick->LOAD = (nms * 21*1000) - 1;// 指的是計數次數,定時時間 = 計數次數 * 計數週期
	SysTick->VAL  = 0; 						 			// 清除當前數值暫存器的值
	SysTick->CTRL = 1; 						 			// 開啟了定時器,並且定時器的時鐘源選擇了21MHZ--> 計數週期 = 1/21us
	while ((SysTick->CTRL & 0x00010000)==0);//等待延時時間到達
	SysTick->CTRL = 0; 						 			// 向控制狀態暫存器中寫入0,目的關閉系統嘀嗒定時器
}

//延時秒
void delay_s(u32 ns)
{
	while(ns--)
	{
		delay_ms(500);
		delay_ms(500);
	}
}

//TIM14的初始化
void  TIM14_Config()
{
	//1.定義GPIO、TIM時基、TIM輸出結構體變數
	TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
	GPIO_InitTypeDef GPIO_InitStructure;
	TIM_OCInitTypeDef  TIM_OCInitStructure;

	//2.開啟TIM14+GPIOF的時鐘
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM14,  ENABLE);
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOF,  ENABLE);
	
	//3.對GPIO結構體變數的引腳PF9進行賦值(LED燈)
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
	GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
	GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP ;
	
	//4.對GPIOF埠進行初始化
	GPIO_Init(GPIOF, &GPIO_InitStructure);
	
	//5.設定GPIOF為中斷源
	GPIO_PinAFConfig(GPIOF, GPIO_PinSource9, GPIO_AF_TIM14);
	
	//6.定義結構體變數並對結構體變數的成員進行賦值,1s可以生成100個脈衝
	TIM_TimeBaseStructure.TIM_Prescaler = 8400-1;				//預分頻值,TIM14的時鐘是84MHZ,所以可以降低頻率 100us計數一次
	TIM_TimeBaseStructure.TIM_Period = 100-1;	 				//計數次數,這個值會寫入自動過載暫存器 100us * 100 = 10ms    
	TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //計數模式,基本定時器TIM6和TIM7只允許遞增計數

	//7.對定時器結構體變數進行賦值
	TIM_TimeBaseInit(TIM14, &TIM_TimeBaseStructure);
	TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;				//PWM模式1
	TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;	//輸出狀態使能
	TIM_OCInitStructure.TIM_Pulse = 95;								//佔空比
	TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low;		//低電平有效
	
	//7.對定時器進行初始化
	TIM_OC1Init(TIM14, &TIM_OCInitStructure);//設定利用通道1輸出,複用功能PF9繫結通道一
	
	//8.對TIM4定時器設定使能預裝載暫存器
	TIM_OC1PreloadConfig(TIM14, TIM_OCPreload_Enable);
	
	//9.對TIM4定時器設定允許自動重灌載暫存器
	TIM_ARRPreloadConfig(TIM14, ENABLE);

	//10.開啟定時器TIM14
	TIM_Cmd(TIM14, ENABLE);
}

int main()
{
	
	//1.硬體的初始化
	TIM14_Config();
	
	while(1)
	{
		//LED越來越亮
		for(int i = 0; i<100;i++)
		{
			TIM14->CCR1 = i;
			delay_ms(15);
		}
		
		//LED越來越暗
		for(int i = 100; i>=0;i--)
		{
			TIM14->CCR1 = i;
			delay_ms(15);
		}
		
	}
}

相關文章