图片:
点击ACCESS project from MCU
然后选择芯片类型
图片:
在 Pinout&Configuration—System Core中:
设置时钟RCC的HSE(外部高速时钟)为晶振模式:
Crystal/ceramic Resonator:
设置系统SYS的Debug为Serial Wire(SWD调试):
在 Pinout&Configuration—Connectivity中:
打开UART1,配置工作模式,在NVIC选项中勾选使能
打开TIM2,配置工作模式,在NVIC选项中勾选使能
注意箭头,点击选择no check
Tips:最好把Linker Settings中的Minimum Heap Size设置为0x600。
最后点击GENERATE CODE代码就生成了:
至此,一个工程就创建完了。
printf重定义
见上一贴
中断函数处理
在tim.c文件中添加如下代码
/* USER CODE BEGIN 1 */
void TIM2_IRQHandler(void)
{
HAL_TIM_IRQHandler(&TIM2_Handler);//定时器共用处理函数
}
uint8_t TIM2CH1_CAPTURE_STA=0; //输入捕获状态
uint32_t TIM2CH1_CAPTURE_VAL; //输入捕获值(TIM2/TIM5是32位)
//定时器更新中断(计数溢出)中断处理回调函数, 该函数在HAL_TIM_IRQHandler中会被调用
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)//更新中断(溢出)发生时执行
{
if((TIM2CH1_CAPTURE_STA&0X80)==0)//还未成功捕获
{
if(TIM2CH1_CAPTURE_STA&0X40)//已经捕获到高电平了
{
if((TIM2CH1_CAPTURE_STA&0X3F)==0X3F)//高电平太长了
{
TIM2CH1_CAPTURE_STA|=0X80; //标记成功捕获了一次
TIM2CH1_CAPTURE_VAL=0XFFFFFFFF;
}
else TIM2CH1_CAPTURE_STA++;
}
}
}
//定时器输入捕获中断处理回调函数,该函数在HAL_TIM_IRQHandler中会被调用
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)//捕获中断发生时执行
{
if((TIM2CH1_CAPTURE_STA&0X80)==0)//还未成功捕获
{
if(TIM2CH1_CAPTURE_STA&0X40) //捕获到一个下降沿
{
TIM2CH1_CAPTURE_STA|=0X80; //标记成功捕获到一次低电平脉宽
TIM2CH1_CAPTURE_VAL=HAL_TIM_ReadCapturedValue(&htim2,TIM_CHANNEL_1);//获取当前的捕获值.
long long temp=0;
temp=TIM2CH1_CAPTURE_STA&0X3F;
temp*=0XFFFFFFFF; //溢出时间总和
temp+=TIM2CH1_CAPTURE_VAL; //得到总的高电平时间
temp=temp*17/1000;
printf("distence:%lld cm\r\n",temp);//打印总的高点平时间
__HAL_TIM_DISABLE(&htim2); //关闭定时器2
}
else //还未开始,第一次捕获上升沿
{
TIM2CH1_CAPTURE_STA=0; //清空
TIM2CH1_CAPTURE_VAL=0;
TIM2CH1_CAPTURE_STA|=0X40; //标记捕获到了上升沿
__HAL_TIM_DISABLE(&htim2); //关闭定时器2
__HAL_TIM_SET_COUNTER(&htim2,0);
TIM_RESET_CAPTUREPOLARITY(&htim2,TIM_CHANNEL_1); //一定要先清除原来的设置!!
TIM_SET_CAPTUREPOLARITY(&htim2,TIM_CHANNEL_1, TIM_ICPOLARITY_FALLING);//定时器2通道1设置为上下降沿捕获
__HAL_TIM_ENABLE(&htim2);//使能定时器5
}
}
}
/* USER CODE END 1 */
最后直接在main.c中添加
/* 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 */
extern uint8_t TIM2CH1_CAPTURE_STA; //输入捕获状态
extern uint32_t TIM2CH1_CAPTURE_VAL; //输入捕获值(TIM2/TIM5是32位)
/* USER CODE END PV */
/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(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 */
long long temp=0;
/* 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_TIM3_Init();
MX_TIM2_Init();
MX_USART1_UART_Init();
/* USER CODE BEGIN 2 */
HAL_TIM_PWM_Start(&htim3,TIM_CHANNEL_1);
printf("\n\r ====================================================================\n\r");
printf("\n\r FS-STM32F407IGT开发板 输入捕获实验 \n\r");
HAL_TIM_IC_Start_IT(&htim2,TIM_CHANNEL_1); //开启TIM2的捕获通道1,并且开启捕获中断
__HAL_TIM_ENABLE_IT(&htim2,TIM_IT_UPDATE); //使能更新中断
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1, GPIO_PIN_SET);
HAL_Delay(1);
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1, GPIO_PIN_RESET);
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{if(TIM2CH1_CAPTURE_STA&0X80) //成功捕获到了一次低电平
{
HAL_Delay(1000);
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1, GPIO_PIN_SET);
HAL_Delay(1);
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1, GPIO_PIN_RESET);
__HAL_TIM_SET_COUNTER(&htim2,0);
TIM_RESET_CAPTUREPOLARITY(&htim2,TIM_CHANNEL_1); //一定要先清除原来的设置!!
TIM_SET_CAPTUREPOLARITY(&htim2,TIM_CHANNEL_1,TIM_ICPOLARITY_RISING);//定时器2通道1设置为上升沿捕获
__HAL_TIM_ENABLE(&htim2);//使能定时器2
TIM2CH1_CAPTURE_STA=0;
}
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
配套代码
相关函数
设置输入捕获极性以及清除输入捕获极性设置
TIM_RESET_CAPTUREPOLARITY(&TIM5_Handler,TIM_CHANNEL_1);//清除极性设置
TIM_SET_CAPTUREPOLARITY(&TIM5_Handler,TIM_CHANNEL_1,TIM_ICPOLARITY_FALLING);//定时器 5 通道 1 设置为下降沿捕获
__HAL_TIM_ENABLE(); //开启定时器
__HAL_TIM_ENABLE_IT(&TIM5_Handler,TIM_IT_UPDATE); //使能定时器更新中断
HAL_StatusTypeDef HAL_TIM_IC_Start_IT (TIM_HandleTypeDef *htim, uint32_t Channel);//同时用来开启定时器的输入捕获通道和使能捕获中断
HAL_StatusTypeDef HAL_TIM_IC_Start (TIM_HandleTypeDef *htim, uint32_t Channel);//,只是开启输入捕获功能
回调函数
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim);//更新(溢出)中断
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim);//捕获中断
以测量脉宽为例
通道一设置为上升沿捕获,t1时事件发生,我们记下此时的计数值然后立即清除计数值重新开始计数并设置通道二为下降沿捕获,t2时事件触发记下此时的计数值
CNT计数的次数等于:N*ARR+CCRx2,有了这个计数次数,再乘以 CNT 的计数周期,即可得到 t2-t1 的时间长度,即高电平持续时间
源码分析
打开cube生成工程定位到time.c文件
/* TIM2 init function */
void MX_TIM2_Init(void)
{
TIM_ClockConfigTypeDef sClockSourceConfig = {0};
TIM_MasterConfigTypeDef sMasterConfig = {0};
TIM_IC_InitTypeDef sConfigIC = {0};
htim2.Instance = TIM2;
htim2.Init.Prescaler = 84;
htim2.Init.CounterMode = TIM_COUNTERMODE_UP;
htim2.Init.Period = 0xffffffff;
htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
htim2.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
if (HAL_TIM_Base_Init(&htim2) != HAL_OK)
{
Error_Handler();
}
sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
if (HAL_TIM_ConfigClockSource(&htim2, &sClockSourceConfig) != HAL_OK)
{
Error_Handler();
}
if (HAL_TIM_IC_Init(&htim2) != HAL_OK)
{
Error_Handler();
}
sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
if (HAL_TIMEx_MasterConfigSynchronization(&htim2, &sMasterConfig) != HAL_OK)
{
Error_Handler();
}
sConfigIC.ICPolarity = TIM_INPUTCHANNELPOLARITY_RISING;
sConfigIC.ICSelection = TIM_ICSELECTION_DIRECTTI;
sConfigIC.ICPrescaler = TIM_ICPSC_DIV1;
sConfigIC.ICFilter = 0;
if (HAL_TIM_IC_ConfigChannel(&htim2, &sConfigIC, TIM_CHANNEL_1) != HAL_OK)
{
Error_Handler();
}
}
我们可以看到定时器定时部分初始化和输入捕获初始化与cube设置相对应