STM32数字编码旋钮的使用,控制LED灯
废话不多说,直接先上程序,后面补充使用中的问题,网上能找到的很多资料要不不好理解,其中有一种会出现死锁的问题,要略加修改,这里是已经修改完成的。这里是调节速度的旋钮,用8个led灯代表8个档位。
用外部中断,上升沿和下降沿都进中断
exti.c
#include "exti.h"
u8 SP_flag;//速度旋钮A口为低电平
u8 Current_SP_status;//当前速度状态
extern int led_SP;//速度LED
//初始化
void My_EXTI_Init(void)
NVIC_InitTypeDef NVIC_InitStructure;
EXTI_InitTypeDef EXTI_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE)
GPIO_EXTILineConfig(GPIO_PortSourceGPIOC, GPIO_PinSource6);
//EXTI9_5 NVIC配置
NVIC_InitStructure.NVIC_IRQChannel = EXTI9_5_IRQn;//exti9_5中断通道
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=2;//抢占优先级
NVIC_InitStructure.NVIC_IRQChannelSubPriority =3; //子优先级
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IQR通道使能
NVIC_Init(&NVIC_InitStructure); //根据指定的参数舒适化NVIC寄存器
//配置线路
EXTI_InitStructure.EXTI_Line=EXTI_Line6;
EXTI_InitStructure.EXTI_Mode=EXTI_Mode_Interrupt;
EXTI_InitStructure.EXTI_Trigger= EXTI_Trigger_Rising_Falling;//上升沿下降沿都触发中断
EXTI_InitStructure.EXTI_LineCmd=ENABLE;
EXTI_Init(&EXTI_InitStructure);
void EXTI9_5_IRQHandler(void)
{
if(EXTI_GetITStatus(EXTI_Line6)==1)
{if(SP_Adj_A==1) //A脚为高电平 读取B脚 如果为1则正转 为0反转
{
Current_SP_status=SP_Adj_B; //读取B的状态
SP_flag=1; // //A为高标志位
if(SP_flag==1)
{
SP_flag=0; //
if(Current_SP_status==1) //正转 下面写要实现的程序就行(底下的正转也要写)
{
led_SP++;
if(led_SP==9)
{
led_SP=8;
}
}
else if(Current_SP_status==0) //反转 下面写要实现的程序就行(底下的反转也要写)
{
led_SP--;
if(led_SP==0)
{
led_SP=1;
}
}
}
}
if(SP_Adj_A==0) //A脚为低电平 读取B脚 如果为0则正转 为1反转
{
Current_SP_status=SP_Adj_B;
SP_flag=1;
if(SP_flag==1)
{
SP_flag=0; //
if(Current_SP_status==0) //正转
{
led_SP++;
if(led_SP==9)
{
led_SP=8;
}
}
else if(Current_SP_status==1) //反转
{
led_SP--;
if(led_SP==0)
{
led_SP=1;
}
}
}
}
}
EXTI_ClearITPendingBit(EXTI_Line6 );
}
exti.h文件
#ifndef _exti_H
#define _exti_H
#include "system.h"
void My_EXTI_Init(void);
#endif
main.c文件
#include "system.h"
#include "SP.h"
#include "exti.h"
u8 led_SP=1;//led SP标志位
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
My_EXTI_Init();
TIM3_Init(10,36000-1);//5ms
SP_Init();
while(1)
{
switch(led_SP)
{
case(1):
SP_A_L;SP_B_L;SP_C_H; break;//
case(2):
SP_A_H;SP_B_L;SP_C_H; break;//
case(3):
SP_A_L;SP_B_H;SP_C_H; break;//
case(4):
SP_A_H ;SP_B_H;SP_C_H; break;//
case(5):
SP_A_L;SP_B_L;SP_C_L; break;//
case(6):
SP_A_H;SP_B_L;SP_C_L; break;//
case(7):
SP_A_L;SP_B_H;SP_C_L; break;//
case(8):
SP_A_H;SP_B_H;SP_C_L; break;//
}
}
SP.c
#include "SP.h"
#include "system.h"
void SP_Init()
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(SP_PROT_RCC,ENABLE);
GPIO_InitStructure.GPIO_Pin=SP_A_PIN;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(SP_A_PORT,&GPIO_InitStructure);
GPIO_SetBits(SP_A_PORT,SP_A_PIN);
GPIO_InitStructure.GPIO_Pin=SP_B_PIN;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(SP_B_PORT,&GPIO_InitStructure);
GPIO_SetBits(SP_B_PORT,SP_B_PIN);
GPIO_InitStructure.GPIO_Pin=SP_C_PIN;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(SP_C_PORT,&GPIO_InitStructure);
GPIO_SetBits(SP_C_PORT,SP_C_PIN);
}
SP.h
#ifndef _SP_H
#define _SP_H
#include "system.h"
#define SP_A_PIN GPIO_Pin_12
#define SP_A_PORT GPIOC
#define SP_PROT_RCC RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOD|RCC_APB2Periph_GPIOC
#define SP_B_PIN GPIO_Pin_2
#define SP_B_PORT GPIOD
#define SP_C_PIN GPIO_Pin_3
#define SP_C_PORT GPIOB
#define SP_A_H GPIO_SetBits(SP_A_PORT, SP_A_PIN)
#define SP_A_L GPIO_ResetBits(SP_A_PORT, SP_A_PIN)
#define SP_B_H GPIO_SetBits(SP_B_PORT, SP_B_PIN)
#define SP_B_L GPIO_ResetBits(SP_B_PORT, SP_B_PIN)
#define SP_C_H GPIO_SetBits(SP_C_PORT, SP_C_PIN)
#define SP_C_L GPIO_ResetBits(SP_C_PORT, SP_C_PIN)
void SP_Init(void);
#endif
这里讲一下过程中容易出现的问题,在学习的教程中只判断A口低电平时候B口是上升沿或者下降沿,并且用了while判断A口状态,每两次转旋钮才会出一次状态,但是只转一下,不转第二下的话会出现死锁,所以,这样分两个部分,在A口是高电平和低电平都判断低电平,且不用while语句就不会出现死锁。
另外这里的译码器不是唯一真值表,具体自己的情况自己判断。