第8-9周作业--定时器&PWM应用编程

第8-9周作业–定时器&PWM应用编程

一. 使用STM32F103的 Tim2~Tim5其一定时器的某一个通道pin(与GPIOx管脚复用,见下图),连接一个LED,用定时器计数方式,控制LED以2s的频率周期性地亮-灭。

创建一个新工程选择STM32F103C8T6,点击START PROJECT

在这里插入图片描述

在System Core下选择RCC,将HSE改成Crystal/Ceramic Resonator

在这里插入图片描述

点击SYS,将Debug改成Serial Wire

在这里插入图片描述

点击PA2,选择GPIO_Output

在这里插入图片描述

在目录Timers下点击TIM2,将Clock Source时钟源选择为Internal Clock内部时钟,设置分频系数为71,向上计数模式,计数周期为5000。

在这里插入图片描述

TIM3同上设置

点击NVIC,勾选TIM2和TIM3的中断

在这里插入图片描述

然后点击Code generation,勾选TIM2的中断优先级

在这里插入图片描述

在目录Connectivity下点击USART1,将Mode改为异步通信Asynchronous

在这里插入图片描述

点击Clock,将HCLK改为72,点击回车

在这里插入图片描述

点击GENNERATE CODE创建工程

在这里插入图片描述

打开工程
在这里插入图片描述

将下断代码复制到main.c里面

`void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
static uint32_t time_cnt = 0;

if (htim->Instance == TIM2)  
{  
    if (++time_cnt >= 400)  
    {  
        time_cnt = 0;  
        HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_2);  
    }  
}  

}`

在这里插入图片描述

烧录进去
在这里插入图片描述

功能实现:
https://live.csdn.net/v/341048

二. 接上,采用定时器pwm模式,让 LED 以呼吸灯方式渐亮渐灭,周期为1~2秒,自己调整到一个满意效果。使用Keil虚拟示波器,观察 pwm输出波形。

选择Timer 4,点击Internal Clock,在Channel3 选择 PWM Generation CH3

在这里插入图片描述

在下方的“Parameter Setting”中的“Counter settings"设置PSC, ARR, auto-reload

在这里插入图片描述

由于呼吸灯没有用到中断,因此NVIC不需要配置;并且由于Timer4的CH3是PB8管脚的复用,因此在完成上面三步的设置后,就相当于配置了PB8,因此GPIO的PB8也不要配置

点击GENERRATE CODE生成keil工程

在这里插入图片描述

打开main.c,输入代码:

`#include “main.h”
#include “tim.h”
#include “usart.h”
#include “gpio.h”

/* Private includes ----------------------------------------------------------/
/
USER CODE BEGIN Includes */

/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------/
/
USER CODE BEGIN PTD */

/* USER CODE END PTD */

/* Private define ------------------------------------------------------------/
/
USER CODE BEGIN PD */

/* USER CODE END PD */

/* Private macro -------------------------------------------------------------/
/
USER CODE BEGIN PM */

/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/

/* USER CODE BEGIN PV */

/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------/
void SystemClock_Config(void);
static void MX_NVIC_Init(void);
/
USER CODE BEGIN PFP */

/* USER CODE END PFP */

/* Private user code ---------------------------------------------------------/
/
USER CODE BEGIN 0 */

/* USER CODE END 0 */

/**

  • @brief The application entry point.
  • @retval int
    /
    int main(void)
    {
    /
    USER CODE BEGIN 1 */

/* USER CODE END 1 */

/* MCU Configuration--------------------------------------------------------*/

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

/* USER CODE BEGIN Init */

/* USER CODE END Init */

/* Configure the system clock */
SystemClock_Config();

/* USER CODE BEGIN SysInit */

/* USER CODE END SysInit */

/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_TIM2_Init();
MX_TIM3_Init();
MX_USART1_Init();
MX_TIM4_Init();

/* Initialize interrupts /
MX_NVIC_Init();
/
USER CODE BEGIN 2 */

/* USER CODE END 2 */

/* Infinite loop /
/
USER CODE BEGIN WHILE */
uint16_t pwmVal = 0;//调整占空比的参数
uint8_t dir = 1;//改变方向 1:越来越亮;0:越来越暗

//写在Timer的初始化后
HAL_TIM_PWM_Start(&htim4, TIM_CHANNEL_3); //打开Timer4的3号Channel

while (1)
{
HAL_Delay(1); //一定要先Delay一下,不然不会亮
if(dir == 1){ //如果是越来越亮
pwmVal++; //则CCRx的值变大,占空比变大,即有效电平(低电平)的占比变大,亮度变高
}else{
pwmVal–; //则CCRx的值变小,占空比变小,即有效电平(低电平)的占比变小,亮度变低
}

	if(pwmVal > 500){ //如果CCRx的值超过了ARR
		dir = 0; //则越来越暗
	}else if(pwmVal == 0){ //如果CCRx的值为0
		dir = 1; //则越来越亮
	}
	
	__HAL_TIM_SetCompare(&htim4, TIM_CHANNEL_3, pwmVal); //修改CCRx,进而修改占空比

}
/* USER CODE END 3 */
}

/**

  • @brief System Clock Configuration
  • @retval None
    */
    void SystemClock_Config(void)
    {
    RCC_OscInitTypeDef RCC_OscInitStruct = {0};
    RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};

/** Initializes the RCC Oscillators according to the specified parameters

  • in the RCC_OscInitTypeDef structure.
    */
    RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
    RCC_OscInitStruct.HSEState = RCC_HSE_ON;
    RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;
    RCC_OscInitStruct.HSIState = RCC_HSI_ON;
    RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
    RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
    RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;
    if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
    {
    Error_Handler();
    }

/** Initializes the CPU, AHB and APB buses clocks
*/
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
{
Error_Handler();
}
}

/**

  • @brief NVIC Configuration.
  • @retval None
    /
    static void MX_NVIC_Init(void)
    {
    /
    TIM2_IRQn interrupt configuration */
    HAL_NVIC_SetPriority(TIM2_IRQn, 0, 0);
    HAL_NVIC_EnableIRQ(TIM2_IRQn);
    }

/* USER CODE BEGIN 4 */

/* USER CODE END 4 */

/**

  • @brief This function is executed in case of error occurrence.
  • @retval None
    /
    void Error_Handler(void)
    {
    /
    USER CODE BEGIN Error_Handler_Debug /
    /
    User can add his own implementation to report the HAL error return state /
    __disable_irq();
    while (1)
    {
    }
    /
    USER CODE END Error_Handler_Debug */
    }

#ifdef USE_FULL_ASSERT
/**

  • @brief Reports the name of the source file and the source line number
  •     where the assert_param error has occurred.
    
  • @param file: pointer to the source file name
  • @param line: assert_param error line source number
  • @retval None
    */
    void assert_failed(uint8_t file, uint32_t line)
    {
    /
    USER CODE BEGIN 6 /
    /
    User can add his own implementation to report the file name and line number,
    ex: printf(“Wrong parameters value: file %s on line %d\r\n”, file, line) /
    /
    USER CODE END 6 /
    }
    #endif /
    USE_FULL_ASSERT */`

在这里插入图片描述

然后烧录运行:

在这里插入图片描述

https://live.csdn.net/v/341049

三. 再接上,采用定时器的另外一个通道,编程采集上面的pwm输出信号,获得其周期和脉宽,并重定向输出到串口显示。

对CUBEMX进行设置

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

任何点击GENERAT CODE 生成工程

在这里插入图片描述

然后将以下代码复制粘贴入main.c里面

`/* USER CODE BEGIN Header /
/
*


  • @file : main.c
  • @brief : Main program body

  • @attention
    *
  • Copyright © 2023 STMicroelectronics.
  • All rights reserved.
    *
  • This software is licensed under terms that can be found in the LICENSE file
  • in the root directory of this software component.
  • If no LICENSE file comes with this software, it is provided AS-IS.
    *

/
/
USER CODE END Header /
/
Includes ------------------------------------------------------------------*/
#include “main.h”
#include “tim.h”
#include “usart.h”
#include “gpio.h”

/* Private includes ----------------------------------------------------------/
/
USER CODE BEGIN Includes */

/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------/
/
USER CODE BEGIN PTD */

/* USER CODE END PTD */

/* Private define ------------------------------------------------------------/
/
USER CODE BEGIN PD */

/* USER CODE END PD */

/* Private macro -------------------------------------------------------------/
/
USER CODE BEGIN PM */

/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/

/* USER CODE BEGIN PV */

/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void MX_NVIC_Init(void);uint8_t i = 0;

float Duty = 0;
float Frequency = 0;
uint16_t Cap_val1 = 0;
uint16_t Cap_val2 = 0;

/* USER CODE BEGIN PFP */

/* USER CODE END PFP */

/* Private user code ---------------------------------------------------------/
/
USER CODE BEGIN 0 */

/* USER CODE END 0 */

/**

  • @brief The application entry point.
  • @retval int
    /
    int main(void)
    {
    /
    USER CODE BEGIN 1 */

/* USER CODE END 1 */

/* MCU Configuration--------------------------------------------------------*/

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

/* USER CODE BEGIN Init */

/* USER CODE END Init */

/* Configure the system clock */
SystemClock_Config();

/* USER CODE BEGIN SysInit */

/* USER CODE END SysInit */

/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_TIM2_Init();
MX_TIM3_Init();
MX_USART1_UART_Init();
MX_TIM4_Init();
MX_TIM1_Init();

/* Initialize interrupts /
MX_NVIC_Init();
/
USER CODE BEGIN 2 */

/* USER CODE END 2 */

/* Infinite loop /
/
USER CODE BEGIN WHILE /
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_TIM1_Init();
MX_TIM3_Init();
MX_USART1_UART_Init();
MX_TIM2_Init();
/
USER CODE BEGIN WHILE */

printf("串口通信测试\r\n");
HAL_TIM_Base_Start_IT(&htim2); // 使能定时器及其更新中断
HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_1); // 使能定时器及其PWM输出
HAL_TIM_IC_Start_IT(&htim1, TIM_CHANNEL_1);       // 使能定时器及其输入捕获
HAL_TIM_IC_Start_IT(&htim1, TIM_CHANNEL_2);       // 使能定时器及其输入捕获
__HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_1, 10); // 设置一个PWM波形进行测量
 
while (1)
{
    // 串口发送 频率 占空比
    printf("Cap_val1 is :%d ,  Cap_val2 is : %d \r\n", Cap_val1, Cap_val2);
    printf("Duty is :%0.2f%% Frequency is : %0.2f ms\r\n", Duty, Frequency);
    HAL_Delay(1000);
}

}
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *tim)
{
if (tim == &htim2)
{
HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_13);
}
}

// 定时输入捕获回调函数 计算占空比和频率
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
{
if (htim->Instance == TIM1)
{
if (htim->Channel == HAL_TIM_ACTIVE_CHANNEL_1)
{
Cap_val1 = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_1);
}
if (htim->Channel == HAL_TIM_ACTIVE_CHANNEL_2)
{
Cap_val2 = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_2);
Duty = 100 - (float)Cap_val2 / (float)Cap_val1 * 100;
Frequency = 0.001 * Cap_val1;
}
}
}

void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};

/** Initializes the RCC Oscillators according to the specified parameters

  • in the RCC_OscInitTypeDef structure.
    */
    RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
    RCC_OscInitStruct.HSEState = RCC_HSE_ON;
    RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;
    RCC_OscInitStruct.HSIState = RCC_HSI_ON;
    RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
    RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
    RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;
    if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
    {
    Error_Handler();
    }

/** Initializes the CPU, AHB and APB buses clocks
*/
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
{
Error_Handler();
}
}

/**

  • @brief NVIC Configuration.
  • @retval None
    /
    static void MX_NVIC_Init(void)
    {
    /
    TIM2_IRQn interrupt configuration */
    HAL_NVIC_SetPriority(TIM2_IRQn, 0, 0);
    HAL_NVIC_EnableIRQ(TIM2_IRQn);
    }

/* USER CODE BEGIN 4 */

/* USER CODE END 4 */

/**

  • @brief This function is executed in case of error occurrence.
  • @retval None
    /
    void Error_Handler(void)
    {
    /
    USER CODE BEGIN Error_Handler_Debug /
    /
    User can add his own implementation to report the HAL error return state /
    __disable_irq();
    while (1)
    {
    }
    /
    USER CODE END Error_Handler_Debug */
    }

#ifdef USE_FULL_ASSERT
/**

  • @brief Reports the name of the source file and the source line number
  •     where the assert_param error has occurred.
    
  • @param file: pointer to the source file name
  • @param line: assert_param error line source number
  • @retval None
    */
    void assert_failed(uint8_t file, uint32_t line)
    {
    /
    USER CODE BEGIN 6 /
    /
    User can add his own implementation to report the file name and line number,
    ex: printf(“Wrong parameters value: file %s on line %d\r\n”, file, line) /
    /
    USER CODE END 6 /
    }
    #endif /
    USE_FULL_ASSERT */`

烧录进去

在这里插入图片描述

   where the assert_param error has occurred.
  • @param file: pointer to the source file name
  • @param line: assert_param error line source number
  • @retval None
    */
    void assert_failed(uint8_t file, uint32_t line)
    {
    /
    USER CODE BEGIN 6 /
    /
    User can add his own implementation to report the file name and line number,
    ex: printf(“Wrong parameters value: file %s on line %d\r\n”, file, line) /
    /
    USER CODE END 6 /
    }
    #endif /
    USE_FULL_ASSERT */`

烧录进去

在这里插入图片描述
在这里插入图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值