OpenEdv-开源电子网

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

十三章定时器中断实验进不了中断,困惑了一个月了。

[复制链接]

11

主题

86

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
354
金钱
354
注册时间
2012-4-26
在线时间
70 小时
发表于 2013-1-7 11:53:59 | 显示全部楼层 |阅读模式
是这样的,以前我做串口实验也没成功,可能代码是我自已一个字母一个字母敲的原因吧(我不喜欢复制,粘贴别人的代码,即使有,我也是对着别人的代码敲出来)。想着做以后的实验说不定回过头来看,可能当时做不了的就会有恍然大悟的感觉。。。但是定时器实验里也用到了NVIC,实验现像为一上电红灯DS0常亮,绿灯无反应,不亮,估计进不了中断。

上代码:
#include "sys.h"
#include "led.h"
#include "delay.h"
#include "timer.h"

int main(void)
{
stm32_clock_init(9);
led_init();
delay_init(72);
tim3_init(4999,7199);
while (1)
{
LED0 = !LED0;
delay_ms(500);
}
}
这是我的main函数。



然后是sys.c
#include "sys.h"
#include "nvic.h"
void my_nvic_priority_group_config(u8 nvic_group)
{
u32 temp, temp1;
temp1   = (~nvic_group) & 0x07;
temp1 <<= 8;
temp    = SCB->AIRCR;
temp   &= 0x0000F8FF;
temp   |= 0x05FA0000;
temp   |= temp1;
SCB->AIRCR = temp;
}
void my_nvic_init(u8 nvic_preemptionpriority, u8 nvic_subpriority, u8 nvic_channel, u8 nvic_group)
{
u32 temp;

u8 ipr_addr   = nvic_channel / 4;
u8 ipr_offset = nvic_channel % 4;
ipr_offset    = ipr_offset * 8 + 4;

my_nvic_priority_group_config(nvic_group);

temp  = nvic_preemptionpriority << (4 - nvic_group);
temp |= nvic_subpriority & (0x0f >> nvic_group);
temp &= 0xF;

if (nvic_channel < 32)
{
NVIC->ISER[0] |= 1 << nvic_channel;
}
else
{
NVIC->ISER[1] |= 1 << (nvic_channel - 32);
}

NVIC->IPR[ipr_addr] |= temp << ipr_offset;

}

//void ex_nvic_config(u8 gpiox, u8 bitx, u8 trim)
//{
// u8 ext_addr;
// u8 ext_offset;
//
// ext_addr = bitx / 4;
// ext_offset = (bitx % 4) * 4;
// RCC->APB2ENR |= 0x01;
//
// AFIO->EXTICR[ext_addr] &= ~(0x000F << ext_offset);
// AFIO->EXTICR[ext_addr] |= gpiox << ext_offset;
//
// EXTI->IMR |= 1 << bitx;
//
// if (trim & 0x01)
// {
// EXTI->FTSR |= 1 << bitx;
// }
//
// if (trim & 0x02)
// {
// EXTI->RTSR |= 1 << bitx;
// }
//}

void my_nvic_set_vector_table(u32 nvic_vect_tab, u32 offset)
{
SCB->VTOR = nvic_vect_tab | (offset & (u32)0x1FFFFF80);
}

void myrcc_deinit(void)
{
RCC->APB1RSTR = 0x00000000;
RCC->APB2RSTR = 0x00000000;

RCC->AHBENR   = 0x00000014;     //bit[4]=1,flash clock enable bit[2]=1,sram clock enable
RCC->APB2ENR  = 0x00000000;     //peripheral clock close
RCC->APB1ENR  = 0x00000000;     
RCC->CR      |= 0x00000001;     //HSION=1,internal 8MHz osc open
RCC->CFGR    &= 0xF8FF0000;     //reset MCO[2:0]=000,ADCPRE[1:0],PPRE2[2:0],PPRE1[2:0],HPRE[3:0],SW[1:0]
RCC->CR      &= 0xFEF6FFFF; //PLLON=0,PLL close.CSSON=0.HSEON=0,HSE osc close.
RCC->CR      &= 0xFFFBFFFF;     //HSEBYP=0.
RCC->CFGR    &= 0xFF80FFFF;     //reset PLLSRC,PLLXTPRE,PLLMUL[3:0],USBPRE.
RCC->CIR      = 0x00000000;

#ifdef VECT_TAB_RAM
my_nvic_set_vector_table(NVIC_VECT_TAB_RAM,0x0);
#else
my_nvic_set_vector_table(NVIC_VECT_TAB_FLASH,0x0);
#endif
}


void stm32_clock_init(u8 pll)
{
u8 temp = 0;

myrcc_deinit();

RCC->CR    |= 0x00010000;          //HSEON=1
while ((RCC->CR >> 17) == 0) //0 external 4-16MHz osc not ready
;
RCC->CFGR   = 0x00000400;         //bit[7:4]=0,AHB=DIV1  bit[13:11]=0,APB2=DIV1  bit[10:8]=100,APB1=DIV2
pll        -= 2;
RCC->CFGR  |= pll << 18;         //PLLMUL x9
RCC->CFGR  |= 1 << 16;           //PLLSRC=1,HSE clock
FLASH->ACR |= 0x32; 

RCC->CR    |= 0x01000000;        //PLLON=1,PLL enable
while ((RCC->CR >> 25) == 0)    //wait for PLL lock
;
RCC->CFGR  |= 0x00000002;        //bit[1:0]PLL as SYSCLK
while (temp != 0x02)
{
temp  = RCC->CFGR >> 2;
temp &= 0x03; 
}
}

//----------------------------------------------------------------------------------------------------------------------------------------------
timer.c




#include "led.h"
#include "type.h"
#include "map.h"
#include "nvic.h"
void tim3_init(u16 arr,u16 psc)
{
RCC->APB1ENR |= 1 << 1;
TIM3->ARR     = arr;
TIM3->SC     = psc;
TIM3->DIER   |= 1 << 0;      //UIE=1,enable update interrupt
TIM3->CR1    |= 0x01;        //bit[0]CEN=1,enable tim3
my_nvic_init(1,3,TIM3_IRQ_CHANNEL,2);                                //这一句,我注释掉的话,DS0可以以0.5S间隔闪烁,没注释的话,一上电,DS0就常亮,感觉程序死在那里了。
}

void tim3_irq_handler(void)
{
if (TIM3->SR & 0x0001)
{
LED1 = !LED1;
}
TIM3->SR &= ~(1 << 0);
}






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

使用道具 举报

2

主题

100

帖子

1

精华

中级会员

Rank: 3Rank: 3

积分
278
金钱
278
注册时间
2012-4-15
在线时间
0 小时
发表于 2013-1-7 12:32:37 | 显示全部楼层
我也有这个的习惯啊!也是经常敲完了之后不能正常工作。有时候找不到出错的地方了,就用正确的代码一部分一部分地替换,这样可以缩小查找错误的范围,一般都可以找出问题的。
喜欢单片机,没什么道理,就像爱吃水煮鱼,对味而已。
回复 支持 反对

使用道具 举报

13

主题

91

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
235
金钱
235
注册时间
2012-11-17
在线时间
18 小时
发表于 2013-1-7 12:54:10 | 显示全部楼层
TIMx_DIER寄存器的位6你没有设置

其实我不明白TIMx_DIER的位6是怎么回事,但原子大哥的书上说如果使用到TIM的中断,该位必须设置为1,你将这句代码加进去看下

TIM3->DIER|=1<<6;  //允许触发中断

还有,红色字体里面表示TIM3中断的中断通道,似乎应该不是全大写字母吧,应该是这个TIM3_IRQChannel ?没留意过这个的大小写有没影响。
回复 支持 反对

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165540
金钱
165540
注册时间
2010-12-1
在线时间
2117 小时
发表于 2013-1-7 13:05:56 | 显示全部楼层
是:TIM3_IRQChannel
加上这句死机,说明你的中断服务函数不对.
你在.s文件里面,找一下中断服务函数的名字,看看和你写的一样不.
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复 支持 反对

使用道具 举报

11

主题

86

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
354
金钱
354
注册时间
2012-4-26
在线时间
70 小时
 楼主| 发表于 2013-1-7 13:45:01 | 显示全部楼层
回复【3楼】bj2008wyou:

TIMx_DIER寄存器的位6你没有设置
其实我不明白TIMx_DIER的位6是怎么回事,但原子大哥的书上说如果使用到TIM的中断,该位必须设置为1,你将这句代码加进去看下
TIM3->DIER|=1<<6;  //允许触发中断
还有,红色字体里面表示TIM3中断的中断通道,似乎应该不是全大写字母吧,应该是这个TIM3_IRQChannel ?没留意过这个的大小写有没影响。

---------------------------------
以下是我的nvic.h文件,全大写是我的一个习惯,因为是宏定义。
#ifndef _NVIC_H
#define _NVIC_H



//#define USART1_IRQ_CHANNEL        ((u8)0x25)
//#define EXTI0_IRQ_CHANNEL         ((u8)0x06)
//#define EXTI1_IRQ_CHANNEL         ((u8)0x07)
//#define EXTI2_IRQ_CHANNEL         ((u8)0x08)
//#define EXTI3_IRQ_CHANNEL         ((u8)0x09)
//#define EXTI4_IRQ_CHANNEL         ((u8)0x0A)
//#define WWDG_IRQ_CHANNEL          ((u8)0x00)
#define TIM3_IRQ_CHANNEL          ((u8)0x1D)



#define NVIC_VECT_TAB_RAM         ((u32)0x20000000)
#define NVIC_VECT_TAB_FLASH       ((u32)0x08000000)

#endif
回复 支持 反对

使用道具 举报

11

主题

86

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
354
金钱
354
注册时间
2012-4-26
在线时间
70 小时
 楼主| 发表于 2013-1-7 13:57:14 | 显示全部楼层
回复【4楼】正点原子:

是:TIM3_IRQChannel
加上这句死机,说明你的中断服务函数不对.
你在.s文件里面,找一下中断服务函数的名字,看看和你写的一样不.

---------------------------------
不太懂原子的意思,这个TIM3_IRQChannel一定要写成这样么?只要我跟nvic.h宏定义里的一样就行了吧?
我晚上回家再试试。
回复 支持 反对

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165540
金钱
165540
注册时间
2010-12-1
在线时间
2117 小时
发表于 2013-1-7 14:37:44 | 显示全部楼层
TIM3_IRQChannel,一定要和nvic.h定义内容一样就可以了.
记得新版本的都是TIM3_IRQn,这样来定义的.
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复 支持 反对

使用道具 举报

11

主题

86

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
354
金钱
354
注册时间
2012-4-26
在线时间
70 小时
 楼主| 发表于 2013-1-8 08:33:59 | 显示全部楼层
正如原子所言,的确是.S文件里的涵数名与我定义的不一致所引起的。.S文件里定义为"TIM3_IRQHandler",而我的timer.c定义为“void tim3_irq_handler(void)”,后来将我定义的改为.S文件里的名字,则运行正常了。想不到.S文件里还有这学问,学习了,谢谢原子,也谢谢大家的关注和帮忙。
回复 支持 反对

使用道具 举报

0

主题

9

帖子

0

精华

初级会员

Rank: 2

积分
53
金钱
53
注册时间
2014-2-16
在线时间
5 小时
发表于 2015-7-19 22:07:05 | 显示全部楼层
学习了~谢谢
回复 支持 反对

使用道具 举报

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

本版积分规则



关闭

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

正点原子公众号

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

GMT+8, 2025-6-19 20:38

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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