状态机介绍
去抖
直接延时会占用处理机的执行时间,降低处理机的利用效率。工程应用中常用状态机和定时中断消抖
状态机设计思想
把一个过程分为若干状态直接的切换,这些状态之间又有一定的联系
任务
以stm32f411ceu6为例
测量外部脉冲要求: 利用按键PA0触发外部脉冲,按键每按下一次,就利用PA6引脚发送一个周期为2ms左右的脉冲,送到定时器2的外部触发引脚ETR(PA5)进行计数,并将计数结果通过串口发送到PC上显示。
工程配置
TIM10配置:
TIM2配置:
记住:一定要用杜邦线将PA5和PA6连接!不然PA5都接不到PA6的脉冲,计数没有意义
代码实现
/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
typedef enum
{
KEY_CHECK=0,//按键检测状态
KEY_COMFIRM,//按键确认状态
KEY_RELEASE//按键释放状态
}KEY_STATE;//定义三种按键状态
/* USER CODE END PTD */
/* USER CODE BEGIN PV */
KEY_STATE KeyState=KEY_CHECK;
uint8_t KeyFlag=0;//按键有效值标志:1——有效,0——无效
uint8_t Result=0;
/* USER CODE END PV */
/* USER CODE BEGIN 2 */
HAL_TIM_Base_Start_IT(&htim10);//开启定时器10中断
HAL_TIM_Base_Start(&htim2);//开启定时器2
printf ("TIMER COUNTER:\r\n");
/* USER CODE END 2 */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
if(KeyFlag==1)//检测按键标志
{
KeyFlag = 0;//清除标志
HAL_GPIO_TogglePin (GPIOC ,GPIO_PIN_13);
//发送一个周期为2ms左右的脉冲
HAL_GPIO_WritePin (GPIOA ,GPIO_PIN_6 ,GPIO_PIN_SET );
HAL_Delay (1);
HAL_GPIO_WritePin (GPIOA ,GPIO_PIN_6 ,GPIO_PIN_RESET );
HAL_Delay (1);
Result = __HAL_TIM_GetCounter(&htim2);
//获取计数器当前计数值
printf ("Count=%d.\r\n",Result);//发送至PC
}
}
/* USER CODE END 3 */
状态机实现
/* USER CODE BEGIN 4 */
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)//回调函数
{
if(htim->Instance == TIM10 )
{
switch(KeyState)
{
case KEY_CHECK :
{
if(HAL_GPIO_ReadPin (GPIOA,GPIO_PIN_0 )==GPIO_PIN_RESET)
{
KeyState = KEY_COMFIRM;
}
break ;
}
case KEY_COMFIRM :
{
if(HAL_GPIO_ReadPin (GPIOA,GPIO_PIN_0 )==GPIO_PIN_RESET)
{
KeyState = KEY_RELEASE ;
KeyFlag = 1;
}
else
{
KeyState = KEY_CHECK ;
}
break ;
}
case KEY_RELEASE :
{
if(HAL_GPIO_ReadPin (GPIOA,GPIO_PIN_0 )==GPIO_PIN_SET)
{
KeyState = KEY_CHECK ;
}
break ;
}
default :break ;
}
}
}
int fputc(int ch,FILE *f)
{
HAL_UART_Transmit (&huart2 ,(uint8_t *)&ch,1,HAL_MAX_DELAY);
return ch;
}//printf函数重定义
/* USER CODE END 4 */
效果: