OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 3389|回复: 10

stm32多任务中断问题

[复制链接]

1

主题

7

帖子

0

精华

新手上路

积分
27
金钱
27
注册时间
2017-9-5
在线时间
3 小时
发表于 2017-9-5 23:23:55 | 显示全部楼层 |阅读模式
1金钱
想利用stm32做一款智能小车,利用红外按键实现遥控、自动避障和循迹时遇到困难。
三个功能有单独实现的的代码,整合时我选用swith语句,把避障和循迹的函数加进遥控的语句怎么也完成不了

正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

1

主题

7

帖子

0

精华

新手上路

积分
27
金钱
27
注册时间
2017-9-5
在线时间
3 小时
 楼主| 发表于 2017-9-5 23:25:33 | 显示全部楼层
有完成循迹、避障、遥控功能的大神分享下,模式切换的思路吗
回复

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165540
金钱
165540
注册时间
2010-12-1
在线时间
2117 小时
发表于 2017-9-6 00:22:32 | 显示全部楼层
帮顶
回复

使用道具 举报

17

主题

354

帖子

0

精华

高级会员

Rank: 4

积分
797
金钱
797
注册时间
2017-5-21
在线时间
340 小时
发表于 2017-9-6 08:20:34 来自手机 | 显示全部楼层
没有看明白,是不是你想在遥控器里实现自动和手动控制,自动控制分为循迹和避障模式?如果是这样,你要加一个功能开关
回复

使用道具 举报

18

主题

155

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
3970
金钱
3970
注册时间
2016-7-8
在线时间
827 小时
发表于 2017-9-6 08:27:32 | 显示全部楼层
有代码才可以分析原因的
回复

使用道具 举报

56

主题

520

帖子

0

精华

高级会员

Rank: 4

积分
964
金钱
964
注册时间
2014-11-18
在线时间
160 小时
发表于 2017-9-6 09:19:08 | 显示全部楼层
弃天宝宝 发表于 2017-9-5 23:25
有完成循迹、避障、遥控功能的大神分享下,模式切换的思路吗

你是不是把巡迹和蔽障的功能函数放到红外按键那里去了?

那个是按一下之进入一次.

也就是按下的时候代码才会跑进去.
自己选择的路,成家前走完。
回复

使用道具 举报

1

主题

7

帖子

0

精华

新手上路

积分
27
金钱
27
注册时间
2017-9-5
在线时间
3 小时
 楼主| 发表于 2017-9-8 11:11:25 | 显示全部楼层
#include "IRCtrol.h"
#include "interface.h"

unsigned char ir_rec_flag=0;//接收数据标志位 1 有新数据 0 没有
unsigned char IRCOM[4];

//use time3 realize delay systick已经在main函数中使用了,在中断中不能重复使用
void Time3Init(void)
{
    TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
    TIM_TimeBaseStructure.TIM_Period = 1;
    TIM_TimeBaseStructure.TIM_Prescaler = (72 - 1);//72M / 72 = 1us
    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Down;
    TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);
}

//1us 延时
void DelayUs(vu32 nCount)
{
  u16 TIMCounter = nCount;
  TIM_Cmd(TIM3, ENABLE);
  TIM_SetCounter(TIM3, TIMCounter);
  while (TIMCounter>1)
  {
    TIMCounter = TIM_GetCounter(TIM3);
  }
  TIM_Cmd(TIM3, DISABLE);
}

//外部中断配置 红外遥控配置
void IRCtrolInit(void)
{
        GPIO_InitTypeDef  GPIO_InitStructure;
        EXTI_InitTypeDef         EXTI_InitStructure;//定义一个外部中断相关的结构体
        NVIC_InitTypeDef NVIC_InitStructure; //定义一个中断的结构体
       
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO , ENABLE);
        GPIO_InitStructure.GPIO_Pin = IRIN_PIN;//配置使能GPIO管脚
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;//配置GPIO模式,输入上拉
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//配置GPIO端口速度
        GPIO_Init(IRIN_GPIO , &GPIO_InitStructure);
               
        GPIO_EXTILineConfig(IRIN_PORTSOURCE , IRIN_PINSOURCE);
        EXTI_InitStructure.EXTI_Line = IRIN_EXITLINE;//将对应的GPIO口连接到中断线上
        EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;//中断事件类型,下降沿
        EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;//选择模式,中断型
        EXTI_InitStructure.EXTI_LineCmd = ENABLE;//使能该中断
        EXTI_Init(&EXTI_InitStructure);//将配置好的参数写入寄存器
                       
        NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);         //阶级为0,不可嵌套
        NVIC_InitStructure.NVIC_IRQChannel =         IRIN_IRQCH;//打开PINA_8的外部中断
        NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;//主优先级0,最高
        NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;        //子优先级,最低
        NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;        //使能该模块中断
        NVIC_Init(&NVIC_InitStructure);        //中断初始化,将结构体定义的数据执行
       
        Time3Init();
}

/*******************************************************************************
* 函 数 名 :DelayIr
* 函数功能 :0.14MS 延时
* 输    入 :无
* 输    出 :无
*******************************************************************************/
void DelayIr(unsigned char x)  
{
  while(x--)
{
  DelayUs(140);
}
}

void IRIntIsr(void)
{
  unsigned char j,k,N=0;
         DelayIr(15);
         if (IRIN==1)
     {
           return;
          }
                 continue_time = 40;//连发信号,表示指令持续 40*5 = 200ms 无指令停车
                           //确认IR信号出现
  while (!IRIN)            //等IR变为高电平,跳过9ms的前导低电平信号。
    {DelayIr(1);}

for (j=0;j<4;j++)         //收集四组数据
{
  for (k=0;k<8;k++)        //每组数据有8位
  {
   while (IRIN)            //等 IR 变为低电平,跳过4.5ms的前导高电平信号。
     {DelayIr(1);}
    while (!IRIN)          //等 IR 变为高电平
     {DelayIr(1);}
     while (IRIN)           //计算IR高电平时长
      {
    DelayIr(1);
    N++;           
    if (N>=30)
         {
         return;}                  //0.14ms计数过长自动离开。
      }                        //高电平计数完毕               
     IRCOM[j]=IRCOM[j] >> 1;                  //数据最高位补“0”
     if (N>=8) {IRCOM[j] = IRCOM[j] | 0x80;}  //数据最高位补“1”
     N=0;
  }//end for k
}//end for j
   
        k = ~IRCOM[3];
   if (IRCOM[2] != k)
   {
     return; }
         
                 //指令转换
                 
                 switch(IRCOM[2])
                 {
                         case 0x46: ctrl_comm = COMM_UP;break;
                         case 0x15: ctrl_comm = COMM_DOWN;break;
                         case 0x44: ctrl_comm = COMM_LEFT;break;
                         case 0x43: ctrl_comm = COMM_RIGHT;break;
                         case 0x40: ctrl_comm = COMM_STOP;break;
                         case 0x16: ctrl_comm = COMM_AUTORUN;break;
                         case 0x19: ctrl_comm = COMM_XUNJI;break;
                         default :  return;
                 }
                 ir_rec_flag = 1;
       
}

//连接方式 :请参考interface.h文件
//部份源码来源网络--请试用24小时后删除
#include "stm32f10x.h"
#include "interface.h"
#include "LCD1602.h"
#include "IRCtrol.h"
#include "motor.h"
#include "UltrasonicCtrol.h"
#include "redvoid.h"

//全局变量定义
unsigned int speed_count=0;//占空比计数器 50次一周期
char front_left_speed_duty=SPEED_DUTY;
char front_right_speed_duty=SPEED_DUTY;
char behind_left_speed_duty=SPEED_DUTY;
char behind_right_speed_duty=SPEED_DUTY;

unsigned char tick_5ms = 0;//5ms计数器,作为主函数的基本周期
unsigned char tick_1ms = 0;//1ms计数器,作为电机的基本计数器
unsigned char tick_200ms = 0;//刷新显示

char ctrl_comm = COMM_STOP;//控制指令
char ctrl_comm_last = COMM_STOP;//上一次的指令
unsigned char continue_time=0;

//循迹,通过判断三个光电对管的状态来控制小车运动
void SearchRun(void)
{
        //三路都检测到
        if(SEARCH_M_IO == BLACK_AREA && SEARCH_L_IO == BLACK_AREA && SEARCH_R_IO == BLACK_AREA)
        {
                ctrl_comm = COMM_UP;
                return;
        }
       
        if(SEARCH_R_IO == BLACK_AREA)//右
        {
                ctrl_comm = COMM_RIGHT;
        }
        else if(SEARCH_L_IO == BLACK_AREA)//左
        {
                ctrl_comm = COMM_LEFT;
        }
        else if(SEARCH_M_IO == BLACK_AREA)//中
        {
                ctrl_comm = COMM_UP;
        }
}

int main(void)
{
        delay_init();
        GPIOCLKInit();
        UserLEDInit();
//        LCD1602Init();
        IRCtrolInit();
        TIM2_Init();
        MotorInit();
        //UltraSoundInit();
        RedRayInit();
        ServoInit();

while(1)
{         
                         if(tick_5ms >= 5)
                {
                        tick_5ms = 0;
                        tick_200ms++;
                        if(tick_200ms >= 40)
                        {
                                tick_200ms = 0;
                                LEDToggle(LED_PIN);
                        }
                        //do something
                        if(ir_rec_flag == 1)//接收到红外信号
                        {
                                ir_rec_flag = 0;
                                switch(ctrl_comm)
                                {
                                        case COMM_UP:    CarGo();break;
                                        case COMM_DOWN:  CarBack();break;
                                        case COMM_LEFT:  CarLeft();break;
                                        case COMM_RIGHT: CarRight();break;
                                        case COMM_STOP:  CarStop();break;
                                        case COMM_AUTORUN: VoidRun();break;
                                        case COMM_XUNJI:         SearchRun();break;
                                        default : break;
                                }
                                LCD1602WriteCommand(ctrl_comm);
                        }
                       
                }
               
}
}

回复

使用道具 举报

1

主题

7

帖子

0

精华

新手上路

积分
27
金钱
27
注册时间
2017-9-5
在线时间
3 小时
 楼主| 发表于 2017-9-8 11:12:41 | 显示全部楼层
aiyeba 发表于 2017-9-6 09:19
你是不是把巡迹和蔽障的功能函数放到红外按键那里去了?

那个是按一下之进入一次.

我应该是把子函数放在按键里,代码在下面,那应该怎么修改呢
回复

使用道具 举报

1

主题

7

帖子

0

精华

新手上路

积分
27
金钱
27
注册时间
2017-9-5
在线时间
3 小时
 楼主| 发表于 2017-9-8 11:13:11 | 显示全部楼层
yanzhuangsongqi 发表于 2017-9-6 08:27
有代码才可以分析原因的

大佬看一下呢,我把关键代码打在下面了
回复

使用道具 举报

1

主题

7

帖子

0

精华

新手上路

积分
27
金钱
27
注册时间
2017-9-5
在线时间
3 小时
 楼主| 发表于 2017-9-8 11:14:50 | 显示全部楼层
l6931639 发表于 2017-9-6 08:20
没有看明白,是不是你想在遥控器里实现自动和手动控制,自动控制分为循迹和避障模式?如果是这样,你要加一 ...

是这样的,功能开关用什么实现呢,我想用红外遥控按键设置这些模式的转换
回复

使用道具 举报

56

主题

520

帖子

0

精华

高级会员

Rank: 4

积分
964
金钱
964
注册时间
2014-11-18
在线时间
160 小时
发表于 2017-9-8 15:13:15 | 显示全部楼层
弃天宝宝 发表于 2017-9-8 11:12
我应该是把子函数放在按键里,代码在下面,那应该怎么修改呢

我有点忙,大概看了一下,是你子函数放红外解码那里了.导致程序只跑了一次.

修改成      u8 bus_mode=0;

红外解码

case COMM_UP:    CarGo();break;
                                        case COMM_DOWN: bus_mode=1;break;
                                        case COMM_LEFT:   bus_mode=2;break;
                                        case COMM_RIGHT:  bus_mode=3;break;
                                        case COMM_STOP:   bus_mode=4;break;
                                        case COMM_AUTORUN:  bus_mode=5;break;
                                        case COMM_XUNJI:          bus_mode=6;break;
                                        default : break;


你再写个子函数

放到while(1)里面循环即可

大概就是
switch(bus_mode)
{
  case 1:   CarGo();break;
  case 2:



}







具体的自己想




自己选择的路,成家前走完。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-6-19 05:06

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表