> 项目环境Environment

基于以下环境测试所得,不保证完全兼容表格以外的环境,需略作修改

设备/环境版本Version补充说明Description
STM32F103C8T6 /> 波特律动 | kk画的白色板子,颜值很高
Keil uVision55.39.0.0标准库+Keil5开发+VSCode编辑 | Hal库在学习中
OLED驱动1.2> 江协科技 | 同款OLED屏幕,标准库最优选择

> 项目配置list

以下描述了项目结构与说明,点击此处标题可跳转至Github打包下载源码

文件夹补充说明Description
INC存放标准库及项目.h头文件
MDKKeil5项目文件目录
OUTPUT链接中间文件、AXF烧录文件等输出目录
SRE存放主函数及项目其余.c文件

> Keil配置

Project -> Options for Target 填写指南

keil选项填写内容
Output选择目录「OUTPUT」,生成HEX文件
C/C++Define :
USE_STDPERIPH_DRIVER,STM32F10X_MD
Language/ Code Generation :
> C99 mode
Include Paths :
..\INC
..\..\Libraries\CMSIS\CM3\DeviceSupport\ST\STM32F10x
..\..\Libraries\STM32F10x_StdPeriph_Driver\inc
DebugST-Link Debugger – Port : SW

> 测试效果

初始化屏幕出现[Num:00000],旋钮向左递减为负数,向右递增为正数,按压旋钮重置当前状态为00000

> 项目分析

摘取关键内容进行记录、巩固知识点 [右下角标直达Github]

C
#include "stm32f10x.h"
#include "Delay.h"
#include "OLED_Main.h"
#include "EC11.h"

int16_t num = 0;

int main(void)
{
	OLED_Init();
    EC11_Init();

    OLED_ShowString(3, 1, "Num:", OLED_8X16);
    OLED_Update();

    while(1) {
        num += EC11_Get_State();
        OLED_ShowSignedNum(3, 35, num, 5, OLED_8X16);
        OLED_Update();
    }
}
main.c
C
#include "stm32f10x.h"
#include <stm32f10x_exti.h>

int16_t Encoder_Count;  //Global variable - EC11's increment
extern int16_t num;
/**
 * @brief  initialize the EC11
 * @param  None
 * @retval None
*/
void EC11_Init(void)
{
	// 1-init clock
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);

	// 2-init GPIO
	GPIO_InitTypeDef GPIO_InitStructrue;
	GPIO_InitStructrue.GPIO_Mode = GPIO_Mode_IPU;
	GPIO_InitStructrue.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9; // PhaseA - PA8 | PhaseB - PA9
	GPIO_InitStructrue.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &GPIO_InitStructrue);

	GPIO_InitStructrue.GPIO_Mode = GPIO_Mode_IPU;
	GPIO_InitStructrue.GPIO_Pin = GPIO_Pin_15; // Key - PB15
	GPIO_InitStructrue.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOB, &GPIO_InitStructrue);

	// 3-init EXTI
	GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource8);
	GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource9);
	GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource15);

	EXTI_InitTypeDef EXTI_InitStructrue;
	EXTI_InitStructrue.EXTI_Line = EXTI_Line8 | EXTI_Line9 | EXTI_Line15;
	EXTI_InitStructrue.EXTI_LineCmd = ENABLE;
	EXTI_InitStructrue.EXTI_Mode = EXTI_Mode_Interrupt;
	EXTI_InitStructrue.EXTI_Trigger = EXTI_Trigger_Falling;
	EXTI_Init(&EXTI_InitStructrue);	
	
	// 4-init NVIC
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);

	NVIC_InitTypeDef NVIC_InitStructure;
	NVIC_InitStructure.NVIC_IRQChannel = EXTI9_5_IRQn; // 2 GPIO use same NVIC Channel
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
	NVIC_Init(&NVIC_InitStructure);	

	NVIC_InitStructure.NVIC_IRQChannel = EXTI15_10_IRQn; 
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
	NVIC_Init(&NVIC_InitStructure);
}

/**
 * @brief  Get the increment of EC11
 * @param  None
 * @retval THE INCREMENT
*/
int16_t EC11_Get_State(void)
{
	int16_t Temp;
	Temp = Encoder_Count;
	Encoder_Count = 0;
	return Temp;
}

/**
 * @brief  EXTI9 - EXTI5 Interrupt Requset Handler
 * @param  None
 * @retval None
*/
void EXTI9_5_IRQHandler(void)
{
	if (EXTI_GetITStatus(EXTI_Line9) == SET) { // Case in PhaseB | Left

		if (GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_9) == 0) // Software for jitters elimination

			if (GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_8) == 0) // Check the rotation direction

				Encoder_Count --;

		EXTI_ClearITPendingBit(EXTI_Line9); // Clear the flag
	}

    if (EXTI_GetITStatus(EXTI_Line8) == SET) { // Case in PhaseA | Right
		
		if (GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_8) == 0) // Software for jitters elimination
		
			if (GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_9) == 0) // Check the rotation direction
			
				Encoder_Count ++;
			
		EXTI_ClearITPendingBit(EXTI_Line8); // Clear the flag
	}
}

/**
 * @brief  EXTI15 - EXTI10 Interrupt Requset Handler
 * @param  None
 * @retval None
*/
void EXTI15_10_IRQHandler(void)
{
	if (EXTI_GetITStatus(EXTI_Line15) == SET) { // Case in Press
		
		if (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_15) == 0) // Software for jitters elimination
		
			num = 0;
			
		EXTI_ClearITPendingBit(EXTI_Line15); // Clear the flag
	}
}
EC11.c