数码之家

 找回密码
 立即注册
搜索
查看: 1611|回复: 28

请教各位老师,STM8中断执行后不能返回

[复制链接]
发表于 2023-2-6 10:51:36 | 显示全部楼层 |阅读模式

爱科技、爱创意、爱折腾、爱极致,我们都是技术控

您需要 登录 才可以下载或查看,没有账号?立即注册

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






 楼主| 发表于 2023-2-6 10:54:19 | 显示全部楼层
请各位老师指点下,不要怕打击我,本来就是不懂,弄好这个一个个学习
回复 支持 反对

使用道具 举报

发表于 2023-2-6 12:35:02 来自手机浏览器 | 显示全部楼层
我没写过STM8点程序,根据一般单片机程序提几点:
1.不知道有没有使能看门狗,好像没看到清看门狗的程序;
2.不知道中断请求标志是否需要手动清除,如果硬件不自动清中断请求标志而又没有手动清,会导致程序频繁反复进入中断服务程序。在中断中调用和主循环一样的delay()函数是有风险的,除非改函数可重入,虽然多数人都不主张在中断中断中调用延时程序,但是,如果你一定要那么做,建议把延时程序复制一份另起一个函数名,如isr_delay(),专供中断服务程序调用(如果有多个不同优先级中断服务程序需要延时,也不要调用相同的函数)。
3.就实际应用而言,简单的延时读按键没有多次确认可靠。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-2-6 13:51:35 来自手机浏览器 | 显示全部楼层
mmxx2015 发表于 2023-2-6 12:35
我没写过STM8点程序,根据一般单片机程序提几点:
1.不知道有没有使能看门狗,好像没看到清看门狗的程序;
...

谢谢您,我也有点怀疑是延时函数名称,度娘搜索也有这个说法
另外,没用看门狗,这个要再学习才懂,这个芯片看资料没有中断标志,所以这没有清除,不知道是不是(其实也没会写中断标志清除)
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-2-6 17:07:20 | 显示全部楼层
今天试过了,即使把中断输出放在其他端口,也是一样的,同时发现一个问题,中断按键短按一下可能成功返回,按长一点或者说重复按下就不能返回, 有个说法是中断里面尽量不用延时是不是?但是我这个左右切换信号是断续的啊,不用延时不好处理,而且倒车信号也是持续低电平
回复 支持 反对

使用道具 举报

发表于 2023-2-6 17:41:05 | 显示全部楼层
本帖最后由 mmxx2015 于 2023-2-6 17:42 编辑
阿甲 发表于 2023-2-6 17:07
今天试过了,即使把中断输出放在其他端口,也是一样的,同时发现一个问题,中断按键短按一下可能成功返回, ...
不是端口的问题,从你描述的现象看,好像是频繁进入中断了。

函数重入问题:非重入函数在主循环和中断中同时调用会导致局部变量冲突。

可以增加一个函数
  1. void isr_delay(u16 Count)
  2. {
  3.   u8 i,j;
  4.   while (Count--)//Count形参控制延时次数
  5.   
  6.     {for(i=0;i<50;i++)
  7.       for(j=0;j<20;j++);}
  8.   
  9.   }
复制代码
中断中用这个函数延时
  1. # pragma vector=0x05
  2. __interrupt void EXTI_PORTA_IRQHandler(void)

  3. {
  4.    OUT=0X00;
  5.    isr_delay(1000);
  6.    
  7. }
复制代码

不在中断中延时也不难:在中断中关闭中断,设置一个标志,主循环判断这个标志为1则多次读取这个引脚状态确认按键,处理完再次打开中断即可。如果你的应用不需要休眠,根本不需要打开中断。

回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-2-6 18:03:56 来自手机浏览器 | 显示全部楼层
mmxx2015 发表于 2023-2-6 17:41
不是端口的问题,从你描述的现象看,好像是频繁进入中断了。

函数重入问题:非重入函数在主循环和中断中同 ...

谢谢您,link放单位了,明天我试下这个不同延时函数
另外我这个用中断的原因就是要强切,不用中断的话我不懂还有其他方式能行。
您最后一段设置标志位我还不懂。
回复 支持 反对

使用道具 举报

发表于 2023-2-6 19:43:40 | 显示全部楼层
加中断清除试试
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-2-6 20:58:06 来自手机浏览器 | 显示全部楼层
qq1329491328 发表于 2023-2-6 19:43
加中断清除试试

记得有人说stm8s系列是没有中断标志的。
话说就是在中断程序最后一句加上
asm"iret"吗?
回复 支持 反对

使用道具 举报

发表于 2023-2-6 21:49:01 来自手机浏览器 | 显示全部楼层
进中断后马上读取引脚状态寄存器…stm8好像只能这样子看中断状态…
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-2-6 22:12:23 来自手机浏览器 | 显示全部楼层
触景情伤 发表于 2023-2-6 21:49
进中断后马上读取引脚状态寄存器…stm8好像只能这样子看中断状态…

是不是要先设置一个变量保存当前状态处理完后再回到当前状态?比如a=out,优先按键执行完后再执行out=a这样
我试过不成功,兄弟有空帮我完善一下可否?
回复 支持 反对

使用道具 举报

发表于 2023-2-7 07:26:17 来自手机浏览器 | 显示全部楼层
阿甲 发表于 2023-2-6 22:12
是不是要先设置一个变量保存当前状态处理完后再回到当前状态?比如a=out,优先按键执行完后再执行out=a这 ...

就是这个样子,中断里面不要延时…只做判断…我现在都没时间玩这个了…
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-2-7 08:08:07 来自手机浏览器 | 显示全部楼层
触景情伤 发表于 2023-2-7 07:26
就是这个样子,中断里面不要延时…只做判断…我现在都没时间玩这个了… ...

谢谢,但是中断后执行的东西需要延时一段时间啊,这个怎么实现?
回复 支持 反对

使用道具 举报

发表于 2023-2-7 09:08:40 | 显示全部楼层
本帖最后由 kkstun 于 2023-2-7 09:09 编辑
阿甲 发表于 2023-2-7 08:08
谢谢,但是中断后执行的东西需要延时一段时间啊,这个怎么实现?

用两个定时器,或者一个定时器两个标识,计数,判断。
回复 支持 反对

使用道具 举报

发表于 2023-2-7 09:21:23 | 显示全部楼层
大概搜索了一下,STM8S系列没有中断标志位,老哥的问题应该是反复多次进入中断,导致程序跑飞了,老哥可以看一下这个帖子下面的回复:
https://www.amobbs.com/thread-5478987-1-1.html
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-2-7 10:40:29 | 显示全部楼层
kkstun 发表于 2023-2-7 09:08
用两个定时器,或者一个定时器两个标识,计数,判断。

我不会定时器啊刚会端口定义,按键+1这样
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-2-7 10:42:13 | 显示全部楼层
wangxiangtan2 发表于 2023-2-7 09:21
大概搜索了一下,STM8S系列没有中断标志位,老哥的问题应该是反复多次进入中断,导致程序跑飞了,老哥可以 ...

谢谢,估计也是这样或者延时问题。其实这个不用中断,用继电器➕按键端口也能强制改变达到逻辑目的,就是意犹未尽,反正不急,慢慢学
回复 支持 反对

使用道具 举报

发表于 2023-2-7 10:48:36 | 显示全部楼层
STM8S的外部中断没有中断标志位可供清除,进中断先关闭中断呢。或者用定时器捕获试试。
回复 支持 反对

使用道具 举报

发表于 2023-2-7 12:52:47 来自手机浏览器 | 显示全部楼层
阿甲 发表于 2023-2-7 08:08
谢谢,但是中断后执行的东西需要延时一段时间啊,这个怎么实现?

写一个调用延时函数给执行功能里面用…
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-2-7 23:11:46 来自手机浏览器 | 显示全部楼层
触景情伤 发表于 2023-2-7 12:52
写一个调用延时函数给执行功能里面用…

这个还不会写呢。能帮忙写一段吗?
回复 支持 反对

使用道具 举报

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

本版积分规则

APP|手机版|小黑屋|关于我们|联系我们|法律条款|技术知识分享平台

闽公网安备35020502000485号

闽ICP备2021002735号-2

GMT+8, 2025-5-3 00:53 , Processed in 0.171600 second(s), 10 queries , Redis On.

Powered by Discuz!

© 2006-2025 MyDigit.Net

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