手电大家谈-手电筒爱好者之家

 找回密码
 注册成为会员,享受更多功能。

QQ登录

只需一步,快速开始

只需一步,快速开始

搜索
查看: 3947|回复: 50

[电子电路] 请教各位老师,STM8中断执行后不能返回

[复制链接]
  • TA的每日心情
    开心
    2016-12-21 15:48
  • 签到天数: 11 天

    [LV.3]偶尔看看II

    发表于 2023-2-6 17:06 | 显示全部楼层 |阅读模式

    马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

    您需要 登录 才可以下载或查看,没有账号?注册成为会员,享受更多功能。

    x
         话说年纪大了,做东西动不动就是世纪工程,弄个几年的感觉也不急了。
          背景,懂点硬件,原来画图用 PROTEL,还是比较老的版本,后面的(PROTEL99SE)都有点嫌大,当然现在上手嘉立创的EDA肯定不是问题,熟悉下肯定可用。
          这次做东西也是因为几年前的一个东西,我的中华V3自己加了前,左,右三个摄像头,后来又弄了个4口模拟海康录像机,当然开始的软件是一位网友帮忙做的(其实硬件也是他随手做的),效果很好。但最近发现使用中偶尔会关机返回车机画面,估计有接触不良,再说想再加点其他功能。反正闲,不想点事会老年痴呆。
          原来的帖子:折腾一年半!尚未完成的中华V3摄像头加装,录像加装过程 https://www.mydigit.cn/thread-253773-1-1.html
          原车是模拟倒车视频,车机有一个12V电平触发车机切换到倒车视频通道,我这个也是利用这个特点,用12V触发切换,原车倒车视频线路再加转换开关切换前,右,左,录像显示(当然真正倒车进来时立刻切换过去,任何时候都倒车优先),转向灯的时候,用断续大概1HZ信号(就是倒车镜上那个指示灯电平)触发切换到相应的左右通道,转向完后返回原来状态。
         现在逻辑是:启动时候按照左,前,右各通道各显示3秒(不用精确)检查车辆周边有无障碍小动物小孩子等,然后返回车机原有状态,如果按下按键,则按照右,左,前,录像机顺序切换,左右转向可以切进去,倒车优先。最后再加一个熄火后发送一个5秒(不用精确)信号,我在车窗处加一个4位继电器关闭车窗(利用原车系统电源供电,这个电源启动后通电,熄火后大概两分钟断电,ACC电源熄火后断电来检测)。
          原来是一位网友帮忙做的,现在联系不上(本论坛被禁言了undefinedundefined,不知道换了ID进来没有?)也是群里的大神,所以自己买了本龙老师的STM8书籍来学习,自己做了stm8s003F3开发板(因为原来兄弟就是这个芯片),跌跌撞撞学习,会写按键了,在各个群里面请教学习,现在其他功能都能实现,就是中断返回有问题。

          准确描述就是:开机启动各通道顺序显示,返回初始状态,按键选择循环都正常,熄火关窗输出也正常(这个也是中断,但输出跟信号切换不是同一组),PD4,PD5左右转向能够触发,但是触发信号消失后不能返回原来状态(比如按键切换到前摄像头或者就是车机输出),一直显示左或者右通道,这时候左、右之间可以相互切换。
          任何时候倒车PA3倒车信号都能够触发(即使在左右触发未退出中),但是触发信号消失后同样不能返回。
          请教各位老师指点下,没有C语言基础的人啊,可能你们看起来小事一桩,我就是弄不过来,听说有个中断标志清除,但STM8S系列没有这个啊,顺便帮忙看看有其他不稳定的没有。
          拜托各位,弄好后再画板。
    -----------------------------------------------分割线,今天试过了,即使把中断输出放在其他端口,也是一样的,同时发现一个问题,中断按键短按一下可能成功返回,按长一点或者说重复按下就不能返回, 有个说法是中断里面尽量不用延时是不是?但是我这个左右切花信号是断续的额,不用延时不好处理,而且倒车信号也是持续低电平
    -----------------------------------

    贴代码:


    /******************************************************************
    * 实验名称及内容:LED
    ******************************************************************/
    #include "iostm8s003F3.h"//主控芯片的头文件
    /************************常用数据类型定义*************************/
    #define u8  uint8_t
    #define u16 uint16_t
    #define u32 uint32_t
    typedef unsigned char    uint8_t;
    typedef unsigned short   uint16_t;
    typedef unsigned long    uint32_t;

    /***********************端口/引脚定义区域*************************/
    #define KEY          PD_IDR_IDR3     //轻触按键
    #define R_OUT        PC_ODR_ODR4     //右切换
    #define L_OUT        PC_ODR_ODR5     //左切换
    #define F_OUT        PC_ODR_ODR6     //前切换
    #define V_OUT        PC_ODR_ODR7     //视频触发
    #define DVR_OUT      PC_ODR_ODR3     //录像机输出
    #define OUT          PC_ODR          //整体输出
    #define R_KEY        PB_IDR_IDR4     //右触发
    #define L_KEY        PB_IDR_IDR5     //左触发
    #define RE_KEY       PA_IDR_IDR3     //后触发,中断
    #define WINDOWS_KEY  PD_IDR_IDR2     //关窗触发,中断
    #define WINDOWS_OUT  PD_ODR_ODR4     //关窗输出

    /***********************用户自定义数据区域************************/
    u8 table[]={0x90,0xA0,0xC0,0x88,0x00};  //输出右,左,前,录像机,全灭

    /*************************函数声明区域****************************/
    void delay(u16 Count);//延时函数声明
    /**************************主函数区域*****************************/
    int main( void )
    {
      u8 i=0,a=0;
      PC_DDR_DDR3=1;     //配置PC4端口为输出模式
      PC_CR1_C13=1;      //配置PC4端口为推挽
      PC_CR2_C23=0;      //配置PC4端口低速率
      PC_DDR_DDR4=1;     //配置PC4端口为输出模式
      PC_CR1_C14=1;      //配置PC4端口为推挽
      PC_CR2_C24=0;      //配置PC4端口低速率
      PC_DDR_DDR5=1;     //配置PC5端口为输出模式
      PC_CR1_C15=1;      //配置PC5端口为推挽
      PC_CR2_C25=0;      //配置PC5端口低速率
      PC_DDR_DDR6=1;     //配置PC6端口为输出模式
      PC_CR1_C16=1;      //配置PC6端口为推挽
      PC_CR2_C26=0;      //配置PC6端口低速率
      PC_DDR_DDR7=1;     //配置PC7端口为输出模式
      PC_CR1_C17=1;      //配置PC7端口为推挽
      PC_CR2_C27=0;      //配置PC7端口低速率
      
      PD_DDR_DDR3=0;     //配置PD3端口为输入模式
      PD_CR1_C13=1;      //配置PD23端口为弱上拉
      PD_CR2_C23=0;      //配置PD23端口关中断
      PD_DDR_DDR4=1;     //配置PD5端口为输出
      PD_CR1_C14=1;      //配置PD5端口为推挽输出
      PD_CR2_C24=0;      //配置PD5端口为低速率输出
      

    OUT=0x90;            //开机右亮
    delay(1000);         
    OUT=0xa0;            //开机左亮
    delay(1000);
    OUT=0xc0;            //开机前亮
    delay(1000);
    OUT=0x88;            //开机录像机亮
    delay(1000);
    WINDOWS_OUT=1;
    delay(1000);
    OUT=0x00;            //全灭
    WINDOWS_OUT=0;

    asm("sim");

    ITC_SPR1=0XC0;    //配置PA端口优先级为3
    EXTI_CR1=0X80;   //配置PA,PB为下降沿和低电平触发,PD为下降沿触发

    PA_DDR_DDR3=0;   //PA3设置为输入,后触发开关
    PA_CR1_C13=1;    //PA3设置为弱上拉
    PA_CR2_C23=1;    //PA3设置为开中断

    PB_DDR_DDR4=0;   //PB4设置为输入,右触发开关
    PB_CR1_C14=1;    //PB4设置为弱上拉
    PB_CR2_C24=1;    //PB4设置开中断


    PB_DDR_DDR5=0;   //PB5设置为输入,左触发开关
    PB_CR1_C15=1;    //PB5设置为弱上拉
    PB_CR2_C25=1;    //PB5设置开中断



    PD_DDR_DDR2=0;  //PD2配置为输入,关窗触发
    PD_CR1_C12=1;   //PD2配置为输入弱上拉
    PD_CR2_C22=1;   //PD2配置为开中断



    asm("rim");


    while(1)
       {
          OUT=a;
    if(KEY==0)
         {
            delay(10);
           if(KEY==0)
             
            {
         
               
               OUT=table;
                i++;
               if(i>=5)
               {i=0;}
               while(!KEY);   
             }
          }
                            a=OUT;
        }

    }



    # pragma vector=0x05
    __interrupt void EXTI_PORTA_IRQHandler(void)

    {
       OUT=0X00;
       delay(1000);
       
    }

    # pragma vector=0x06
    __interrupt void EXTI_PORTB_IRQHandler(void)

    {
          
          
       delay(100);
       if(PB_IDR_IDR4==0)
      {
       OUT=0x90;
       delay(700);

       
      }

       if(PB_IDR_IDR5==0)
         
      {  
      OUT=0xA0;
      delay(700);

      }


    }



    # pragma vector=0x08
    __interrupt void EXTI_PORTD_IRQHandler(void)

    {
       PD_ODR_ODR4=1;
       delay(1000);
       PD_ODR_ODR4=0;
    }




    /****************************************************************/
    //延时函数delay(),有形参Count用于控制延时函数执行次数,无返回值
    /****************************************************************/
    void delay(u16 Count)
    {
      u8 i,j;
      while (Count--)//Count形参控制延时次数
      
        {for(i=0;i<50;i++)
          for(j=0;j<20;j++);}
      
      }


    回复 dsu_marcocopyright:copyright

    使用道具 举报

  • TA的每日心情
    开心
    2024-9-6 14:01
  • 签到天数: 233 天

    [LV.7]常住居民III

    发表于 2023-2-6 17:23 | 显示全部楼层
    中断里面不用延时。左右切花信号是断续,你可以用定时器

    点评

    我还达不到用定时器的级别啊,兄弟能不能帮我弄下,弄好了能理解,主要是没有语法基础,处于照虎画猫阶段  详情 回复 发表于 2023-2-6 17:28
    回复

    使用道具 举报

  • TA的每日心情
    开心
    2016-12-21 15:48
  • 签到天数: 11 天

    [LV.3]偶尔看看II

     楼主| 发表于 2023-2-6 17:28 来自手机 | 显示全部楼层
    dst 发表于 2023-2-6 17:23
    中断里面不用延时。左右切花信号是断续,你可以用定时器

    我还达不到用定时器的级别啊,兄弟能不能帮我弄下,弄好了能理解,主要是没有语法基础,处于照虎画猫阶段

    点评

    dst
    我年龄太大,血压也高,多年不弄了。  详情 回复 发表于 2023-2-6 17:30
    回复

    使用道具 举报

  • TA的每日心情
    开心
    2024-9-6 14:01
  • 签到天数: 233 天

    [LV.7]常住居民III

    发表于 2023-2-6 17:30 | 显示全部楼层
    阿甲 发表于 2023-2-6 17:28
    我还达不到用定时器的级别啊,兄弟能不能帮我弄下,弄好了能理解,主要是没有语法基础,处于照虎画猫阶段 ...

    我年龄太大,血压也高,多年不弄了。

    点评

    这里面老头子多  详情 回复 发表于 2023-2-6 17:31
    回复

    使用道具 举报

  • TA的每日心情
    开心
    2016-12-21 15:48
  • 签到天数: 11 天

    [LV.3]偶尔看看II

     楼主| 发表于 2023-2-6 17:31 来自手机 | 显示全部楼层
    dst 发表于 2023-2-6 17:30
    我年龄太大,血压也高,多年不弄了。

    这里面老头子多
    回复

    使用道具 举报

  • TA的每日心情
    开心
    2024-4-16 14:04
  • 签到天数: 127 天

    [LV.7]常住居民III

    发表于 2023-2-6 18:38 | 显示全部楼层
    思路是这样的,中断服务程序里尽量简单,只做一个清中断标识位和flag设置的动作。主程序根据flag的值再进行分支选择,做不同的事情。
    既然你这么写了,延时在中断函数里也没有问题,那么既然进了中断服务程序中,为何不先清中断?
    中断服务程序进来先把当前中断标识清一下试试。
    唠叨一句,贴个原理图或者示意图上来看看啊,看文字想了半天,

    点评

    你头像挺提神啊!  详情 回复 发表于 2023-2-7 08:29
    非常感谢,草图是这样的,刚开始学,刚会设置io,初始化,按键,中断都是强补的。所以设置中断标志和清标志位还不会。另外听说stm8s系列没有标志位,怎么清除呢  详情 回复 发表于 2023-2-6 19:37
    回复

    使用道具 举报

  • TA的每日心情
    开心
    2024-4-16 14:04
  • 签到天数: 127 天

    [LV.7]常住居民III

    发表于 2023-2-6 18:44 | 显示全部楼层
    同时发现一个问题,中断按键短按一下可能成功返回,按长一点或者说重复按下就不能返回,

    这个问题可能是按键抖动导致不停的进中断。按键加滤波电容没有?

    点评

    感谢,有两个按键特意设置了延时100还是10来检测毛刺,没有改善  详情 回复 发表于 2023-2-6 19:38
    回复

    使用道具 举报

  • TA的每日心情
    开心
    2016-12-21 15:48
  • 签到天数: 11 天

    [LV.3]偶尔看看II

     楼主| 发表于 2023-2-6 19:37 来自手机 | 显示全部楼层
    barla 发表于 2023-2-6 18:38
    思路是这样的,中断服务程序里尽量简单,只做一个清中断标识位和flag设置的动作。主程序根据flag的值再进行 ...

    非常感谢,草图是这样的,刚开始学,刚会设置io,初始化,按键,中断都是强补的。所以设置中断标志和清标志位还不会。另外听说stm8s系列没有标志位,怎么清除呢
    IMG_20230206_193317.jpg

    点评

    stm8没用过,所以中断标志是否可以清除这里不是很熟悉 想当然的回复你清中断。 网上你可以查查这种中断函数例程,应该有很多。  详情 回复 发表于 2023-2-6 21:03
    回复

    使用道具 举报

  • TA的每日心情
    开心
    2016-12-21 15:48
  • 签到天数: 11 天

    [LV.3]偶尔看看II

     楼主| 发表于 2023-2-6 19:38 来自手机 | 显示全部楼层
    barla 发表于 2023-2-6 18:44
    同时发现一个问题,中断按键短按一下可能成功返回,按长一点或者说重复按下就不能返回,

    这个问题可能是 ...

    感谢,有两个按键特意设置了延时100还是10来检测毛刺,没有改善
    回复

    使用道具 举报

  • TA的每日心情
    开心
    2024-4-16 14:04
  • 签到天数: 127 天

    [LV.7]常住居民III

    发表于 2023-2-6 20:58 | 显示全部楼层
    不知道你的delay是怎么计算的,和时钟相关,所以不好计算这个采样的时间

    __interrupt void EXTI_PORTB_IRQHandler(void)
    {
            u8 i;
            static uint8_t count[2] = {0};
            for ( i=0; i<8; i++ )
            {
                    delay(20);
                    count[0] = (PB_IDR_IDR4==0)?:(++count[0]):0;
                    count[1] = (PB_IDR_IDR5==0)?:(++count[1]):0;
            }
            if(count[0] >4 )
            {
                    OUT=0x90;        delay(700);
            }
            if(count[1] >4 )
            {
                    OUT=0xA0;        delay(700);
            }
    }
    这个中断函数你试试看,如果不行就调整delay(20);这个中间的20参数。
    你的图纸上,按键那里为何不加滤波电容?

    点评

    谢谢,这个左右延时主要是考虑转向灯(触发)频率是30秒闪动40次左右,大概不到一秒钟这样估计的,以保证重复触发。 明天我试试您这个函数,另外这个函数变量也要个主函数那个一样在后面声明吗?  详情 回复 发表于 2023-2-6 21:10
    回复

    使用道具 举报

  • TA的每日心情
    开心
    2023-1-20 08:48
  • 签到天数: 4 天

    [LV.2]偶尔看看I

    发表于 2023-2-6 21:02 来自手机 | 显示全部楼层
    每次进中断以后都没有清除相关中断标志

    点评

    是在刚进中断函数的时候加 还是在结束时加比如 asm"iret"这样语句嘛?  详情 回复 发表于 2023-2-6 21:15
    回复

    使用道具 举报

  • TA的每日心情
    开心
    2024-4-16 14:04
  • 签到天数: 127 天

    [LV.7]常住居民III

    发表于 2023-2-6 21:03 | 显示全部楼层
    阿甲 发表于 2023-2-6 19:37
    非常感谢,草图是这样的,刚开始学,刚会设置io,初始化,按键,中断都是强补的。所以设置中断标志和清标 ...

    stm8没用过,所以中断标志是否可以清除这里不是很熟悉
    想当然的回复你清中断。
    网上你可以查查这种中断函数例程,应该有很多。
    回复

    使用道具 举报

  • TA的每日心情
    开心
    2016-12-21 15:48
  • 签到天数: 11 天

    [LV.3]偶尔看看II

     楼主| 发表于 2023-2-6 21:10 来自手机 | 显示全部楼层
    barla 发表于 2023-2-6 20:58
    不知道你的delay是怎么计算的,和时钟相关,所以不好计算这个采样的时间

    __interrupt void EXTI_PORTB_IRQ ...

    谢谢,这个左右延时主要是考虑转向灯(触发)频率是30秒闪动40次左右,大概不到一秒钟这样估计的,以保证重复触发。
    明天我试试您这个函数,另外这个函数变量也要个主函数那个一样在后面声明吗?
    回复

    使用道具 举报

  • TA的每日心情
    开心
    2016-12-21 15:48
  • 签到天数: 11 天

    [LV.3]偶尔看看II

     楼主| 发表于 2023-2-6 21:12 来自手机 | 显示全部楼层
    另外,按键没加滤波是原来那个兄弟帮我做的时候也没有,软件又延时检测,主要的时候加也容易,软件弄好了再画板
    回复

    使用道具 举报

  • TA的每日心情
    开心
    2016-12-21 15:48
  • 签到天数: 11 天

    [LV.3]偶尔看看II

     楼主| 发表于 2023-2-6 21:15 来自手机 | 显示全部楼层
    拓荒牛 发表于 2023-2-6 21:02
    每次进中断以后都没有清除相关中断标志

    是在刚进中断函数的时候加
    还是在结束时加比如
    asm"iret"这样语句嘛?
    回复

    使用道具 举报

  • TA的每日心情
    擦汗
    2015-1-15 14:39
  • 签到天数: 6 天

    [LV.2]偶尔看看I

    发表于 2023-2-6 21:19 | 显示全部楼层
    像这种简单逻辑控制,使用8位MCU,汇编语言就可以搞定

    点评

    其实就现在写状态换个端口来加继电器也能实现,用纯4000逻辑电路也能实现。 就是有点意犹未尽的感觉,反正闲,又不急,实际上也不是刚需,就是学东西  详情 回复 发表于 2023-2-6 21:24
    回复

    使用道具 举报

  • TA的每日心情
    开心
    2016-12-21 15:48
  • 签到天数: 11 天

    [LV.3]偶尔看看II

     楼主| 发表于 2023-2-6 21:24 来自手机 | 显示全部楼层
    dqp05 发表于 2023-2-6 21:19
    像这种简单逻辑控制,使用8位MCU,汇编语言就可以搞定

    其实就现在写状态换个端口来加继电器也能实现,用纯4000逻辑电路也能实现。
    就是有点意犹未尽的感觉,反正闲,又不急,实际上也不是刚需,就是学东西

    点评

    对于新手,先不要同时使用几个中断; 像你这种逻辑判断,速度很慢,没必要使用中断,可以使用查询模式;  详情 回复 发表于 2023-2-6 21:29
    回复

    使用道具 举报

  • TA的每日心情
    擦汗
    2015-1-15 14:39
  • 签到天数: 6 天

    [LV.2]偶尔看看I

    发表于 2023-2-6 21:29 | 显示全部楼层
    阿甲 发表于 2023-2-6 21:24
    其实就现在写状态换个端口来加继电器也能实现,用纯4000逻辑电路也能实现。
    就是有点意犹未尽的感觉,反 ...

    对于新手,先不要同时使用几个中断;  
    像你这种逻辑判断,速度很慢,没必要使用中断,可以使用查询模式;


    点评

    查询法能够优先处理某个输出吗。还有处理完后能够返回到原来状态吗?是不是要先设置一个变量保存当前状态处理完后再回到当前状态?比如a=out,优先按键执行完后再执行out=a这样 我试过不成功,兄弟有空帮我完善一下  详情 回复 发表于 2023-2-6 21:47
    回复

    使用道具 举报

  • TA的每日心情
    开心
    2016-12-21 15:48
  • 签到天数: 11 天

    [LV.3]偶尔看看II

     楼主| 发表于 2023-2-6 21:47 来自手机 | 显示全部楼层
    dqp05 发表于 2023-2-6 21:29
    对于新手,先不要同时使用几个中断;  
    像你这种逻辑判断,速度很慢,没必要使用中断,可以使用查询模式 ...

    查询法能够优先处理某个输出吗。还有处理完后能够返回到原来状态吗?是不是要先设置一个变量保存当前状态处理完后再回到当前状态?比如a=out,优先按键执行完后再执行out=a这样
    我试过不成功,兄弟有空帮我完善一下可否?

    点评

    查询可以放在主程序里,只要 相关寄存器专用,就不需要保存变量; 举个例子,需要判断3个事情, A B C; 如果你想先判断A ,那你就先判断A,使用循环等待判断就行了,A被处理完毕,再跳转去判断下一个;  详情 回复 发表于 2023-2-6 21:57
    回复

    使用道具 举报

  • TA的每日心情
    擦汗
    2015-1-15 14:39
  • 签到天数: 6 天

    [LV.2]偶尔看看I

    发表于 2023-2-6 21:57 | 显示全部楼层
    本帖最后由 dqp05 于 2023-2-6 22:02 编辑
    阿甲 发表于 2023-2-6 21:47
    查询法能够优先处理某个输出吗。还有处理完后能够返回到原来状态吗?是不是要先设置一个变量保存当前状态 ...

    查询可以放在主程序里,只要 相关寄存器专用,就不需要保存变量;
    举个例子,需要判断3个事情, A B C;

    如果你想先判断A ,那你就先判断A,使用循环等待判断就行了,A被处理完毕,再往下执行,判断下一个事情;



    点评

    这个是有执行中插入的,比如按键选择了显示前摄像头,但是用途左转向,这时候需要立刻切换到左摄像头,转向完成电平消失后要能够自动返回原来的前摄像头,轮询没办法返回,所以才学习中断  详情 回复 发表于 2023-2-6 22:10
    回复

    使用道具 举报

    本版积分规则

    小黑屋|手机版|Archiver|论坛自带搜索|下载论坛app|手电大家谈-手电筒爱好者之家 ( 备案序号:鲁ICP备05002565号 )
    以上言论纯属个人观点,与手电大家谈立场无关。
    最佳浏览模式:1920*1080


    GMT+8, 2024-11-18 16:24 , Processed in 0.237554 second(s), 81 queries , Gzip On.

    Powered by Discuz! X3.4

    © 2001-2023 Discuz! Team.

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