复刻江协激光触发器
1、初始化硬件
- 将
PB8
和PB9
分别设为SCK
与SDA
端的接口
注意:江协的OLED驱动为软件模拟
IIC
所以不要使能IIC
模块
- 使能
RCC
,改为外部晶振
- 将
PA9
设为GPIO_EXTI
,接入激光模块的D0
端并使能GPIO
的外部中断
- 在
main.c
中初始化OLED
/* USER CODE BEGIN 2 */OLED_Init();OLED_Clear();
2、设置中断处理
- 在
stm32f1xx_it.c
中定义变量count
,用于记录传感器遮挡次数
/* USER CODE BEGIN PFP */
uint16_t count = 0;
/* USER CODE END PFP */
- 在
stm32f1xx_it.c
的外设中断处理函数中写入以下内容:
/******************************************************************************/
/* STM32F1xx 外设中断处理 */
/* 在这里加上外设中断的处理 */
/* 关于可使用的外设名称, */
/* 请对照相应启动文件 (startup_stm32f1xx.s). */
/******************************************************************************//*** @brief 这个函数用于处理外部中断 line[9:5] */
void EXTI9_5_IRQHandler(void)
{/* USER CODE BEGIN EXTI9_5_IRQn 0 */if(__HAL_GPIO_EXTI_GET_FLAG(GPIO_PIN_9)){/* USER CODE END EXTI9_5_IRQn 0 */HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_9);/* USER CODE BEGIN EXTI9_5_IRQn 1 */count++;}/* USER CODE END EXTI9_5_IRQn 1 */
}
注意,由于
count
变量位于stm32f1xx_it.c
文件,所以读取变量值需要额外定义函数GetCounter
,并在stm32f1xx_it.h
中声明该函数
/* USER CODE BEGIN EFP */
uint16_t GetCounter(void);
/* USER CODE BEGIN 1 */
/** @brief 用于返回遮挡计数值* @retval 计数器的数值
*/
uint16_t GetCounter(void){return count;
}
3、打印内容
- 在主循环外写入该代码:
OLED_ShowString(1, 1, "count:");/* USER CODE END 2 */
- 在主循环内写入以下内容
while (1){OLED_ShowNum(2, 1, GetCounter(), 5);/* USER CODE END WHILE */
4、消除抖动
- 在烧录并运行代码后,能发现显示的数字偶尔会突然增加很多,因此需要将信号消抖
由于处理中断的函数位于
stm32f1xx_it.c
中,所以单片机执行到HAL_GetTick();
会卡死,导致无法利用HAL_Delay(uint8_t Delay)
函数进行延时消抖
- 在
stm32f1xx_it.h
中声明函数MyDelay(uint16_t time)
,并在对应源文件中进行定义
void MyDelay(uint16_t times);
/* USER CODE END EFP */
void MyDelay(uint16_t time){while(time--){;}
}
原理:使单片机做大数字的减法运算,达到延时效果
- 在中断处理函数中添加延时函数(注意不要把数字设的过大)
void EXTI9_5_IRQHandler(void)
{/* USER CODE BEGIN EXTI9_5_IRQn 0 */if(__HAL_GPIO_EXTI_GET_FLAG(GPIO_PIN_9)){/* USER CODE END EXTI9_5_IRQn 0 */HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_9);/* USER CODE BEGIN EXTI9_5_IRQn 1 */MyDelay(1000);count++;}/* USER CODE END EXTI9_5_IRQn 1 */
}