[资料分享] STM32F103C8 旋转编码器 控制PWM 软件代码

lange98   2023-3-23 10:30 楼主

//encoder.h 如下

#ifndef __ENCODER_H
#define __ENCODER_H     
#include "sys.h"
#include "delay.h"

#define ENCODER_PORT_A    GPIOA        //定义IO接口组
#define ENCODER_L    GPIO_Pin_6    //定义IO接口
#define ENCODER_D    GPIO_Pin_7    //定义IO接口

#define ENCODER_PORT_B    GPIOB        //定义IO接口组
#define ENCODER_R    GPIO_Pin_2    //定义IO接口


void ENCODER_Init(void);//初始化
u8 ENCODER_READ(void);
void ENCODER_CTL(void);
void ENCODER_pwmctl_w(void);
void ENCODER_pwmctl_f(void);    
void ENCODER_TIM4_pwmctl_w(void);
#endif

//    1     GPIO_WriteBit(LEDPORT,LED1,(BitAction)(1)); LED1接口输出高电平1
//          GPIO_WriteBit(LEDPORT,LED1,(BitAction)(1-GPIO_ReadOutputDataBit(LEDPORT,LED1)));取反LED1
//    2     GPIO_SetBits(LEDPORT,LED1); 
//    3     GPIO_ResetBits(LEDPORT,LED1);
//    4     GPIO_Write(LEDPORT,0x0001); 直接数值操作将变量值写入LED
//选择IO接口工作方式:
//GPIO_Mode_AIN 模拟输入
//GPIO_Mode_IN_FLOATING 浮空输入
//GPIO_Mode_IPD 下拉输入
//GPIO_Mode_IPU 上拉输入
//GPIO_Mode_Out_PP 推挽输出
//GPIO_Mode_Out_OD 开漏输出
//GPIO_Mode_AF_PP 复用推挽输出
//GPIO_Mode_AF_OD 复用开漏输出

 

//encoder.c 如下

#include "encoder.h"
#include "touch_key.h"
#include "delay.h"
#include "usart.h"
#include "oled0561.h"
#include "flash.h"
#include "pwm.h"
#define FLASH_START_ADDR  0x0801f000      //写入的起始地址#define FLASH_START_ADDR  0x0801f000      //写入的起始地址
#define FLASH_data2_ADDR  0x0801f010      
#define FLASH_data3_ADDR  0x0801f100

u8 KUP;//旋钮锁死标志(1为锁死)
u16 cou;
void ENCODER_Init(void)
{ //接口初始化
        GPIO_InitTypeDef  GPIO_InitStructure; //定义GPIO的初始化枚举结构    
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOC,ENABLE);       
        GPIO_InitStructure.GPIO_Pin = ENCODER_L | ENCODER_D; //选择端口号                        
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //选择IO接口工作方式 //上拉电阻       
        GPIO_Init(ENCODER_PORT_A,&GPIO_InitStructure);    
        GPIO_InitStructure.GPIO_Pin = ENCODER_R; //选择端口号                        
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //选择IO接口工作方式 //上拉电阻       
        GPIO_Init(ENCODER_PORT_B,&GPIO_InitStructure);                
}
u8 ENCODER_READ(void){ //接口初始化
    u8 a;//存放按键的值
    u8 kt;
    a=0;
    if(GPIO_ReadInputDataBit(ENCODER_PORT_A,ENCODER_L))KUP=0;    //判断旋钮是否解除锁死
    if(!GPIO_ReadInputDataBit(ENCODER_PORT_A,ENCODER_L)&&KUP==0){ //判断是否旋转旋钮,同时判断是否有旋钮锁死
        delay_us(100);
        kt=GPIO_ReadInputDataBit(ENCODER_PORT_B,ENCODER_R);    //把旋钮另一端电平状态记录
        delay_ms(3); //延时
        if(!GPIO_ReadInputDataBit(ENCODER_PORT_A,ENCODER_L)){ //去抖
            if(kt==0){ //用另一端判断左或右旋转
                a=1;//右转
            }else{
                a=2;//左转
            }
            cou=0; //初始锁死判断计数器
            while(!GPIO_ReadInputDataBit(ENCODER_PORT_A,ENCODER_L)&&cou<60000){ //等待放开旋钮,同时累加判断锁死
                cou++;KUP=1;delay_us(20); //
            }
        }
    }
    if(!GPIO_ReadInputDataBit(ENCODER_PORT_A,ENCODER_D)&&KUP==0)
        { //判断旋钮是否按下  
            delay_ms(20);
            if(!GPIO_ReadInputDataBit(ENCODER_PORT_A,ENCODER_D))
            { //去抖动
            
            a=3;//在按键按下时加上按键的状态值
            
            while(GPIO_ReadInputDataBit(ENCODER_PORT_A,ENCODER_D)==0)
                ;    //等等旋钮放开
                delay_ms(10);
            }
    }
    return a;

void ENCODER_CTL(void)
{
  u8 b=0;
    u16 c=150;
    u16 k;
  k = FLASH_R(FLASH_START_ADDR);//从指定页的地址读FLASH
    b=ENCODER_READ();    //读出旋转编码器值    
    if(b==1)//分析按键值,并加减计数器值。
     {
            k++;
          if(k>=c)k=0;
          printf("右转   %d \r\n",k); 
          } 
    if(b==2)
       { 
              k--;
            if(k==0)
            k=c;
              printf("左转   %d \r\n",k);
           }
  if(b==3)k=75, printf("OK %d \r\n",k);
    if(b!=0)//如果有旋转器的操作
        { 
      OLED_DISPLAY_8x16(6,13*8,k/100+0x30);
            OLED_DISPLAY_8x16(6,14*8,k%100/10+0x30);
          OLED_DISPLAY_8x16(6,15*8,k%100%10+0x30);
            FLASH_W(FLASH_START_ADDR,k);
        }
}


void ENCODER_pwmctl_w(void)
{
  u8 b=0;
    u16 c=140;
    u16 t1pwm_w;
  t1pwm_w = FLASH_R(FLASH_data2_ADDR);//从指定页的地址读FLASH
    b=ENCODER_READ();    //读出旋转编码器值    
    if(b==1)//分析按键值,并加减计数器值。
     {
            t1pwm_w++;
          if(t1pwm_w>=c)t1pwm_w=10;
          printf("右转   %d \r\n",t1pwm_w); 
          } 
    if(b==2)
       { 
              t1pwm_w--;
            if(t1pwm_w<=10)
            t1pwm_w=c;
              printf("左转   %d \r\n",t1pwm_w);
           }
  if(b==3)t1pwm_w=72,
             printf("OK %d \r\n",t1pwm_w);
            
    if(b!=0)//如果有旋转器的操作
        { 
      OLED_DISPLAY_8x16(6,13*8,t1pwm_w/100+0x30);
            OLED_DISPLAY_8x16(6,14*8,t1pwm_w%100/10+0x30);
          OLED_DISPLAY_8x16(6,15*8,t1pwm_w%100%10+0x30);
            FLASH_W(FLASH_data2_ADDR,t1pwm_w);
            
        TIM1_2PWM_Init( 144,0);
            TIM_SetCompare1(TIM1,t1pwm_w);
            TIM_SetCompare3(TIM1,t1pwm_w);
        }
}
void ENCODER_TIM4_pwmctl_w(void)
{
  u8 b=0;
    u16 c=720;
    u16 t4pwm_w;
  t4pwm_w = FLASH_R(FLASH_data2_ADDR);//从指定页的地址读FLASH
    b=ENCODER_READ();    //读出旋转编码器值    
    if(b==1)//分析按键值,并加减计数器值。
     {
            t4pwm_w++;
          if(t4pwm_w>=c)t4pwm_w=10;
          printf("右转   %d \r\n",t4pwm_w); 
          } 
    if(b==2)
       { 
              t4pwm_w--;
            if(t4pwm_w<=10)
            t4pwm_w=c;
              printf("左转   %d \r\n",t4pwm_w);
           }
  if(b==3)t4pwm_w=360,
             printf("OK %d \r\n",t4pwm_w);
            
    if(b!=0)//如果有旋转器的操作
        { 
      OLED_DISPLAY_8x16(6,13*8,t4pwm_w/100+0x30);
            OLED_DISPLAY_8x16(6,14*8,t4pwm_w%100/10+0x30);
          OLED_DISPLAY_8x16(6,15*8,t4pwm_w%100%10+0x30);
            FLASH_W(FLASH_data2_ADDR,t4pwm_w);
            
        TIM4_PWM_Init( 720,0);
            TIM_SetCompare3(TIM4,t4pwm_w);
        }
}


void ENCODER_pwmctl_f(void)
{
  u8 b=0;
    u16 c=654;
    u16 t1pwm_f;
  t1pwm_f = FLASH_R(FLASH_data2_ADDR);//从指定页的地址读FLASH
    b=ENCODER_READ();    //读出旋转编码器值    
    if(b==1)//分析按键值,并加减计数器值。
     {
            t1pwm_f++;
          if(t1pwm_f>=c)t1pwm_f=343;
//      TIM_SetCompare3(TIM3,k);
//            TIM3_PWM_Init(pwm_f,0);
          printf("右转   %d \r\n",t1pwm_f); 
//            OLED_DISPLAY_8x16(6,13*8,k/100+0x30);
//            OLED_DISPLAY_8x16(6,14*8,k%100/10+0x30);
//          OLED_DISPLAY_8x16(6,15*8,k%100%10+0x30);
            
              
          } 
    if(b==2)
       { 
              t1pwm_f--;
            if(t1pwm_f==343)
            t1pwm_f=c;
//      TIM_SetCompare3(TIM3,k);
//            TIM3_PWM_Init(pwm_f,0);
              printf("左转   %d \r\n",t1pwm_f);
//                OLED_DISPLAY_8x16(6,13*8,k/100+0x30);
//              OLED_DISPLAY_8x16(6,14*8,k%100/10+0x30);
//            OLED_DISPLAY_8x16(6,15*8,k%100%10+0x30);
           }
  if(b==3)t1pwm_f=600,
             printf("OK %d \r\n",t1pwm_f);
            
    if(b!=0)//如果有旋转器的操作
        { 
      OLED_DISPLAY_8x16(6,13*8,t1pwm_f/100+0x30);
            OLED_DISPLAY_8x16(6,14*8,t1pwm_f%100/10+0x30);
          OLED_DISPLAY_8x16(6,15*8,t1pwm_f%100%10+0x30);
            FLASH_W(FLASH_data2_ADDR,t1pwm_f);
            
        TIM1_2PWM_Init( t1pwm_f,0);
            TIM_SetCompare1(TIM1,t1pwm_f/2);
        }
}


希望对你有帮助。。。。

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

回复评论 (2)

建议使用高级模式,那边有个插入代码,使用插入代码功能就会看的更清晰一点

希望做一些大家觉得好用的东西!
点赞  2023-3-23 22:33

如此简单的一个功能,搞得如此复杂。

有专用的函数和功能为社么不用。

 

چوآن شـين
点赞  2023-3-27 08:51
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 京公网安备 11010802033920号
    写回复