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;
}
}
}
}
感谢小编!
谢谢分享,学习学习。