#include “stm32f10x.h”
#include “delay.h”
#include “motor.h”
#include “keysacn.h”
#include “IRSEARCH.h”
#include “IRAvoid.h”
/*
void ZYSTM32_run(int speed,int time); //前进函数
void ZYSTM32_brake(int time); //刹车函数
void ZYSTM32_Left(int speed,int time); //左转函数
void ZYSTM32_Spin_Left(int speed,int time); //左旋转函数
void ZYSTM32_Right(int speed,int time); //右转函数
void ZYSTM32_Spin_Right(int speed,int time);//右旋转函数
void ZYSTM32_back(int speed,int time); //后退函数
*/
int main(void)
{
delay_init();
KEY_Init();
IRSearchInit();
IRAvoidInit();
TIM4_PWM_Init(7199,0); //初始化PWM
ZYSTM32_brake(500);
keysacn();
while(1)
{
if(AVOID_IO == BARRIER_Y ) { BEEP_SET; LED_D3_SET; ZYSTM32_back(50,200); ZYSTM32_Spin_Left(50,350); delay_ms(300); } else { BEEP_RESET; LED_D3_RESET; SearchRun(); //循迹函数 } }
}
#include “IRSEARCH.h”
#include “delay.h”
#include “motor.h”
#include “stm32f10x.h” // Device header
char ctrl_comm = COMM_STOP;//控制指令
char ctrl_comm_last = COMM_STOP;//上一次的指令
void IRSearchInit(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOB , ENABLE);
GPIO_InitStructure.GPIO_Pin = SEARCH_R_PIN;//配置使能GPIO管脚
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;//配置GPIO模式,输入上拉
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//配置GPIO端口速度
GPIO_Init(SEARCH_R_GPIO , &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = SEARCH_L_PIN;//配置使能GPIO管脚 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;//配置GPIO模式,输入上拉 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//配置GPIO端口速度 GPIO_Init(SEARCH_L_GPIO , &GPIO_InitStructure);
}
void SearchRun(void)
{
if(SEARCH_L_IO == WHITE_AREA && SEARCH_R_IO == WHITE_AREA)
ctrl_comm = COMM_UP;
else if (SEARCH_L_IO == BLACK_AREA && SEARCH_R_IO == WHITE_AREA)
ctrl_comm = COMM_RIGHT;
else if (SEARCH_R_IO == BLACK_AREA & SEARCH_L_IO == WHITE_AREA)
ctrl_comm = COMM_LEFT;
else
ctrl_comm = COMM_DOWN;
if(ctrl_comm_last != ctrl_comm) { ctrl_comm_last = ctrl_comm; switch(ctrl_comm) { case COMM_UP: ZYSTM32_run(80,6);break; case COMM_DOWN: ZYSTM32_back(50,100);ZYSTM32_Spin_Left(70,400);break; case COMM_LEFT: ZYSTM32_back(50,100);ZYSTM32_Spin_Left(70,400);break; case COMM_RIGHT: ZYSTM32_back(50,100);ZYSTM32_Spin_Right(70,250);break; case COMM_STOP: ZYSTM32_brake(10);break; default : break; } }
}
#include “IRAvoid.h”
#include “delay.h”
#include “motor.h”
#include “keysacn.h”
#include “stm32f10x.h” // Device header
void IRAvoidInit(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB , ENABLE);
GPIO_InitStructure.GPIO_Pin = AVOID_PIN;//配置使能GPIO管脚 PB1
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;//配置GPIO模式,输入上拉
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//配置GPIO端口速度
GPIO_Init(AVOID_PIN_GPIO , &GPIO_InitStructure);
}
void AVoidRun(void)
{
if(AVOID_IO == BARRIER_N )
{
ZYSTM32_run(50,10);
BEEP_RESET;
LED_D3_RESET;
}
else
{
BEEP_SET;
LED_D3_SET;
ZYSTM32_brake(300);//停止300MS
ZYSTM32_back(50,400);//后退400MS
ZYSTM32_Left(50,500);//左转500MS
}
}
#ifndef _IRAVOID_H
#define _IRAVOID_H
#include “stm32f10x.h” // Device header
void IRAvoidInit(void);
void AVoidRun(void);
//避障传感器
/*
避障传感器 AVOID_PIN PB1
*/
#define AVOID_PIN GPIO_Pin_1
#define AVOID_PIN_GPIO GPIOB
#define AVOID_IO GPIO_ReadInputDataBit(AVOID_PIN_GPIO, AVOID_PIN)
#define BARRIER_Y 0 //有障碍物
#define BARRIER_N 1 //无障碍物
#endif
#include “motor.h”
#include “Math.h”
#include “delay.h”
#include “stm32f10x.h” // Device header
signed short sPWMR,sPWML,dPWM;
//GPIO配置函数
/*void MotorGPIO_Configuration(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOB, ENABLE); //使能PA,PB端口时钟
GPIO_InitStructure.GPIO_Pin = LEFT_MOTOR_GO; //左电机方向控制 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_Init(LEFT_MOTOR_GO_GPIO, &GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = LEFT_MOTOR_PWM; GPIO_Init(LEFT_MOTOR_PWM_GPIO, &GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = RIGHT_MOTOR_PWM; GPIO_Init(RIGHT_MOTOR_PWM_GPIO, &GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = RIGHT_MOTOR_GO; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_Init(RIGHT_MOTOR_GPIO, &GPIO_InitStructure);
}
void run() //前进
{
RIGHT_MOTOR_GO_SET;
RIGHT_MOTOR_PWM_RESET;//PB9
LEFT_MOTOR_GO_SET; LEFT_MOTOR_PWM_RESET;//PB8
}
*/
void TIM4_PWM_Init(unsigned short arr,unsigned short psc)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);// RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOB , ENABLE); //使能GPIO外设时钟使能
GPIO_InitStructure.GPIO_Pin = LEFT_MOTOR_GO; //左电机方向控制 PB7
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(LEFT_MOTOR_GO_GPIO, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = LEFT_MOTOR_PWM; //左电机PWM控制 PB8 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出 GPIO_Init(LEFT_MOTOR_PWM_GPIO, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = RIGHT_MOTOR_GO; //右电机方向控制 PA4
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(RIGHT_MOTOR_GPIO, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = RIGHT_MOTOR_PWM; //右电机PWM控制 PB9 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出 GPIO_Init(RIGHT_MOTOR_PWM_GPIO, &GPIO_InitStructure); TIM_TimeBaseStructure.TIM_Period = arr; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值 80K TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置用来作为TIMx时钟频率除数的预分频值 不分频 TIM_TimeBaseStructure.TIM_ClockDivision = 0; //设置时钟分割:TDTS = Tck_tim TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM向上计数模式 TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure); //根据TIM_TimeBaseInitStruct中指定的参数初始化TIMx的时间基数单位 TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2; //选择定时器模式:TIM脉冲宽度调制模式2 TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比较输出使能 TIM_OCInitStructure.TIM_Pulse = 0; //设置待装入捕获比较寄存器的脉冲值 TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //输出极性:TIM输出比较极性高 TIM_OC3Init(TIM4, &TIM_OCInitStructure); //根据TIM_OCInitStruct中指定的参数初始化外设TIMx TIM_OC4Init(TIM4, &TIM_OCInitStructure); //根据TIM_OCInitStruct中指定的参数初始化外设TIMx TIM_CtrlPWMOutputs(TIM4,ENABLE); //MOE 主输出使能 TIM_OC3PreloadConfig(TIM4, TIM_OCPreload_Enable); //CH1预装载使能 TIM_OC4PreloadConfig(TIM4, TIM_OCPreload_Enable); //CH1预装载使能
TIM_ARRPreloadConfig(TIM4, ENABLE); //使能TIMx在ARR上的预装载寄存器
TIM_Cmd(TIM4, ENABLE); //使能TIM1
}
void SetMotorSpeed(unsigned char ucChannel,signed char cSpeed)
{
// static short sMotorSpeed = 0;
short sPWM;
// float fDir = 1;
if (cSpeed>=100) cSpeed = 100; if (cSpeed<=-100) cSpeed = -100; sPWM = 7201 - fabs(cSpeed)*72; switch(ucChannel) { case 0://右轮 TIM_SetCompare3(TIM4,sPWM); if (cSpeed>0) RIGHT_MOTOR_GO_RESET; else if(cSpeed<0) RIGHT_MOTOR_GO_SET; break; case 1://左轮 TIM_SetCompare4(TIM4,sPWM); if (cSpeed>0) LEFT_MOTOR_GO_SET; else if (cSpeed<0) LEFT_MOTOR_GO_RESET; break; }
}
//----------------------------------运动函数--------------------------------
void ZYSTM32_run(signed char speed,int time) //前进函数
{
signed char f_speed = - speed;
SetMotorSpeed(1,f_speed);//左轮 //为负数
SetMotorSpeed(0,speed);//右轮 //为正数
delay_ms(time); //时间为毫秒
}
void ZYSTM32_brake(int time) //刹车函数
{
SetMotorSpeed(1,0);//左轮 //为0
SetMotorSpeed(0,0);//右轮 //为0
RIGHT_MOTOR_GO_RESET;
LEFT_MOTOR_GO_RESET;
delay_ms(time); //时间为毫秒
}
void ZYSTM32_Left(signed char speed,int time) //左转函数
{
SetMotorSpeed(1,0);//左轮 //左轮不动
SetMotorSpeed(0,speed); //右轮为正
delay_ms(time); //时间为毫秒
}
void ZYSTM32_Spin_Left(signed char speed,int time) //左旋转函数
{
SetMotorSpeed(1,speed);//左轮 //左轮为正
SetMotorSpeed(0,speed); //右轮为正
delay_ms(time); //时间为毫秒
}
void ZYSTM32_Right(signed char speed,int time) //右转函数
{
signed char f_speed = - speed;
SetMotorSpeed(1,f_speed);//左轮 //左轮为负
SetMotorSpeed(0,0); //右轮为0
delay_ms(time); //时间为毫秒
}
void ZYSTM32_Spin_Right(signed char speed,int time) //右旋转函数
{
signed char f_speed = - speed;
SetMotorSpeed(1,f_speed);//左轮 //左轮为负
SetMotorSpeed(0,f_speed); //右轮为负
delay_ms(time); //时间为毫秒
}
void ZYSTM32_back(signed char speed,int time) //后退函数
{
signed char u_speed = 100- speed;
signed char f_speed = - u_speed;
SetMotorSpeed(1,u_speed);//左轮 //为正数
SetMotorSpeed(0,f_speed);//右轮 //为负数
delay_ms(time); //时间为毫秒
}
#include “delay.h”
//////////////////////////////////////////////////////////////////////////////////
//如果需要使用OS,则包括下面的头文件即可.
#if SYSTEM_SUPPORT_OS
#include “includes.h” //ucos 使用
#endif
//////////////////////////////////////////////////////////////////////////////////
//本程序只供学习使用,未经作者许可,不得用于其它任何用途
//ZYSTM32-A0机器人主控板
//使用SysTick的普通计数模式对延迟进行管理(适合STM32F10x系列)
//包括delay_us,delay_ms
//智宇电子
//www.hnzhiyu.cn
//创建日期:2017/4/14
//版本:V1.8
//All rights reserved
//********************************************************************************
//////////////////////////////////////////////////////////////////////////////////
static u8 fac_us=0; //us延时倍乘数
static u16 fac_ms=0; //ms延时倍乘数,在ucos下,代表每个节拍的ms数
#if SYSTEM_SUPPORT_OS //如果SYSTEM_SUPPORT_OS定义了,说明要支持OS了(不限于UCOS).
//当delay_us/delay_ms需要支持OS的时候需要三个与OS相关的宏定义和函数来支持
//首先是3个宏定义:
// delay_osrunning:用于表示OS当前是否正在运行,以决定是否可以使用相关函数
//delay_ostickspersec:用于表示OS设定的时钟节拍,delay_init将根据这个参数来初始哈systick
// delay_osintnesting:用于表示OS中断嵌套级别,因为中断里面不可以调度,delay_ms使用该参数来决定如何运行
//然后是3个函数:
// delay_osschedlock:用于锁定OS任务调度,禁止调度
//delay_osschedunlock:用于解锁OS任务调度,重新开启调度
// delay_ostimedly:用于OS延时,可以引起任务调度.
//本例程仅作UCOSII和UCOSIII的支持,其他OS,请自行参考着移植
//支持UCOSII
#ifdef OS_CRITICAL_METHOD //OS_CRITICAL_METHOD定义了,说明要支持UCOSII
#define delay_osrunning OSRunning //OS是否运行标记,0,不运行;1,在运行
#define delay_ostickspersec OS_TICKS_PER_SEC //OS时钟节拍,即每秒调度次数
#define delay_osintnesting OSIntNesting //中断嵌套级别,即中断嵌套次数
#endif
//支持UCOSIII
#ifdef CPU_CFG_CRITICAL_METHOD //CPU_CFG_CRITICAL_METHOD定义了,说明要支持UCOSIII
#define delay_osrunning OSRunning //OS是否运行标记,0,不运行;1,在运行
#define delay_ostickspersec OSCfg_TickRate_Hz //OS时钟节拍,即每秒调度次数
#define delay_osintnesting OSIntNestingCtr //中断嵌套级别,即中断嵌套次数
#endif
//us级延时时,关闭任务调度(防止打断us级延迟)
void delay_osschedlock(void)
{
#ifdef CPU_CFG_CRITICAL_METHOD //使用UCOSIII
OS_ERR err;
OSSchedLock(&err); //UCOSIII的方式,禁止调度,防止打断us延时
#else //否则UCOSII
OSSchedLock(); //UCOSII的方式,禁止调度,防止打断us延时
#endif
}
//us级延时时,恢复任务调度
void delay_osschedunlock(void)
{
#ifdef CPU_CFG_CRITICAL_METHOD //使用UCOSIII
OS_ERR err;
OSSchedUnlock(&err); //UCOSIII的方式,恢复调度
#else //否则UCOSII
OSSchedUnlock(); //UCOSII的方式,恢复调度
#endif
}
//调用OS自带的延时函数延时
//ticks:延时的节拍数
void delay_ostimedly(u32 ticks)
{
#ifdef CPU_CFG_CRITICAL_METHOD
OS_ERR err;
OSTimeDly(ticks,OS_OPT_TIME_PERIODIC,&err); //UCOSIII延时采用周期模式
#else
OSTimeDly(ticks); //UCOSII延时
#endif
}
//systick中断服务函数,使用ucos时用到
void SysTick_Handler(void)
{
if(delay_osrunning==1) //OS开始跑了,才执行正常的调度处理
{
OSIntEnter(); //进入中断
OSTimeTick(); //调用ucos的时钟服务程序
OSIntExit(); //触发任务切换软中断
}
}
#endif
//初始化延迟函数
//当使用OS的时候,此函数会初始化OS的时钟节拍
//SYSTICK的时钟固定为HCLK时钟的1/8
//SYSCLK:系统时钟
void delay_init()
{
#if SYSTEM_SUPPORT_OS //如果需要支持OS.
u32 reload;
#endif
SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8); //选择外部时钟 HCLK/8
fac_us=SystemCoreClock/8000000; //为系统时钟的1/8
#if SYSTEM_SUPPORT_OS //如果需要支持OS.
reload=SystemCoreClock/8000000; //每秒钟的计数次数 单位为M
reload*=1000000/delay_ostickspersec; //根据delay_ostickspersec设定溢出时间
//reload为24位寄存器,最大值:16777216,在72M下,约合1.86s左右
fac_ms=1000/delay_ostickspersec; //代表OS可以延时的最少单位
SysTick->CTRL|=SysTick_CTRL_TICKINT_Msk; //开启SYSTICK中断 SysTick->LOAD=reload; //每1/delay_ostickspersec秒中断一次 SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk; //开启SYSTICK
#else
fac_ms=(u16)fac_us*1000; //非OS下,代表每个ms需要的systick时钟数
#endif
}
#if SYSTEM_SUPPORT_OS //如果需要支持OS.
//延时nus
//nus为要延时的us数.
void delay_us(u32 nus)
{
u32 ticks;
u32 told,tnow,tcnt=0;
u32 reload=SysTick->LOAD; //LOAD的值
ticks=nusfac_us; //需要的节拍数
tcnt=0;
delay_osschedlock(); //阻止OS调度,防止打断us延时
told=SysTick->VAL; //刚进入时的计数器值
while(1)
{
tnow=SysTick->VAL;
if(tnow!=told)
{
if(tnow<told)tcnt+=told-tnow; //这里注意一下SYSTICK是一个递减的计数器就可以了.
else tcnt+=reload-tnow+told;
told=tnow;
if(tcnt>=ticks)break; //时间超过/等于要延迟的时间,则退出.
}
};
delay_osschedunlock(); //恢复OS调度
}
//延时nms
//nms:要延时的ms数
void delay_ms(u16 nms)
{
if(delay_osrunning&&delay_osintnesting==0) //如果OS已经在跑了,并且不是在中断里面(中断里面不能任务调度)
{
if(nms>=fac_ms) //延时的时间大于OS的最少时间周期
{
delay_ostimedly(nms/fac_ms); //OS延时
}
nms%=fac_ms; //OS已经无法提供这么小的延时了,采用普通方式延时
}
delay_us((u32)(nms1000)); //普通方式延时
}
#else //不用OS时
//延时nus
//nus为要延时的us数.
void delay_us(u32 nus)
{
u32 temp;
SysTick->LOAD=nusfac_us; //时间加载
SysTick->VAL=0x00; //清空计数器
SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk ; //开始倒数
do
{
temp=SysTick->CTRL;
}while((temp&0x01)&&!(temp&(1<<16))); //等待时间到达
SysTick->CTRL&=~SysTick_CTRL_ENABLE_Msk; //关闭计数器
SysTick->VAL =0X00; //清空计数器
}
//延时nms
//注意nms的范围
//SysTick->LOAD为24位寄存器,所以,最大延时为:
//nms<=0xffffff81000/SYSCLK
//SYSCLK单位为Hz,nms单位为ms
//对72M条件下,nms<=1864
void delay_ms(u16 nms)
{
u32 temp;
SysTick->LOAD=(u32)nmsfac_ms; //时间加载(SysTick->LOAD为24bit)
SysTick->VAL =0x00; //清空计数器
SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk ; //开始倒数
do
{
temp=SysTick->CTRL;
}while((temp&0x01)&&!(temp&(1<<16))); //等待时间到达
SysTick->CTRL&=~SysTick_CTRL_ENABLE_Msk; //关闭计数器
SysTick->VAL =0X00; //清空计数器
}
#endif 现在的代码小车在避障后就会进入旋转的死循环
最新发布