单片机STM8S903K3 。
void main(void)
{
clock_inti();//时钟初始化
io_inti();//IO口初始化
while(1)
{
PC_ODR|=0x80;
}
以上程序可以将LED指示灯点亮,但如下面程序:加入基准定时程序后,指示灯怎么样也点不亮,不知道什么原因?
定时器初始化程序
void timer6_50us(void)//配置50Us中断的寄存器状态
{
TIM6_CR1=0X01;//使能TIM6计数功能,使能预装载寄存器
TIM6_IER=0X01;//使能更新中断
TIM6_CNTR=0X64;//给计数器附初值为0X64;计数100次为50uS
TIM6_PSCR=0X00;//主时钟未分频后做为定时器时钟,频率:2M
TIM6_ARR=0x64;//给预装载寄存器赋值0x64
}
主程序
void main(void)
{
clock_inti();
io_inti();
timer6_50us();
while(flag_1ms==1)
{
PC_ODR|=0x80;
}
中断服务程序
@far @interrupt void TIM6_UPD_OVF_TRG_IRQHandler(void)
{
count_50us++;
if(count_50us>=20)
{
flag_1ms=1;
count_50us=0;
}
}
本人新手,请各位看官不吝指导!
1. 总中断开在哪了?
2. 中断服务程序为什么不清楚溢出标志位?
3.为什么配置TIM6要先使能计数器?为什么不启用软件更新?
正规的操作是配置完毕后进行软件更新确保各寄存器在开启定时器后立即生效。请认真再看一遍有关PSCR等寄存器的说明。
4.建议不要再计数器允许的时候改写CNTR的值。
5.我也不明白为什么要给CNTR赋初值?而且还跟ARR一样?难道你不知道TIM6计数器是单向上计数?。
我的TIM6配置格式如下。
TIM6_ARR=0X64;
TIM6_PSCR=0X00;
TIM6_CR1=0X84;//使能预装载,仅计数器溢出发送中断请求。
TIM6_EGR=0X01;//软件更新TIM6所有寄存器
TIM6_SR1=0X00;//清除溢出标志位。
TIM6_IER=0X01;//开启溢出中断
TIM6_CR1|=0X01;//开启计数器
别忘了开总中断,还有在中断服务程序里清除溢出标志位,否则,到时你试下就知道会出现什么现象了。
额。。。多谢大哥指教啊。
按照你的提示将程序做了下修改,程序是可以进中断了,但是还是有些问题。主循环里灯还是点不亮,真是郁闷。单步运行了一下,程序进了中断后就在中断程序里循环,不跳出来了,这是什么原因?。把程序贴出来,请更多些指点。
void timer6_50us(void)//配置50us中断的寄存器状态
{
TIM6_ARR=0X64;
TIM6_PSCR=0X00;
TIM6_CR1=0X84;
TIM6_EGR=0X01;
TIM6_SR=0X00;
TIM6_IER=0X01;
TIM6_CR1|=0X01;
}
void main(void)
{
_asm("sim");
clock_inti();
io_inti();
_asm("rim");
timer6_50us();
while(flag_1ms==1)
{
PC_ODR|=0x80;
}
}
中断服务程序:
#include"stm8s903k3.h"
typedef void @far (*interrupt_handler_t)(void);
extern void _stext(); /* startup routine */
extern flag_1ms;
extern count_50us;
struct interrupt_vector {
unsigned char interrupt_instruction;
interrupt_handler_t interrupt_handler;
};
@far @interrupt void NonHandledInterrupt (void)
{
/* in order to detect unexpected events during development,
it is recommended to set a breakpoint on the following instruction
*/
return;
}
@far @interrupt void TIM6_UPD_OVF_TRG_IRQHandler(void)
{
TIM6_SR=0X00;
//count_songsi++;
count_50us++;
if(count_50us>=1)
{
flag_1ms=1;
count_50us=0;
}
return;
}
extern void _stext(); /* startup routine */
将主程序做了点小的修改,程序如下。却又进不了中断了。我超级郁闷啊!
main()
{
_asm("sim");
clock_inti();
io_inti();
_asm("rim");
while(1)
{
timer6_50us();
if(flag_1ms==1)
PC_ODR|=0x80;
}
}
你中断向量那边有没有做对啊。
中断了跳不出来,看你的程序也清状态了啊,应该可以跳出来啊,还是要你自己好好检查一下的。这么简单的东西不应该会有什么问题。
你怎么把timer6_50us()这个函数放在while循环!!!这样不停的初始化TIM6当然会出问题啦!
进去中断出不来,如果清除了标志位正常情况是会返回的。。。你编译后有没有出现警告?
还有一点,extern flag_1ms;在我的编译器里是会提示这是个错误。要我改成extern unsigned char flag_1ms;才通过编译。真是奇怪。。
如果是每次中断都只能进去而不能出来,而且又清除了标志位,那我怀疑,是不是中断已经跳出来但是你不知道它已经跳出来了!
从你主程序中的while循环可以看出,如果不满足flag_1ms=1,括号里的程序是不执行的。这种情况下你的调试断点假设是在PC_ODR|=0x80;语句,那么就算中断跳出来也不会执行PC_ODR|=0x80;语句!造成一种中断似乎没有跳出来的假象!
如果以上看的不是很明白,我直接说我的该法
void main(void)
{
_asm("sim");
clock_inti();
io_inti();
_asm("rim");
timer6_50us();
while(1)
{
while(flag_1ms==1)
{
PC_ODR|=0x80;
}
PC_ODR|=0x80;//多出一条语句,把断点设在这里检查中断是否有跳出。
}
}
还有把所有变量都赋上初值。如果还搞不定,唉。。。
如果
呵呵,8楼的是专家级别,几个问题都让你看出来了。问题已经解决了的。你说的对,基准定时程序应该放在主循环外面;另外在中断程序里变量的声明是要声明类型的,你用的什么编译器,这么好,帮你指出问题了。我用的COSMIC,开始没申明变量的数据类型,编译可以通过,但是中断程序里变量不起做用,执行了变量的赋值语句,但是变量的值始终不变,为零。就这个问题昨天害我瞎折腾了一天,郁闷啊!中断的跳出好象只要在return语句之前清了中断标志,就好了。全让你说对了,佩服啊!
我用的也是COSMIC,关于外部变量声明需要同时声明类型,我遇到过跟你一样的问题,当时也是拉网式搜索了一整天才锁定是这个地方出问题,具体原因,我也不明白,总之我记得以后不能不声明类型了。