【STM8L】STM8L之修正库函数GPIO_WriteBit的Bug

本篇博文最后修改时间:2016年11月18日,02:54。


一、简介

本文修正STM8L的库函数GPIO_WriteBit的Bug


二、实验平台

编译软件:IAR for STM8 1.42.2

硬件平台:stm8l101f3p6开发板

仿真器:ST-LINK

库函数版本:STM8L_STMTouch_Lib_V1.1.0


版权声明

博主:甜甜的大香瓜

声明:喝水不忘挖井人,转载请注明出处。

原文地址:http://blog.csdn.NET/feilusia

联系方式:897503845@qq.com

香瓜BLE之CC2541群:127442605

香瓜BLE之CC2640群:557278427

香瓜BLE之Android群:541462902

香瓜单片机之STM8/STM32群:164311667
甜甜的大香瓜的小店(淘宝店):https://shop217632629.taobao.com/?spm=2013.1.1000126.d21.hd2o8i

四、BUG现象
通过GPIO_WriteBit函数无法控制IO的电平。

五、实验步骤
1、替换GPIO_WriteBit函数(在stm8l10x_gpio.c中)
//******************************************************************************        
//name:             GPIO_WriteBit        
//introduce:        GPIO控制位的函数     
//parameter:        GPIOx: 端口(x = A to D)  
//                  GPIO_Pin: GPIO_Pin_0~GPIO_Pin_7 
//                  GPIO_BitVal: SET or RESET                      
//return:           none      
//author:           甜甜的大香瓜             
//email:            897503845@qq.com         
//QQ group          香瓜单片机之STM8/STM32(164311667)                      
//changetime:       2016.11.18       
//******************************************************************************  
void GPIO_WriteBit(GPIO_TypeDef* GPIOx, GPIO_Pin_TypeDef GPIO_Pin, BitAction GPIO_BitVal)
{
  /* Check the parameters */
  assert_param(IS_GPIO_PIN(GPIO_Pin));
  assert_param(IS_STATE_VALUE(GPIO_BitVal));

  if (GPIO_BitVal != RESET)
  {
    //SetBit(GPIOx->ODR, GPIO_Pin);//BUG语句,GPIO_Pin是按位来定义的,却被SetBit以字节来操作。
    GPIOx->ODR |= GPIO_Pin;    
  }
  else
  {
    //ClrBit(GPIOx->ODR, GPIO_Pin);//BUG语句,GPIO_Pin是按位来定义的,却被SetBit以字节来操作。
    GPIOx->ODR &= (uint8_t)(~GPIO_Pin);    
  }
}

六、实验结果
将函数修正后,IO口能被正常拉高拉低了。
因此,实验成功。




#include "sys.h" void WFI_SET(void) { __ASM volatile("wfi"); } //关闭所有中断 void INTX_DISABLE(void) { __ASM volatile("cpsid i"); } //开启所有中断 void INTX_ENABLE(void) { __ASM volatile("cpsie i"); } //设置栈顶地址 //addr:栈顶地址 __asm void MSR_MSP(u32 addr) { MSR MSP, r0 //set Main Stack value BX r14 } #ifndef __SYS_H #define __SYS_H #include "stm32f10x.h" //0,不支持ucos //1,支持ucos #define SYSTEM_SUPPORT_OS 0 //定义系统文件夹是否支持UCOS //位带操作,实现51类似的GPIO控制功能 //具体实现思想,参考<<CM3权威指南>>第五章(87页~92页). //IO口操作宏定义 #define BITBAND(addr, bitnum) ((addr & 0xF0000000)+0x2000000+((addr &0xFFFFF)<<5)+(bitnum<<2)) #define MEM_ADDR(addr) *((volatile unsigned long *)(addr)) #define BIT_ADDR(addr, bitnum) MEM_ADDR(BITBAND(addr, bitnum)) //IO口地址映射 #define GPIOA_ODR_Addr (GPIOA_BASE+12) //0x4001080C #define GPIOB_ODR_Addr (GPIOB_BASE+12) //0x40010C0C #define GPIOC_ODR_Addr (GPIOC_BASE+12) //0x4001100C #define GPIOD_ODR_Addr (GPIOD_BASE+12) //0x4001140C #define GPIOE_ODR_Addr (GPIOE_BASE+12) //0x4001180C #define GPIOF_ODR_Addr (GPIOF_BASE+12) //0x40011A0C #define GPIOG_ODR_Addr (GPIOG_BASE+12) //0x40011E0C #define GPIOA_IDR_Addr (GPIOA_BASE+8) //0x40010808 #define GPIOB_IDR_Addr (GPIOB_BASE+8) //0x40010C08 #define GPIOC_IDR_Addr (GPIOC_BASE+8) //0x40011008 #define GPIOD_IDR_Addr (GPIOD_BASE+8) //0x40011408 #define GPIOE_IDR_Addr (GPIOE_BASE+8) //0x40011808 #define GPIOF_IDR_Addr (GPIOF_BASE+8) //0x40011A08 #define GPIOG_IDR_Addr (GPIOG_BASE+8) //0x40011E08 //IO口操作,只对单一的IO口! //确保n的值小于16! #define PAout(n) BIT_ADDR(GPIOA_ODR_Addr,n) //输出 #define PAin(n) BIT_ADDR(GPIOA_IDR_Addr,n) //输入 #define PBout(n) BIT_ADDR(GPIOB_ODR_Addr,n) //输出 #define PBin(n) BIT_ADDR(GPIOB_IDR_Addr,n) //输入 #define PCout(n) BIT_ADDR(GPIOC_ODR_Addr,n) //输出 #define PCin(n) BIT_ADDR(GPIOC_IDR_Addr,n) //输入 #define PDout(n) BIT_ADDR(GPIOD_ODR_Addr,n) //输出 #define PDin(n) BIT_ADDR(GPIOD_IDR_Addr,n) //输入 #define PEout(n) BIT_ADDR(GPIOE_ODR_Addr,n) //输出 #define PEin(n) BIT_ADDR(GPIOE_IDR_Addr,n) //输入 #define PFout(n) BIT_ADDR(GPIOF_ODR_Addr,n) //输出 #define PFin(n) BIT_ADDR(GPIOF_IDR_Addr,n) //输入 #define PGout(n) BIT_ADDR(GPIOG_ODR_Addr,n) //输出 #define PGin(n) BIT_ADDR(GPIOG_IDR_Addr,n) //输入 //以下为汇编函数 void WFI_SET(void); //执行WFI指令 void INTX_DISABLE(void);//关闭所有中断 void INTX_ENABLE(void); //开启所有中断 void MSR_MSP(u32 addr); //设置堆栈地址 #endif #include "stm32f10x.h" #include "Delay.h" #include "ps2.h" #include "moto.h" #include "sys.h" #include "encoder.h" #include "pwm.h" #include "gpio.h" #include <math.h> #include "Servo.h" #define PS2_MAX_SPEED 7000 int PS2_KEY; uint32_t system_time = 0; float Target_Left, Actual_Left, Out_Left; float Target_Right, Actual_Right, Out_Right; float Kp = 0.5, Ki = 0.5, Kd = 0.2; float Error0_Left, Error1_Left, Error2_Left; float Error0_Right, Error1_Right, Error2_Right; static float dout_last_Left, dout_last_Right; float dout_Left, dout_Right; int32_t Encoder_Offset[4] = {0}; int main(void) { NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); delay_Init(); Servo_Init(); PS2_Init(); PS2_SetInit(); Gpio_Init(); PWM_Init(7200, 0); Encoder_Init_Tim2(); Encoder_Init_Tim3(); Encoder_Init_Tim4(); Encoder_Init_Tim8(); uint8_t count = 0; do { PS2_SetInit(); delay_ms(100); count++; } while(PS2_RedLight() != 0 && count < 3); while(1) { PS2_KEY = PS2_DataKey(); // 电机控制 switch(PS2_KEY) { case 5: Target_Left = PS2_MAX_SPEED * 2.0f; Target_Right = PS2_MAX_SPEED * 2.0f; break; case 7: Target_Left = -PS2_MAX_SPEED * 2.0f; Target_Right = -PS2_MAX_SPEED * 2.0f; break; case 6: Target_Left = -PS2_MAX_SPEED * 2.0f; Target_Right = PS2_MAX_SPEED * 2.0f; break; case 8: Target_Left = PS2_MAX_SPEED * 2.0f; Target_Right = -PS2_MAX_SPEED * 2.0f; break; case 2: Servo_Start_UP(); break; case 3: Servo_Start_DOWN(); break; default: Target_Left = 0; Target_Right = 0; break; } system_time++; // 编码器读取和PID控制 Encoder_Offset[0] = Read_Encoder(2); Encoder_Offset[1] = Read_Encoder(3); Encoder_Offset[2] = Read_Encoder(4); Encoder_Offset[3] = Read_Encoder(8); Actual_Left = (Encoder_Offset[0] + Encoder_Offset[1]) / 2.0f; Actual_Right = (Encoder_Offset[2] + Encoder_Offset[3]) / 2.0f; // PID计算 Error2_Left = Error1_Left; Error1_Left = Error0_Left; Error0_Left = Target_Left - Actual_Left; // 积分分离 float c_Left; if (fabs(Error0_Left) < 100) { c_Left = 1; } else { c_Left = 0; } // 不完全微分 float alpha = 0.8f; float dout_standard_Left = Kd * (Error0_Left + Error2_Left - 2 * Error1_Left); dout_last_Left = dout_Left; dout_Left = (1 - alpha) * dout_standard_Left + alpha * dout_last_Left; // 设置死区 if (fabs(Error0_Left) < 10) { Out_Left = 0; } else { Out_Left += Kp * (Error0_Left - Error1_Left) + Ki * Error0_Left * c_Left + dout_Left; } if (Out_Left > PS2_MAX_SPEED * 2.0f) { Out_Left = PS2_MAX_SPEED * 2.0f; } if (Out_Left < -PS2_MAX_SPEED * 2.0f) { Out_Left = -PS2_MAX_SPEED * 2.0f; } Error2_Right = Error1_Right; Error1_Right = Error0_Right; Error0_Right = Target_Right - Actual_Right; float c_Right; if (fabs(Error0_Right) < 100) { c_Right = 1; } else { c_Right = 0; } float dout_standard_Right = Kd * (Error0_Right + Error2_Right - 2 * Error1_Right); dout_last_Right = dout_Right; dout_Right = (1 - alpha) * dout_standard_Right + alpha * dout_last_Right; if (fabs(Error0_Right) < 10) { Out_Right = 0; } else { Out_Right += Kp * (Error0_Right - Error1_Right) + Ki * Error0_Right * c_Right + dout_Right; } if (Out_Right > PS2_MAX_SPEED * 2.0f) { Out_Right = PS2_MAX_SPEED * 2.0f; } if (Out_Right < -PS2_MAX_SPEED * 2.0f) { Out_Right = -PS2_MAX_SPEED * 2.0f; } // 电机输出 motor_SetSpeed1((int16_t)Out_Left); motor_SetSpeed2((int16_t)Out_Left); motor_SetSpeed3((int16_t)Out_Right); motor_SetSpeed4((int16_t)Out_Right); delay_ms(10); } } #include "stm32f10x.h" #include "Servo.h" #include "delay.h" SERVO_PARAM Servo = {1500, 500, 1500, 2000, 5}; void Servo_Init(void) { Servo_Gpio_Init(); delay_ms(10); Servo_Time_Init(); delay_ms(10); Servo_Pwm_Set(Servo.middle); delay_ms(200); } void Servo_Start_UP(void) { if (Servo.pwm < Servo.right_limit) { uint16_t new_pwm = Servo.pwm + Servo.speed; if(new_pwm > Servo.right_limit) { new_pwm = Servo.right_limit; } Servo_Pwm_Set(new_pwm); } } void Servo_Start_DOWN(void) { if (Servo.pwm > Servo.left_limit) { uint16_t new_pwm = Servo.pwm - Servo.speed; if(new_pwm < Servo.left_limit) { new_pwm = Servo.left_limit; } Servo_Pwm_Set(new_pwm); } } void Servo_STOP(void) { } #define SERVO_PWM_PIN GPIO_Pin_8 #define SERVO_PWM_PORT GPIOA void Servo_Gpio_Init(void) { // 开启GPIOA和AFIO时钟 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO, ENABLE); GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure); } void Servo_Time_Init(void) { RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE); TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure; TIM_TimeBaseInitStructure.TIM_Period = 20000-1; TIM_TimeBaseInitStructure.TIM_Prescaler = 72-1; TIM_TimeBaseInitStructure.TIM_ClockDivision = 0; TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up; TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0; TIM_TimeBaseInit(TIM1, &TIM_TimeBaseInitStructure); TIM_OCInitTypeDef TIM_OCInitStructure; TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; TIM_OCInitStructure.TIM_OutputNState = TIM_OutputState_Disable; TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCPolarity_High; TIM_OCInitStructure.TIM_Pulse = Servo.middle; TIM_OC1Init(TIM1, &TIM_OCInitStructure); TIM_OC1PreloadConfig(TIM1, TIM_OCPreload_Enable); TIM_ARRPreloadConfig(TIM1, ENABLE); TIM_CtrlPWMOutputs(TIM1, ENABLE); TIM_Cmd(TIM1, ENABLE); } void Servo_Pwm_Set(uint16_t value) { if (value < Servo.left_limit) { value = Servo.left_limit; } else if (value > Servo.right_limit) { value = Servo.right_limit; } TIM_SetCompare1(TIM1, value); Servo.pwm = value; } #ifndef _SERVO_H_ #define _SERVO_H_ #include "stm32f10x.h" #define SERVO_PWM_PIN GPIO_Pin_8 #define SERVO_PWM_PORT GPIOA typedef struct { uint16_t pwm; uint16_t left_limit; uint16_t middle; uint16_t right_limit; uint16_t speed; } SERVO_PARAM; extern SERVO_PARAM Servo; void Servo_Init(void); void Servo_Gpio_Init(void); void Servo_Pwm_Set(uint16_t value); void Servo_Start_UP(void); void Servo_Start_DOWN(void); void Servo_STOP(void); void Servo_Time_Init(void); void Servo_Update_PWM(void); #endif #include "encoder.h" #include "stm32f10x_gpio.h" /******************************************************* Function:Initialize TIM1 to encoder interface mode Input ;none Output :none 函数 :把TIM1初始化为编码器接口模式 入口参数:无 返回值 :无 ********************************************************/ void Encoder_Init_Tim8(void) { TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; TIM_ICInitTypeDef TIM_ICInitStructure; GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM8, ENABLE);//使能定时器4的时钟 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);//使能PB端口时钟 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6|GPIO_Pin_7; //端口配置 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; //浮空输入 GPIO_Init(GPIOC, &GPIO_InitStructure); //根据设定参数初始化GPIOA TIM_TimeBaseStructInit(&TIM_TimeBaseStructure); TIM_TimeBaseStructure.TIM_Prescaler = 0x0; // 预分频器 TIM_TimeBaseStructure.TIM_Period = 65535; //设定计数器自动重装值 TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;//选择时钟分频:不分频 TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;////TIM向上计数 TIM_TimeBaseInit(TIM8, &TIM_TimeBaseStructure); TIM_EncoderInterfaceConfig(TIM8, TIM_EncoderMode_TI12, TIM_ICPolarity_Rising, TIM_ICPolarity_Rising);//使用编码器模式3 TIM_ICStructInit(&TIM_ICInitStructure); TIM_ICInitStructure.TIM_ICFilter = 10; //滤波10 TIM_ICInit(TIM8, &TIM_ICInitStructure); TIM_ClearFlag(TIM8, TIM_FLAG_Update);//清除TIM的更新标志位 TIM_ITConfig(TIM8, TIM_IT_Update, ENABLE); //Reset counter TIM_SetCounter(TIM8,0); TIM_Cmd(TIM8, ENABLE); } /******************************************************* Function:Initialize TIM2 to encoder interface mode Input ;none Output :none 函数 :把TIM2初始化为编码器接口模式 入口参数:无 返回值 :无 ********************************************************/ void Encoder_Init_Tim2(void) { TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; TIM_ICInitTypeDef TIM_ICInitStructure; GPIO_InitTypeDef GPIO_InitStructure; RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);//使能定时器4的时钟 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_AFIO, ENABLE);//使能PB端口时钟 GPIO_PinRemapConfig(GPIO_FullRemap_TIM2,ENABLE); // GPIO_PinRemapConfig(GPIO_Remap_SWJ_Disable,ENABLE); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_15; //端口配置 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; //浮空输入 GPIO_Init(GPIOA, &GPIO_InitStructure); //根据设定参数初始化GPIOB GPIO_InitStructure.GPIO_Pin =GPIO_Pin_3; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_Init(GPIOB,&GPIO_InitStructure); TIM_TimeBaseStructInit(&TIM_TimeBaseStructure); TIM_TimeBaseStructure.TIM_Prescaler = 0x0; // 预分频器 TIM_TimeBaseStructure.TIM_Period = 65535; //设定计数器自动重装值 TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;//选择时钟分频:不分频 TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;////TIM向上计数 TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure); TIM_EncoderInterfaceConfig(TIM2, TIM_EncoderMode_TI12, TIM_ICPolarity_Rising, TIM_ICPolarity_Rising);//使用编码器模式3 TIM_ICStructInit(&TIM_ICInitStructure); TIM_ICInitStructure.TIM_ICFilter = 10; //滤波10 TIM_ICInit(TIM2, &TIM_ICInitStructure); TIM_ClearFlag(TIM2, TIM_FLAG_Update);//清除TIM的更新标志位 TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE); //Reset counter TIM_SetCounter(TIM2,0); TIM_Cmd(TIM2, ENABLE); } /******************************************************* Function:Initialize TIM2 to encoder interface mode Input ;none Output :none 函数 :把TIM2初始化为编码器接口模式 入口参数:无 返回值 :无 ********************************************************/ void Encoder_Init_Tim3(void) { TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; TIM_ICInitTypeDef TIM_ICInitStructure; GPIO_InitTypeDef GPIO_InitStructure; RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);//使能定时器3的时钟 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);//使能PB端口时钟 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6|GPIO_Pin_7; //端口配置 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; //浮空输入 GPIO_Init(GPIOA, &GPIO_InitStructure); //根据设定参数初始化GPIOB TIM_TimeBaseStructInit(&TIM_TimeBaseStructure); TIM_TimeBaseStructure.TIM_Prescaler = 0x0; // 预分频器 TIM_TimeBaseStructure.TIM_Period = 65535; //设定计数器自动重装值 TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;//选择时钟分频:不分频 TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;////TIM向上计数 TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); TIM_EncoderInterfaceConfig(TIM3, TIM_EncoderMode_TI12, TIM_ICPolarity_Rising, TIM_ICPolarity_Rising);//使用编码器模式3 TIM_ICStructInit(&TIM_ICInitStructure); TIM_ICInitStructure.TIM_ICFilter = 10; //滤波10 TIM_ICInit(TIM3, &TIM_ICInitStructure); TIM_ClearFlag(TIM3, TIM_FLAG_Update);//清除TIM的更新标志位 TIM_ITConfig(TIM3, TIM_IT_Update, ENABLE); //Reset counter TIM_SetCounter(TIM3,0); TIM_Cmd(TIM3, ENABLE); } /************************************************************************** Function: Initialize TIM4 to encoder interface mode Input : none Output : none 函数功能:把TIM4初始化为编码器接口模式 入口参数:无 返回 值:无 **************************************************************************/ void Encoder_Init_Tim4(void) { TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; TIM_ICInitTypeDef TIM_ICInitStructure; GPIO_InitTypeDef GPIO_InitStructure; RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);//使能定时器4的时钟 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);//使能PB端口时钟 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6|GPIO_Pin_7; //端口配置 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; //浮空输入 GPIO_Init(GPIOB, &GPIO_InitStructure); //根据设定参数初始化GPIOB TIM_TimeBaseStructInit(&TIM_TimeBaseStructure); TIM_TimeBaseStructure.TIM_Prescaler = 0x0; // 预分频器 TIM_TimeBaseStructure.TIM_Period = 65535; //设定计数器自动重装值 TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;//选择时钟分频:不分频 TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;////TIM向上计数 TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure); TIM_EncoderInterfaceConfig(TIM4, TIM_EncoderMode_TI12, TIM_ICPolarity_Rising, TIM_ICPolarity_Rising);//使用编码器模式3 TIM_ICStructInit(&TIM_ICInitStructure); TIM_ICInitStructure.TIM_ICFilter = 10; TIM_ICInit(TIM4, &TIM_ICInitStructure); TIM_ClearFlag(TIM4, TIM_FLAG_Update);//清除TIM的更新标志位 TIM_ITConfig(TIM4, TIM_IT_Update, ENABLE); //Reset counter TIM_SetCounter(TIM4,0); TIM_Cmd(TIM4, ENABLE); } /************************************************************************** Function: Read encoder count per unit time Input : TIMX:Timer Output : none 函数功能:单位时间读取编码器计数 入口参数:TIMX:定时器 返回 值:速度值 **************************************************************************/ int Read_Encoder(u8 TIMX) { int Encoder_TIM; switch(TIMX) { case 8: Encoder_TIM= (short)TIM8 -> CNT; TIM8 -> CNT=0;break; case 2: Encoder_TIM= (short)TIM2 -> CNT; TIM2 -> CNT=0;break; case 3: Encoder_TIM= (short)TIM3 -> CNT; TIM3 -> CNT=0;break; case 4: Encoder_TIM= (short)TIM4 -> CNT; TIM4 -> CNT=0;break; default: Encoder_TIM=0; } //if(Encoder_TIM<0) Encoder_TIM=-Encoder_TIM; return Encoder_TIM; } /************************************************************************** Function: TIM4 interrupt service function Input : none Output : none 函数功能:TIM4中断服务函数 入口参数:无 返回 值:无 **************************************************************************/ void TIM4_IRQHandler(void) { if(TIM4->SR&0X0001)//溢出中断 { } TIM4->SR&=~(1<<0);//清除中断标志位 } /************************************************************************** Function: TIM1 interrupt service function Input : none Output : none 函数功能:TIM1中断服务函数 入口参数:无 返回 值:无 **************************************************************************/ void TIM8_IRQHandler(void) { if(TIM8->SR&0X0001)//溢出中断 { } TIM8->SR&=~(1<<0);//清除中断标志位 } /************************************************************************** Function: TIM3 interrupt service function Input : none Output : none 函数功能:TIM3中断服务函数 入口参数:无 返回 值:无 **************************************************************************/ void TIM3_IRQHandler(void) { if(TIM3->SR&0X0001)//溢出中断 { } TIM3->SR&=~(1<<0);//清除中断标志位 } /************************************************************************** Function: TIM2 interrupt service function Input : none Output : none 函数功能:TIM2中断服务函数 入口参数:无 返回 值:无 **************************************************************************/ void TIM2_IRQHandler(void) { if(TIM2->SR&0X0001)//溢出中断 { } TIM2->SR&=~(1<<0);//清除中断标志位 } #ifndef _ENCODER_H #define _ENCODER_H #include "stm32f10x.h" void Encoder_Init_Tim2(void); void Encoder_Init_Tim4(void); void Encoder_Init_Tim3(void); void Encoder_Init_Tim8(void); int Read_Encoder(u8 TIMX); // 中断服务函数声明 void TIM4_IRQHandler(void); void TIM8_IRQHandler(void); void TIM3_IRQHandler(void); void TIM2_IRQHandler(void); #endif #include "gpio.h" void Gpio_Init(void) { GPIO_InitTypeDef GPIO_InitStructure; // 使能时钟 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOC, ENABLE); // 配置电机控制引脚为推挽输出 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; // 电机A控制引脚 GPIO_InitStructure.GPIO_Pin = MOTOR_AIN1_PIN | MOTOR_AIN2_PIN; GPIO_Init(MOTOR_AIN1_PORT, &GPIO_InitStructure); // 电机B控制引脚 GPIO_InitStructure.GPIO_Pin = MOTOR_BIN1_PIN | MOTOR_BIN2_PIN; GPIO_Init(MOTOR_BIN1_PORT, &GPIO_InitStructure); // 电机C控制引脚 GPIO_InitStructure.GPIO_Pin = MOTOR_CIN1_PIN | MOTOR_CIN2_PIN; GPIO_Init(MOTOR_CIN1_PORT, &GPIO_InitStructure); // 电机D控制引脚 GPIO_InitStructure.GPIO_Pin = MOTOR_DIN1_PIN | MOTOR_DIN2_PIN; GPIO_Init(MOTOR_DIN1_PORT, &GPIO_InitStructure); // STBY引脚 GPIO_InitStructure.GPIO_Pin = MOTOR_STBY_PIN; GPIO_Init(MOTOR_STBY_PORT, &GPIO_InitStructure); // 默认使能电机驱动 Motor_Enable(); } void Motor_Enable(void) { GPIO_SetBits(MOTOR_STBY_PORT, MOTOR_STBY_PIN); // STBY = 1 } void Motor_Disable(void) { GPIO_ResetBits(MOTOR_STBY_PORT, MOTOR_STBY_PIN); // STBY = 0 } #ifndef __GPIO_H #define __GPIO_H #include "stm32f10x.h" #define MOTOR_AIN1_PIN GPIO_Pin_13 #define MOTOR_AIN1_PORT GPIOC #define MOTOR_AIN2_PIN GPIO_Pin_14 #define MOTOR_AIN2_PORT GPIOC #define MOTOR_BIN1_PIN GPIO_Pin_12 #define MOTOR_BIN1_PORT GPIOB #define MOTOR_BIN2_PIN GPIO_Pin_13 #define MOTOR_BIN2_PORT GPIOB #define MOTOR_CIN1_PIN GPIO_Pin_0 #define MOTOR_CIN1_PORT GPIOB #define MOTOR_CIN2_PIN GPIO_Pin_1 #define MOTOR_CIN2_PORT GPIOB #define MOTOR_DIN1_PIN GPIO_Pin_2 #define MOTOR_DIN1_PORT GPIOC #define MOTOR_DIN2_PIN GPIO_Pin_1 #define MOTOR_DIN2_PORT GPIOC // STBY引脚 #define MOTOR_STBY_PIN GPIO_Pin_15 #define MOTOR_STBY_PORT GPIOB void Gpio_Init(void); void Motor_Enable(void); void Motor_Disable(void); #endif #include "moto.h" #include "pwm.h" #include <math.h> #include <stdlib.h> // 添加这个头文件用于abs函数 void moto(int mode) { if(mode==1) //顺时针转动 { GPIO_SetBits(GPIOC, GPIO_Pin_14); // 高电平 PC14 --- AIN2 1 GPIO_ResetBits(GPIOC, GPIO_Pin_13); // 低电平} PC13 --- AIN1 0 GPIO_SetBits(GPIOB, GPIO_Pin_13); //高电平 PB13 --- BIN2 1 GPIO_ResetBits(GPIOB, GPIO_Pin_12); // 低电平 PB12 --- BIN1 0 GPIO_SetBits(GPIOB, GPIO_Pin_1); //高电平 PB1 --- CIN2 1 GPIO_ResetBits(GPIOB, GPIO_Pin_0); // 低电平 PB0 --- CIN1 0 GPIO_SetBits(GPIOC, GPIO_Pin_1); //高电平 PC2 --- DIN2 1 GPIO_ResetBits(GPIOC, GPIO_Pin_2); // 低电平 PC1 --- DIN1 0 } if(mode==0) //逆时针转动 { GPIO_SetBits(GPIOC, GPIO_Pin_13); // 高电平 PC13 --- AIN1 1 GPIO_ResetBits(GPIOC, GPIO_Pin_14); // 低电平} PC14 --- AIN2 0 GPIO_SetBits(GPIOB, GPIO_Pin_12); //高电平 PB12 --- BIN1 1 GPIO_ResetBits(GPIOB, GPIO_Pin_13); // 低电平 PB13 --- BIN2 0 GPIO_SetBits(GPIOB, GPIO_Pin_0); //高电平 PB0 --- CIN1 1 GPIO_ResetBits(GPIOB, GPIO_Pin_1); // 低电平 PB1 --- CIN2 0 GPIO_SetBits(GPIOC, GPIO_Pin_2); //高电平 PC1 --- DIN1 1 GPIO_ResetBits(GPIOC, GPIO_Pin_1); // 低电平 PC2 --- DIN2 0 } } void motor_StopAll(void) { motor_SetSpeed1(0); motor_SetSpeed2(0); motor_SetSpeed3(0); motor_SetSpeed4(0); } void motor_SetSpeed1(int16_t speed) { // 根据TB6612真值表设置方向 if(speed > 0) { // 正转 GPIO_SetBits(GPIOC, GPIO_Pin_13); // AIN1 = 1 GPIO_ResetBits(GPIOC, GPIO_Pin_14); // AIN2 = 0 } else if(speed < 0) { // 反转 GPIO_ResetBits(GPIOC, GPIO_Pin_13); // AIN1 = 0 GPIO_SetBits(GPIOC, GPIO_Pin_14); // AIN2 = 1 } else { // 停止 GPIO_ResetBits(GPIOC, GPIO_Pin_13); // AIN1 = 0 GPIO_ResetBits(GPIOC, GPIO_Pin_14); // AIN2 = 0 } TIM_SetCompare1(TIM5, abs(speed)); } // 其他三个电机的SetSpeed函数做类似修改,将参数改为int16_t void motor_SetSpeed2(int16_t speed) { if(speed > 0) { GPIO_SetBits(GPIOB, GPIO_Pin_12); // BIN1 = 1 GPIO_ResetBits(GPIOB, GPIO_Pin_13); // BIN2 = 0 } else if(speed < 0) { GPIO_ResetBits(GPIOB, GPIO_Pin_12); // BIN1 = 0 GPIO_SetBits(GPIOB, GPIO_Pin_13); // BIN2 = 1 } else { GPIO_ResetBits(GPIOB, GPIO_Pin_12); // BIN1 = 0 GPIO_ResetBits(GPIOB, GPIO_Pin_13); // BIN2 = 0 } TIM_SetCompare2(TIM5, abs(speed)); } void motor_SetSpeed3(int16_t speed) { if(speed > 0) { GPIO_SetBits(GPIOB, GPIO_Pin_0); // CIN1 = 1 GPIO_ResetBits(GPIOB, GPIO_Pin_1); // CIN2 = 0 } else if(speed < 0) { GPIO_ResetBits(GPIOB, GPIO_Pin_0); // CIN1 = 0 GPIO_SetBits(GPIOB, GPIO_Pin_1); // CIN2 = 1 } else { GPIO_ResetBits(GPIOB, GPIO_Pin_0); // CIN1 = 0 GPIO_ResetBits(GPIOB, GPIO_Pin_1); // CIN2 = 0 } TIM_SetCompare3(TIM5, abs(speed)); } void motor_SetSpeed4(int16_t speed) { if(speed > 0) { GPIO_SetBits(GPIOC, GPIO_Pin_2); // DIN1 = 1 GPIO_ResetBits(GPIOC, GPIO_Pin_1); // DIN2 = 0 } else if(speed < 0) { GPIO_ResetBits(GPIOC, GPIO_Pin_2); // DIN1 = 0 GPIO_SetBits(GPIOC, GPIO_Pin_1); // DIN2 = 1 } else { GPIO_ResetBits(GPIOC, GPIO_Pin_2); // DIN1 = 0 GPIO_ResetBits(GPIOC, GPIO_Pin_1); // DIN2 = 0 } TIM_SetCompare4(TIM5, abs(speed)); }#ifndef __MOTO_H #define __MOTO_H #include "stm32f10x.h" void moto_Init(void); void moto(int mode); void motor_SetSpeed1(int16_t speed); // 改为int16_t void motor_SetSpeed2(int16_t speed); void motor_SetSpeed3(int16_t speed); void motor_SetSpeed4(int16_t speed); void motor_StopAll(void); int Velocity_A(int TargetVelocity, int CurrentVelocity); int Velocity_B(int TargetVelocity, int CurrentVelocity); int Velocity_C(int TargetVelocity, int CurrentVelocity); int Velocity_D(int TargetVelocity, int CurrentVelocity); #endif #include "ps2.h" #define DELAY_TIME delay_us(5); u16 Handkey; // 按键值读取,零时存储。 u8 Comd[2]={0x01,0x42}; //开始命令。请求数据 u8 Data[9]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; //数据存储数组 u16 MASK[]={ PSB_SELECT, PSB_L1, PSB_R1, PSB_START, PSB_PAD_UP, PSB_PAD_RIGHT, PSB_PAD_DOWN, PSB_PAD_LEFT, PSB_L2, PSB_R2, PSB_L3, PSB_R3, PSB_GREEN, PSB_RED, PSB_BLUE, PSB_PINK }; /************************************************************************** 函数功能:以下是PS2接收器模块的初始化代码 入口参数:无 返回 值:无 按键值与按键明 手柄接口初始化 输入 DI->PA11 输出 DO->PA1 CS->PA2 CLK->PA0 **************************************************************************/ void PS2_Init(void) { GPIO_InitTypeDef GPIO_InitStructure; //定义GPIO_InitStructure结构体 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE); //开启GPIOA时钟 GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP; //复用推挽输出模式 GPIO_InitStructure.GPIO_Pin=GPIO_Pin_8|GPIO_Pin_9|GPIO_Pin_10; //P1.P2.P0口 GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz; //50MHZ GPIO_Init(GPIOB,&GPIO_InitStructure); //GPIOA初始化 PA1 PA2 PA0 GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPD; //下拉输入模式 GPIO_InitStructure.GPIO_Pin=GPIO_Pin_11; //P3口 GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz; //50MHZ GPIO_Init(GPIOB,&GPIO_InitStructure); //GPIOA初始化 PA0 } /************************************************************************** 函数功能:向手柄发送命令 入口参数:CMD指令 返回 值:无 **************************************************************************/ void PS2_Cmd(u8 CMD) { volatile u16 ref=0x01; Data[1] = 0; for(ref=0x01;ref<0x0100;ref<<=1) { if(ref&CMD) { DO_H; //拉高输出位,输出一位控制位 } else DO_L; CLK_H; //时钟拉高 DELAY_TIME; CLK_L; DELAY_TIME; CLK_H; if(DI) Data[1] = ref|Data[1]; } delay_us(16); } /************************************************************************** 函数功能:判断是否为红灯模式,0x41=模拟绿灯,0x73=模拟红灯 入口参数:CMD指令 返回 值:0,红灯模式 其他,其他模式 **************************************************************************/ u8 PS2_RedLight(void) { CS_L; PS2_Cmd(Comd[0]); //开始命令 PS2_Cmd(Comd[1]); //请求数据 CS_H; if( Data[1] == 0X41) return 1 ; else return 0; } /************************************************************************** 函数功能:读取手柄数据 入口参数:无 返回 值:无 **************************************************************************/ void PS2_ReadData(void) { volatile u8 byte=0; volatile u16 ref=0x01; CS_L; PS2_Cmd(Comd[0]); //开始命令 PS2_Cmd(Comd[1]); //请求数据 for(byte=2;byte<9;byte++) //开始接受数据 { for(ref=0x01;ref<0x100;ref<<=1) { CLK_H; DELAY_TIME; CLK_L; DELAY_TIME; CLK_H; if(DI) Data[byte] = ref|Data[byte]; } delay_us(16); } CS_H; } /************************************************************************** 函数功能:对读出来的PS2的数据进行处理,只处理按键部分 入口参数:CMD指令 返回 值:无 //只有一个按键按下时按下为0, 未按下为1 **************************************************************************/ u8 PS2_DataKey() { u8 index; PS2_ClearData(); PS2_ReadData(); Handkey=(Data[4]<<8)|Data[3]; //这是16个按键 按下为0, 未按下为1 for(index=0;index<16;index++) { if((Handkey&(1<<(MASK[index]-1)))==0) return index+1; } return 0; //有按键按下回调0传输给while循环的函数里。 } /************************************************************************** 函数功能:向手柄发送命令 入口参数:得到一个摇杆的模拟量 范围0~256 返回 值:无 **************************************************************************/ u8 PS2_AnologData(u8 button) { return Data[button]; } //清除数据缓冲区 void PS2_ClearData() { u8 a; for(a=0;a<9;a++) Data[a]=0x00; } /****************************************************** 函数功能: 手柄震动函数, Calls: void PS2_Cmd(u8 CMD); 入口参数: motor1:右侧小震动电机 0x00关,其他开 motor2:左侧大震动电机 0x40~0xFF 电机开,值越大 震动越大 返回 值:无 ******************************************************/ void PS2_Vibration(u8 motor1, u8 motor2) { CS_L; delay_us(16); PS2_Cmd(0x01); //开始命令 PS2_Cmd(0x42); //请求数据 PS2_Cmd(0X00); PS2_Cmd(motor1); PS2_Cmd(motor2); PS2_Cmd(0X00); PS2_Cmd(0X00); PS2_Cmd(0X00); PS2_Cmd(0X00); CS_H; delay_us(16); } /************************************************************************** 函数功能:short poll 入口参数:无 返回 值:无 **************************************************************************/ void PS2_ShortPoll(void) { CS_L; delay_us(16); PS2_Cmd(0x01); PS2_Cmd(0x42); PS2_Cmd(0X00); PS2_Cmd(0x00); PS2_Cmd(0x00); CS_H; delay_us(16); } /************************************************************************** 函数功能:进入配置 入口参数:无 返回 值:无 **************************************************************************/ void PS2_EnterConfing(void) { CS_L; delay_us(16); PS2_Cmd(0x01); PS2_Cmd(0x43); PS2_Cmd(0X00); PS2_Cmd(0x01); PS2_Cmd(0x00); PS2_Cmd(0X00); PS2_Cmd(0X00); PS2_Cmd(0X00); PS2_Cmd(0X00); CS_H; delay_us(16); } /************************************************************************** 函数功能:发送模式设置 入口参数:无 返回 值:无 **************************************************************************/ void PS2_TurnOnAnalogMode(void) { CS_L; PS2_Cmd(0x01); PS2_Cmd(0x44); PS2_Cmd(0X00); PS2_Cmd(0x01); //analog=0x01;digital=0x00 软件设置发送模式 PS2_Cmd(0xEE); //Ox03锁存设置,即不可通过按键“MODE”设置模式。固定为绿灯模式。 //0xEE不锁存软件设置,可通过按键“MODE”设置模式。 PS2_Cmd(0X00); PS2_Cmd(0X00); PS2_Cmd(0X00); PS2_Cmd(0X00); CS_H; delay_us(16); } /************************************************************************** 函数功能:振动设置 入口参数:无 返回 值:无 **************************************************************************/ void PS2_VibrationMode(void) { CS_L; delay_us(16); PS2_Cmd(0x01); PS2_Cmd(0x4D); PS2_Cmd(0X00); PS2_Cmd(0x00); PS2_Cmd(0X01); CS_H; delay_us(16); } /************************************************************************** 函数功能:完成并保存配置 入口参数:无 返回 值:无 **************************************************************************/ void PS2_ExitConfing(void) { CS_L; delay_us(16); PS2_Cmd(0x01); PS2_Cmd(0x43); PS2_Cmd(0X00); PS2_Cmd(0x00); PS2_Cmd(0x5A); PS2_Cmd(0x5A); PS2_Cmd(0x5A); PS2_Cmd(0x5A); PS2_Cmd(0x5A); CS_H; delay_us(16); } /************************************************************************** 函数功能:手柄配置初始化 入口参数:无 返回 值:无 **************************************************************************/ void PS2_SetInit(void) { PS2_ShortPoll(); PS2_ShortPoll(); PS2_ShortPoll(); PS2_EnterConfing(); //进入配置模式 PS2_TurnOnAnalogMode(); //“红绿灯”配置模式,并选择是否保存 //PS2_VibrationMode(); //开启震动模式 PS2_ExitConfing(); //完成并保存配置 } #ifndef __PSTWO_H #define __PSTWO_H #include "delay.h" #include "sys.h" /********************************************************* **********************************************************/ #define DI PBin(11) //PA0 输入 #define DO_H PBout(10)=1 //命令位高 #define DO_L PBout(10)=0 //命令位低 #define CS_H PBout(9)=1 //CS拉高 #define CS_L PBout(9)=0 //CS拉低 #define CLK_H PBout(8)=1 //时钟拉高 #define CLK_L PBout(8)=0 //时钟拉低 #define PSB_SELECT 1 #define PSB_L1 2 #define PSB_R1 3 #define PSB_START 4 #define PSB_PAD_UP 5 #define PSB_PAD_RIGHT 6 #define PSB_PAD_DOWN 7 #define PSB_PAD_LEFT 8 #define PSB_L2 9 /**/ #define PSB_R2 10/**/ #define PSB_L3 11 #define PSB_R3 12 #define PSB_GREEN 13 #define PSB_RED 14 #define PSB_BLUE 15 #define PSB_PINK 16 #define PSB_TRIANGLE 13 #define PSB_CIRCLE 14 #define PSB_CROSS 15 #define PSB_SQUARE 16 //#define WHAMMY_BAR 8 //These are stick values #define PSS_RX 5 //右摇杆X轴数据 #define PSS_RY 6 #define PSS_LX 7 #define PSS_LY 8 extern u8 Data[9]; extern u16 MASK[16]; extern u16 Handkey; void PS2_Init(void); u8 PS2_RedLight(void); //判断是否为红灯模式 void PS2_ReadData(void); //读手柄数据 void PS2_Cmd(u8 CMD); //向手柄发送命令 u8 PS2_DataKey(void); //按键值读取 u8 PS2_AnologData(u8 button); //得到一个摇杆的模拟量 void PS2_ClearData(void); //清除数据缓冲区 void PS2_Vibration(u8 motor1, u8 motor2);//振动设置motor1 0xFF开,其他关,motor2 0x40~0xFF void PS2_EnterConfing(void); //进入配置 void PS2_TurnOnAnalogMode(void); //发送模拟量 void PS2_VibrationMode(void); //振动设置 void PS2_ExitConfing(void); //完成配置 void PS2_SetInit(void); //配置初始化 #endif #include "pwm.h" #include "math.h" #include <stdlib.h> /************************************************************************** 函数功能:pwm初始化 入口参数:arr:设为一个时钟频率的最大值 psc: 预分频值 返回 值:无 **************************************************************************/ void PWM_Init(u16 arr,u16 psc) { GPIO_InitTypeDef GPIO_InitStructure; //定义结构体GPIO_InitStructure TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; //定义结构体TIM_TimeBaseStructure TIM_OCInitTypeDef TIM_OCInitStructure; //定义结构体TIM_OCInitStructure RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);//使能PA端口时钟 RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5,ENABLE);//使能定时器3 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3; GPIO_InitStructure.GPIO_Speed= GPIO_Speed_50MHz; GPIO_Init(GPIOA,&GPIO_InitStructure); TIM_TimeBaseStructure.TIM_Period = arr; //设置下一个更新活动的自动重装载寄存器的值 TIM_TimeBaseStructure.TIM_Prescaler = psc; //预分配值 TIM_TimeBaseStructure.TIM_ClockDivision = 0; //时钟分割 TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //向上计数 TIM_TimeBaseInit(TIM5,&TIM_TimeBaseStructure); TIM_OCInitStructure.TIM_OCMode= TIM_OCMode_PWM1; //PWM脉冲宽度调制1 TIM_OCInitStructure.TIM_Pulse = 0; //设置待装入捕获比较寄存器的脉冲值 TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //设置TIM输出极性为高 TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;//比较输出使能 TIM_OC1Init(TIM5,&TIM_OCInitStructure); TIM_OC2Init(TIM5,&TIM_OCInitStructure); TIM_OC3Init(TIM5,&TIM_OCInitStructure); TIM_OC4Init(TIM5,&TIM_OCInitStructure); TIM_OC1PreloadConfig(TIM5,TIM_OCPreload_Enable); TIM_OC2PreloadConfig(TIM5,TIM_OCPreload_Enable); TIM_OC3PreloadConfig(TIM5,TIM_OCPreload_Enable); TIM_OC4PreloadConfig(TIM5,TIM_OCPreload_Enable);//使能预装载寄存器 TIM_ARRPreloadConfig(TIM5,ENABLE); //使能自动装载允许位 TIM_Cmd(TIM5,ENABLE);//启动定时器5 } int myabs(int value){ if (value<0) value=-value; return value; } void Set_PWM(int motor1,int motor2,int motor3,int motor4) { if(motor1>0){ GPIO_SetBits(GPIOC, GPIO_Pin_14); // 高电平 PC14 --- AIN2 1 GPIO_ResetBits(GPIOC, GPIO_Pin_13); // 低电平} PC13 --- AIN1 0 }else{ GPIO_SetBits(GPIOC, GPIO_Pin_13); // 高电平 PC13 --- AIN1 1 GPIO_ResetBits(GPIOC, GPIO_Pin_14); // 低电平} PC14 --- AIN2 0 } if(motor2>0){ GPIO_SetBits(GPIOB, GPIO_Pin_13); //高电平 PB13 --- BIN2 1 GPIO_ResetBits(GPIOB, GPIO_Pin_12); // 低电平 PB12 --- BIN1 0 }else{ GPIO_SetBits(GPIOB, GPIO_Pin_12); //高电平 PB12 --- BIN1 1 GPIO_ResetBits(GPIOB, GPIO_Pin_13); // 低电平 PB13 --- BIN2 0 } if(motor3>0){ GPIO_SetBits(GPIOB, GPIO_Pin_1); //高电平 PB1 --- CIN2 1 GPIO_ResetBits(GPIOB, GPIO_Pin_0); // 低电平 PB0 --- CIN1 0 }else{ GPIO_SetBits(GPIOB, GPIO_Pin_0); //高电平 PB0 --- CIN1 1 GPIO_ResetBits(GPIOB, GPIO_Pin_1); // 低电平 PB1 --- CIN2 0 } if(motor4>0){ GPIO_SetBits(GPIOC, GPIO_Pin_1); //高电平 PC2 --- DIN2 1 GPIO_ResetBits(GPIOC, GPIO_Pin_2); // 低电平 PC1 --- DIN1 0 }else{ GPIO_SetBits(GPIOC, GPIO_Pin_2); //高电平 PC1 --- DIN1 1 GPIO_ResetBits(GPIOC, GPIO_Pin_1); // 低电平 PC2 --- DIN2 0 } TIM_SetCompare1(TIM5,myabs(motor1)); TIM_SetCompare2(TIM5,myabs(motor2)); TIM_SetCompare3(TIM5,myabs(motor3));//设置TIM3通道3的占空比 3000/7200 TIM_SetCompare4(TIM5,myabs(motor4)); } #ifndef __PWM_H #define __PWM_H #include "stm32f10x.h" void PWM_Init(u16 arr,u16 psc); void Set_PWM(int motor1,int motor2,int motot3,int motor4); #endif 帮我检查代码,为什么在ps2上使用#define PSB_GREEN 13 #define PSB_RED 14 #define PSB_BLUE 15 #define PSB_PINK 16这些按键时候没有反应,没法操控小车实现实时的舵机上升和下降
最新发布
10-14
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

甜甜的大香瓜

谢谢你的支持^_^

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值