请教各位老师,STM8中断执行后不能返回
话说年纪大了,做东西动不动就是世纪工程,弄个几年的感觉也不急了。背景,懂点硬件,原来画图用 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 u8uint8_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_KEYPD_IDR_IDR2 //关窗触发,中断
#define WINDOWS_OUTPD_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++);}
}
中断里面不用延时。左右切花信号是断续,你可以用定时器 dst 发表于 2023-2-6 17:23
中断里面不用延时。左右切花信号是断续,你可以用定时器
我还达不到用定时器的级别啊,兄弟能不能帮我弄下,弄好了能理解,主要是没有语法基础,处于照虎画猫阶段 阿甲 发表于 2023-2-6 17:28
我还达不到用定时器的级别啊,兄弟能不能帮我弄下,弄好了能理解,主要是没有语法基础,处于照虎画猫阶段 ...
我年龄太大,血压也高,多年不弄了。
dst 发表于 2023-2-6 17:30
我年龄太大,血压也高,多年不弄了。
这里面老头子多 思路是这样的,中断服务程序里尽量简单,只做一个清中断标识位和flag设置的动作。主程序根据flag的值再进行分支选择,做不同的事情。
既然你这么写了,延时在中断函数里也没有问题,那么既然进了中断服务程序中,为何不先清中断?
中断服务程序进来先把当前中断标识清一下试试。
唠叨一句,贴个原理图或者示意图上来看看啊,看文字想了半天, 同时发现一个问题,中断按键短按一下可能成功返回,按长一点或者说重复按下就不能返回,
这个问题可能是按键抖动导致不停的进中断。按键加滤波电容没有? barla 发表于 2023-2-6 18:38
思路是这样的,中断服务程序里尽量简单,只做一个清中断标识位和flag设置的动作。主程序根据flag的值再进行 ...
非常感谢,草图是这样的,刚开始学,刚会设置io,初始化,按键,中断都是强补的。所以设置中断标志和清标志位还不会。另外听说stm8s系列没有标志位,怎么清除呢 barla 发表于 2023-2-6 18:44
同时发现一个问题,中断按键短按一下可能成功返回,按长一点或者说重复按下就不能返回,
这个问题可能是 ...
感谢,有两个按键特意设置了延时100还是10来检测毛刺,没有改善 不知道你的delay是怎么计算的,和时钟相关,所以不好计算这个采样的时间
__interrupt void EXTI_PORTB_IRQHandler(void)
{
u8 i;
static uint8_t count = {0};
for ( i=0; i<8; i++ )
{
delay(20);
count = (PB_IDR_IDR4==0)?:(++count):0;
count = (PB_IDR_IDR5==0)?:(++count):0;
}
if(count >4 )
{
OUT=0x90; delay(700);
}
if(count >4 )
{
OUT=0xA0; delay(700);
}
}
这个中断函数你试试看,如果不行就调整delay(20);这个中间的20参数。
你的图纸上,按键那里为何不加滤波电容?
每次进中断以后都没有清除相关中断标志 阿甲 发表于 2023-2-6 19:37
非常感谢,草图是这样的,刚开始学,刚会设置io,初始化,按键,中断都是强补的。所以设置中断标志和清标 ...
stm8没用过,所以中断标志是否可以清除这里不是很熟悉{:5_624:}
想当然的回复你清中断。
网上你可以查查这种中断函数例程,应该有很多。
barla 发表于 2023-2-6 20:58
不知道你的delay是怎么计算的,和时钟相关,所以不好计算这个采样的时间
__interrupt void EXTI_PORTB_IRQ ...
谢谢,这个左右延时主要是考虑转向灯(触发)频率是30秒闪动40次左右,大概不到一秒钟这样估计的,以保证重复触发。
明天我试试您这个函数,另外这个函数变量也要个主函数那个一样在后面声明吗? 另外,按键没加滤波是原来那个兄弟帮我做的时候也没有,软件又延时检测,主要的时候加也容易,软件弄好了再画板 拓荒牛 发表于 2023-2-6 21:02
每次进中断以后都没有清除相关中断标志
是在刚进中断函数的时候加
还是在结束时加比如
asm"iret"这样语句嘛? 像这种简单逻辑控制,使用8位MCU,汇编语言就可以搞定 dqp05 发表于 2023-2-6 21:19
像这种简单逻辑控制,使用8位MCU,汇编语言就可以搞定
其实就现在写状态换个端口来加继电器也能实现,用纯4000逻辑电路也能实现。
就是有点意犹未尽的感觉,反正闲,又不急,实际上也不是刚需,就是学东西 阿甲 发表于 2023-2-6 21:24
其实就现在写状态换个端口来加继电器也能实现,用纯4000逻辑电路也能实现。
就是有点意犹未尽的感觉,反 ...
对于新手,先不要同时使用几个中断;
像你这种逻辑判断,速度很慢,没必要使用中断,可以使用查询模式;
dqp05 发表于 2023-2-6 21:29
对于新手,先不要同时使用几个中断;
像你这种逻辑判断,速度很慢,没必要使用中断,可以使用查询模式 ...
查询法能够优先处理某个输出吗。还有处理完后能够返回到原来状态吗?是不是要先设置一个变量保存当前状态处理完后再回到当前状态?比如a=out,优先按键执行完后再执行out=a这样
我试过不成功,兄弟有空帮我完善一下可否? 本帖最后由 dqp05 于 2023-2-6 22:02 编辑
阿甲 发表于 2023-2-6 21:47
查询法能够优先处理某个输出吗。还有处理完后能够返回到原来状态吗?是不是要先设置一个变量保存当前状态 ...
查询可以放在主程序里,只要 相关寄存器专用,就不需要保存变量;
举个例子,需要判断3个事情, A B C;
如果你想先判断A ,那你就先判断A,使用循环等待判断就行了,A被处理完毕,再往下执行,判断下一个事情;