微波EDA网,见证研发工程师的成长!
首页 > 研发问答 > 嵌入式设计讨论 > MCU和单片机设计讨论 > stm32f103控制两电机+摄像头图传源代码

stm32f103控制两电机+摄像头图传源代码

时间:10-02 整理:3721RD 点击:

#include "stm32f10x.h"
#include "common.h"
#include "stm32f10x_conf.h"
#include "uart.h"

void RCC_Configuration(void)
{
   SystemInit();
   RCC_APB2PeriphClockCmd( RCC_APB2Periph_AFIO  , ENABLE);   
}
void GPIO_Configuration(void)
{
                        -
       
        GPIO_InitTypeDef GPIO_InitStructure;
        RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA |
                RCC_APB2Periph_GPIOB |RCC_APB2Periph_GPIOC , ENABLE);
         
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;       
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_Init(GPIOA, &GPIO_InitStructure);       
        RUNLED_OFF;
       
        //PA8-->MCO 测试时钟用
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;       
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_Init(GPIOA, &GPIO_InitStructure);       
        RCC_MCOConfig(RCC_MCO_SYSCLK);
       

        //PB0---->TIM3  ch3--->motor pwm
        //PB1---->TIM3        ch4--->motor pwm
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_Init(GPIOB, &GPIO_InitStructure);
        //TIM2端口需要重映射
        GPIO_PinRemapConfig(GPIO_PartialRemap2_TIM2,ENABLE);
        //PB10--->[TIM2_CH3]--->motor pwm
        //PB11--->[TIM2_CH4]--->motor pwm
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10|GPIO_Pin_11;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_Init(GPIOB, &GPIO_InitStructure);
       
        //PB9---->TIM4  ch4--->Servo
        // Ch4 as alternate function push-pull */
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_Init(GPIOB, &GPIO_InitStructure);
       
        //PB12,13,14,15 红外输入
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12|GPIO_Pin_13|GPIO_Pin_14|GPIO_Pin_15;       
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_Init(GPIOB, &GPIO_InitStructure);
       
}

//servo 舵机PWM控制
//20ms周期,其等分为1800,那样500us~2500us的位置刚
//好为周期的1/10,且为180等分,这样设置角度很简单
//for tank only
#define servo_max_deg        120
#define servo_min_deg        60
#define servo_start_deg        45        //0°位置
#define servo_end_deg        225        //180°位置
#define servo_mid_deg        servo_start_deg+90        //90°位置
uint16_t servo_set_deg = 90;        //实际PWM控制位置
unsigned char Continue_flag = 0;//舵机持续转动标记

#define Left_motor_P                1        //用于PWM设置时的标记
#define Left_motor_N                2        //用于PWM设置时的标记
#define Right_motor_P        3        //用于PWM设置时的标记
#define Right_motor_N        4        //用于PWM设置时的标记
#define Motor_PWM_Level_Max  360        //360级调速

//定时器初始化,暂用于串口超时判断
void Init_Timer(void)
{
        //TIM4 舵机
        //TIM3 TIM2  驱动电机
       
        TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
        TIM_OCInitTypeDef  TIM_OCInitStructure;
        //=====================TIM4===========================
        RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4,ENABLE);//enable Tim4 clock
        /* Time base configuration */
        TIM_TimeBaseStructure.TIM_Period = 1800;//1800/(2400000/(799+1) )= 20ms
        TIM_TimeBaseStructure.TIM_Prescaler = 799;//n+1分频
          TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_div1;
          TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
          TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure);
        /* PWM1 Mode configuration: Channel4 */
        TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
        TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
        TIM_OCInitStructure.TIM_Pulse = servo_set_deg;
        TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
        TIM_OC4Init(TIM4, &TIM_OCInitStructure);
        TIM_OC4PreloadConfig(TIM4, TIM_OCPreload_Enable);
        TIM_ARRPreloadConfig(TIM4, ENABLE);
         /* TIM4 enable counter */
          TIM_Cmd(TIM4, ENABLE);
         
        //=================TIM2======================
        //电机驱动暂定1KHz
        RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);//enable Tim4 clock
        /* Time base configuration */
        TIM_TimeBaseStructure.TIM_Period = 360;//360/(7200000/(199+1) )= 1ms
        TIM_TimeBaseStructure.TIM_Prescaler = 199;//n+1分频
          TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_div1;
          TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
          TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
        /* PWM1 Mode configuration: Channel4 */
        TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
        TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
        TIM_OCInitStructure.TIM_Pulse = 0;//        初始低电平,
        TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;//高位有效
        TIM_OC3Init(TIM2, &TIM_OCInitStructure);
        TIM_OC4Init(TIM2, &TIM_OCInitStructure);
        TIM_OC4PreloadConfig(TIM2, TIM_OCPreload_Enable);
        TIM_ARRPreloadConfig(TIM2, ENABLE);
         /* TIM4 enable counter */
          TIM_Cmd(TIM2, ENABLE);
         //=================TIM3======================
        //电机驱动暂定1KHz
        RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);//enable Tim4 clock
        /* Time base configuration */
        TIM_TimeBaseStructure.TIM_Period = 360;//360/(7200000/(199+1) )= 1ms
        TIM_TimeBaseStructure.TIM_Prescaler = 199;//n+1分频
          TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_div1;
          TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
          TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);
        /* PWM1 Mode configuration: Channel4 */
        TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
        TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
        TIM_OCInitStructure.TIM_Pulse = 0;//        初始低电平,
        TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;//高位有效
        TIM_OC3Init(TIM3, &TIM_OCInitStructure);
        TIM_OC4Init(TIM3, &TIM_OCInitStructure);
        TIM_OC4PreloadConfig(TIM3, TIM_OCPreload_Enable);
        TIM_ARRPreloadConfig(TIM3, ENABLE);
         /* TIM4 enable counter */
          TIM_Cmd(TIM3, ENABLE);
}
void NVIC_Configuration(void)
{
  NVIC_InitTypeDef NVIC_InitStructure;
   /* Enable the USARTx Interrupt */
  NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  NVIC_Init(&NVIC_InitStructure);
  #if 0
  //未使用USART1中断处理
   /* Enable the USARTx Interrupt */
  NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  NVIC_Init(&NVIC_InitStructure);
  #endif
}
void delay_100ms(unsigned int value)
{
        unsigned int i=0;
        unsigned int cnt=0;
        for(cnt=0;cnt<value;cnt++)
                //for(i=0;i<70500;i++);//100ms @4.2MHz MSI
                //for(i=0;i<518000;i++);//100ms @72MHz
                for(i=0;i<656000;i++);//100ms @72MHz
}
void delay_10ms(unsigned int value)
{
        unsigned int i=0;
        unsigned int cnt=0;
        for(cnt=0;cnt<value;cnt++)
                for(i=0;i<51800;i++);//10ms @72MHz
}
//未测试
void delay_1ms(unsigned int value)
{
        unsigned int i=0;
        unsigned int cnt=0;
        for(cnt=0;cnt<value;cnt++)
                for(i=0;i<5180;i++);//10ms @72MHz
}

//设置角度值
void Servo_Set(unsigned char deg)
{
        if(deg <= 180 )
                TIM_SetCompare4(TIM4,servo_start_deg+deg);
}
void PWM_Set(unsigned char PWM_Num,unsigned int level)
{
        //0~360
        if(level <= Motor_PWM_Level_Max)
        {
                switch(PWM_Num)
                {
                        case Left_motor_P: //PIN16
                                TIM_SetCompare4(TIM3,level);//TIM3 CH4,
                                break;
                        case Left_motor_N: //PIN15
                                TIM_SetCompare3(TIM3,level);//TIM3 CH3
                                break;
                        case Right_motor_P: //PIN14
                                TIM_SetCompare3(TIM2,level);//TIM4 CH3
                                break;
                        case Right_motor_N: //Pin13
                                TIM_SetCompare4(TIM2,level);//TIM4 CH4
                                break;
                        default: break;
                }
        }
}
//快速右转弯
//双轮机动右转
void Fast_TurnR(void)  
{
        // 右电机前进             
        PWM_Set(Right_motor_P,360);//PWM比例0~360调速,左右轮差异略增减
        PWM_Set(Right_motor_N,0);//0-->关闭PWM ,拉低
        // 左电机前进
        PWM_Set(Left_motor_P,360);//PWM比例0~360调速,左右轮差异略增减
        PWM_Set(Left_motor_N,0);
        //delay(a * 100);   //执行时间,可以调整  
}
//快速左转弯
//双轮机动左转
void Fast_TurnL(void)
{
     //右轮后退
        PWM_Set(Right_motor_P,0);
        PWM_Set(Right_motor_N,360);//PWM比例0~360调速
        //左轮后退
        PWM_Set(Left_motor_P,0);
        PWM_Set(Left_motor_N,360);//PWM比例0~360调速
     //delay(g * 100);     //执行时间,可以调整  
}

// 前進,走偏请调整左右PWM
void advance(void)   
{
        //右轮后退
        PWM_Set(Right_motor_P,0);
        PWM_Set(Right_motor_N,360);//PWM比例0~360调速
        //左轮前进
        PWM_Set(Left_motor_P,360);//PWM比例0~360调速,左右轮差异略增减
        PWM_Set(Left_motor_N,0);
        //delay(d * 10);//执行时间,可以调整  
}
//後退
void Reverse(void)   
{
        //右轮前进
       PWM_Set(Right_motor_P,360);//PWM比例0~360调速,左右轮差异略增减
        PWM_Set(Right_motor_N,0);
        //左轮后退
        PWM_Set(Left_motor_P,0);
        PWM_Set(Left_motor_N,360);//PWM比例0~360调速
        //delay(e * 10);//执行时间,可以调整  
}   
//刹车,停车
void Brake(unsigned char t)         
{
        PWM_Set(Right_motor_P,0);
        PWM_Set(Right_motor_N,0);
        PWM_Set(Left_motor_P,0);
        PWM_Set(Left_motor_N,0);
        delay_100ms(t );//执行时间,可以调整  
}  

void Action(unsigned char ctrl_val)
{
   switch(ctrl_val)
   {
      //move                           //hex  dec
      case 'L': USART_SendStringwithEnter(USART2,"Turn left.");Fast_TurnL();break;   //0x4C==76
      case 'R': USART_SendStringwithEnter(USART2,"Turn right.");Fast_TurnR();break;   //0x52==82
      case 'F': USART_SendStringwithEnter(USART2,"Go Forward.");advance();break;      //0x46==70
      case 'B': USART_SendStringwithEnter(USART2,"Go back.");Reverse();break;      //0x42==66
      case 'S': USART_SendStringwithEnter(USART2,"Stop car.");Brake(5);break;        //0x53==83
      //servo
      case 'r':         Continue_flag = 1;
                        break;  //0x72==114
      case 'm': //USART_Send_Value(USART2,"old deg = ",servo_set_deg);//调试用执行信息
                          servo_set_deg=90;
                        //USART_Send_Value(USART2,"new deg = ",servo_set_deg);//调试用执行信息
                          Servo_Set(servo_set_deg);
                        break;                      //0x6D==109
      case 'l':         Continue_flag = 2;
                        break; //0x6C==108
      case 's': //USART_SendStringwithEnter(USART2,"stop");//调试用执行信息
                              Continue_flag = 0;
                        break;//0x73==115
      default: break;
   }   
}

unsigned char ProcessEnable = 0;//串口多字节处理时,未处理完成不执行新动作
unsigned char test0=0,test1=0;
unsigned char Rxbuf[Rx_length];
unsigned char Rx_available_flag = 0;
unsigned char Rx_AutoSave_mark = 0;//当前存储位置
unsigned char Rx_handle_mark=0;//当前处理位置
void Judge(void)
{
        //unsigned char ii=0;
        if(Rx_available_flag==1)
        {               
               
                test1 = Rxbuf[Rx_handle_mark++];
                if(Rx_handle_mark >= Rx_length)
                        Rx_handle_mark = 0;
                delay_10ms(1);
                //因9600速率较慢,单片机处理速度快,
                //此处增加等待,保证有后继数据时,
                //串口中断有时间修改Rx_AutoSave_mark值,
                //这样不会造成单步失效,若来不及修改则判断为长按了
                if(Rx_handle_mark == Rx_AutoSave_mark)
                {
                        Rx_available_flag = 0;
                }
                #if 0       
                //此处增加信息打印有利于调试
                USART_SendString(USART2,"Rxbuf :");
                for(ii=0;ii<10;ii++)
                {
                        if(Rxbuf[ii] != 0)
                                USART_SendChar(USART2,Rxbuf[ii]);       
                        else USART_SendChar(USART2,0x30);       
                        USART_SendChar(USART2,' ');
                }
                USART_SendChar(USART2,0x0d);
                USART_SendChar(USART2,0x0a);
                USART_Send_Value(USART2,"Rx_handle_mark = ", Rx_handle_mark);
                USART_Send_Value(USART2,"Rx_AutoSave_mark = ", Rx_AutoSave_mark);
                #endif
                //USART_SendChar(test1);
                if(test0 == test1)
                {
                        //USART_SendWithData(USART2,"Process with : ",test1);
                        ProcessEnable = 1;                       
                        Action(test1);//choose any for process
                }
                else {
                        test0 = test1;//updata
                }
        }
}
unsigned int ledcnt = 0;
unsigned char led_flag = 0;
void RUNLED_TG(void)
{
        if(ledcnt < 0x4ffff)
                ledcnt++;
        else {
                ledcnt = 0;
                led_flag = ~led_flag;
        }
        if(led_flag)
                RUNLED_ON;
        else
                RUNLED_OFF;
       
}
int main()
{
        RCC_Configuration();
        GPIO_Configuration();
        Init_Timer();
        Init_USART();       
        NVIC_Configuration();
        USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);//开启接收中断
        USART_SendStringwithEnter(USART2,"POWSOS STM32 WIFI TANK.");
        PWM_Set(Left_motor_P,0);
        PWM_Set(Left_motor_N,0);
        PWM_Set(Right_motor_P,0);
        PWM_Set(Right_motor_N,0);
        Servo_Set(servo_set_deg);                //初始化摄像头朝前
        while(1)
        {
                RUNLED_TG();
                Judge();
                //舵机持续转动
                if(ProcessEnable)
                {
                        if(Rx_available_flag)//后继无数据,要保持连续转动的动作
                                ProcessEnable = 0;
                        switch(Continue_flag)
                        {
                                case 1:        //USART_Send_Value(USART2,"loop old deg = ",servo_set_deg);
                                                if(servo_set_deg>servo_min_deg)
                                                {
                                                        servo_set_deg-=1;
                                                        //USART_Send_Value(USART2,"loop new deg = ",servo_set_deg);
                                                        Servo_Set(servo_set_deg);
                                                        delay_10ms(5);
                                                }
                                                else{
                                                        Continue_flag = 0;
                                                }
                                                break;//turn right
                                case 2:        //USART_Send_Value(USART2,"loop old deg = ",servo_set_deg);
                                                if(servo_set_deg<servo_max_deg)
                                                {
                                                        servo_set_deg +=1;
                                                        //USART_Send_Value(USART2,"loop new deg = ",servo_set_deg);
                                                        Servo_Set(servo_set_deg);
                                                        delay_10ms(5);
                                                }
                                                else{
                                                        Continue_flag = 0;
                                                }break;//turn left
                                default: break;
                        }
                }
        }
}

感谢小编!

谢谢分享,学习学习。

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top