1、任务计划
2、计划完成度
(1)今天一天只是做第一个任务,就调试了一天呢~对着一块32的板子,已经改了无数遍程序了。每改一遍程序,调的没有错误了,就开始下载,下载了再观察呢。我是先设置了LED1为1s闪烁一次,然后一遍一遍的对照着LED0开始计算LED1是不是已经达到了循环的要求。
[1]每隔一秒闪烁 ,则周期为2;每隔2s闪烁则周期为4;每隔3s闪烁,周期为6;所以整体的周期就是2+4+6=12s。
[2]我先是用flag作为标记,每当判断进入一次中断成立,if(TIM_GetITStatus(TIM3,TIM_IT_Update)==SET)flag就++。因为周期为12,我就直接设置flag=flag%12。
[3]刚开始写条件判断的时候,我是用的switch语句:
switch(flag)
{
case1: LED0=!LED1,SIH0=!SHI0;
case3: LED0=!LED1,SIH0=!SHI0;
case7: LED0=!LED1,SIH0=!SHI0;
defult: ;
}
TIM_ClearITPendingBit(TIM3,TIM_IT_Update);
结果灯每秒都会闪烁一次。
[4]我刚开始开始设置以2,以3为周期的时候,设置计数时钟不知弄哪个函数,我就改了if(TIM_GetITStatus(TIM3,TIM_IT_Update)==SET),把其中的TIM3改为2*TIM3,3*TIM3,结果不符合STM32的使用规则,不能实现周期的改动。
[5]后来学姐跟我讲,其实她是想让我用STM32的库函数TIM_SetAutoreload(TIM3,20000)来设置 TIMx 自动重装载寄存器值,这样当flag=3的时候,就可以实现以2为周期的循环了。
[6]我就和之前的switch语句结合了一下
switch(flag)
{
//case1: LED0=!LED1,SIH0=!SHI0;
case3:TIM_SetAutoreload(TIM3,2000);
case7:TIM_SetAutoreload(TIM3,3000);
defult: ;
}
LED0=!LED1;
SIH0=!SHI0;
TIM_ClearITPendingBit(TIM3,TIM_IT_Update);
大体思路是有的,但是每次调整这个条件语句的条件语句和执行语句,以及清除标志位的时候,基本上都是每秒循环一次,还有可能就是所有的灯都灭掉,连我设置的指示灯都不会亮,再就是亮了指示灯但是中断的灯一个都不亮,还有可能是中断的灯会亮会闪但是指示灯不会亮,但还是达不到要求的。
[7]因为执行语句不是一句就好了的,虽然switch语句很简单,但是我想试试if了,毕竟if语句分开了三种情况,可以更明确一些嘛if(TIM_GetITStatus(TIM3,TIM_IT_Update)==SET)
{
flag=flag++;
flag=flag%12;
{
if(flag==1)
{
LED0=!LED0;
SHI0=!SHI0;
//TIM_ClearITPendingBit(TIM3,TIM_IT_Update); }
else if(flag==3)
{
TIM_SetAutoreload(TIM3,20000); LED0=!LED0;
SHI0=!SHI0;
//TIM_ClearITPendingBit(TIM3,TIM_IT_Update);
}
else if(flag==7)
{
TIM_SetAutoreload(TIM3,30000);
LED0=!LED0;
SHI0=!SHI0;
//TIM_ClearITPendingBit(TIM3,TIM_IT_Update);
}
TIM_ClearITPendingBit(TIM3,TIM_IT_Update);
}
}
这样改动了之后出现了更多的循环情况。在我每次在这个基础上做改动的时候,要么全是1s的循环,要么就是3s的循环,还有可能就是所有的灯都灭掉,连我设置的指示灯都不会亮,再就是亮了指示灯但是中断的灯一个都不亮,还有可能是中断的灯会亮会闪但是指示灯不会亮,最好的情况就是两个灯能一起的亮1s的循环和3s的循环了。但是还没有达到要求。
if(TIM_GetITStatus(TIM3,TIM_IT_Update)==SET)
{
flag=flag++;
flag=flag%12;
{
if(flag==1)
{
LED0=!LED0;
SHI0=!SHI0;
//TIM_ClearITPendingBit(TIM3,TIM_IT_Update); }
else if(flag==3)
{
TIM_SetAutoreload(TIM3,20000); LED0=!LED0;
SHI0=!SHI0;
//TIM_ClearITPendingBit(TIM3,TIM_IT_Update);
}
else if(flag==7)
{
TIM_SetAutoreload(TIM3,30000);
LED0=!LED0;
SHI0=!SHI0;
//TIM_ClearITPendingBit(TIM3,TIM_IT_Update);
}
TIM_ClearITPendingBit(TIM3,TIM_IT_Update);
}
}
[8]我觉得可能是执行完一趟if之后,flag++,无法构成个循环,它本身跳不出来。我就试了试for循环if(TIM_GetITStatus(TIM3,TIM_IT_Update)==SET)
{
for (flag=1;flag<=12;flag++)
{
if(flag==1)
{
LED0=!LED0;
SHI0=!SHI0;
//TIM_ClearITPendingBit(TIM3,TIM_IT_Update);
}
else if(flag==3)
{
TIM_SetAutoreload(TIM3,20000);
LED0=!LED0;
SHI0=!SHI0;
//TIM_ClearITPendingBit(TIM3,TIM_IT_Update);
}
else if(flag==7)
{
TIM_SetAutoreload(TIM3,30000);
LED0=!LED0;
SHI0=!SHI0;
//TIM_ClearITPendingBit(TIM3,TIM_IT_Update);
}
flag=flag%12;
TIM_ClearITPendingBit(TIM3,TIM_IT_Update);
}
}
但是这样最好也是做到3s的循环呢~
if(TIM_GetITStatus(TIM3,TIM_IT_Update)==SET)
{
for (flag=1;flag<=12;flag++)
{
if(flag==1)
{
LED0=!LED0;
SHI0=!SHI0;
//TIM_ClearITPendingBit(TIM3,TIM_IT_Update);
}
else if(flag==3)
{
TIM_SetAutoreload(TIM3,20000);
LED0=!LED0;
SHI0=!SHI0;
//TIM_ClearITPendingBit(TIM3,TIM_IT_Update);
}
else if(flag==7)
{
TIM_SetAutoreload(TIM3,30000);
LED0=!LED0;
SHI0=!SHI0;
//TIM_ClearITPendingBit(TIM3,TIM_IT_Update);
}
flag=flag%12;
TIM_ClearITPendingBit(TIM3,TIM_IT_Update);
}
}
[9]想到前段时间,实验室有小伙伴写外部中断的实验,来控制流水灯的三个流速。一共有快中慢三种速度,每按一下键就可以改变一次。虽然他们是写的51的吧,系统不一样,但是还可以找找思路的。我看了他们控制速度的这部分程序。
可以总结为,分了三部分来写的。首先一个delay的函数来控制相应的键按下时是什么速度,再一个实参的函数,判断每次是按下了哪一种的键,最后在main函数中调用。
显然系统不一样,写出来的程序差距还是很大的。
首先我们不能用delay函数,因为这个已经在SYSTEM中调用了。当然这都是小事,改改函数名就好了。
第二我先写了51中的“delay”
void TIM3_IRQHandler(int i)
{
if(i==1)
{
LED0=!LED0;
SHI0=!SHI0;
//TIM_ClearITPendingBit(TIM3,TIM_IT_Update);
};
if(i==3)
{
TIM_SetAutoreload(TIM3,20000);
LED0=!LED0;
SHI0=!SHI0;
// TIM_ClearITPendingBit(TIM3,TIM_IT_Update);
};
if(i==7)
{
TIM_SetAutoreload(TIM3,20000);
LED0=!LED0;
SHI0=!SHI0;
// TIM_ClearITPendingBit(TIM3,TIM_IT_Update);
};
TIM_ClearITPendingBit(TIM3,TIM_IT_Update);
}
但是当我用51的方法写实参的函数的时候,程序就会报错呢~
void spee()
{
int i;
if(TIM_GetITStatus(TIM3,TIM_IT_Update)==SET)
{
TIM3_IRQHandler_dat++;
TIM3_IRQHandler_dat=TIM3_IRQHandler_dat%12
}
return TIM3_IRQHandler_dat;
}
凡是含有TIM3_IRQHandler_dat的语句都会报错。
(2)调了一天实在是调不出来了,今天我就不打算在这上边浪费时间了,我就看NVIC中断优先级管理的教学视频了。
之前的时候,写外部中断和定时器中断的时候,我倒是都都用过NVIC了,对于它的功能设置可以说是比较熟悉的了。今天就进一步的了解一下NVIC中断优先级分组以及配置。
第一部分是NVIC中断优先级分组。
[1]*CM4内核支持256个中断,其中包含了16个内核中断和240个外部中断,并且具有256级的可编程中断设置。但STM32F4并没有使用CM4内核的全部东西,而是只用了它的一部分。
*STM32F40xx/STM32F41xx总共有92个中断
*STM32F40xx/STM32F41xx的92个中断里面,包括10个内核中断和82个可屏蔽中断,具有16级可编程的中断优先级,而我们常用的就是这82个可屏蔽中断。
[2]中断优先级管理方法:对STM32中断分组,组0-4。同时,对每个中断设置抢占优先级和响应优先级。
*分组配置是在SCB->AIRCR寄存器的bit10~8来定义的
[3]抢占优先级和响应优先级的区别:
*高优先级的抢占优先级是可以打断正在进行的低抢占优先级中断的。
*抢占优先级相同的中断,高响应优先级不可以打断低响应优先级的中断。
*抢占优先级相同的中断,当两个中断同时发生的情况下,哪个响应优先级高,哪个先执行。
*如果两个中断的抢占优先级和响应优先级都是一样的话,则看哪个中断先发生就先执行。
[4]特别要注意的是:一般情况下,系统代码执行过程中,只设置一次中断优先级分组。
[5]中断优先级分组函数:
voidNVIC_PriorityGroupConfig(uint32_t NVIC_PriorityGroup);
第二部分是讲的中断优先级配置。这个在之前的程序中就有写过,算是比较熟悉的了。今天也是主要的学了几个中断设置相关寄存器
[1]中断优先级控制的寄存器组 IP[240];
voidNVIC_Init(NVIC_InitTypeDef*NVIC_InitStruct);具体的用法,在前两天写定时器中断的时候应该有提到的。
[2]中断使能寄存器组:ISER[8]
[3]中断失能寄存器组:ICER[8]。 特点及配置同[2]
[4]中断挂起控制寄存器组:ISPR[8]
[6]中断激活标志位寄存器组:IABR[8]
32位寄存器,每个位控制一个中断的使能。STM32F40x只有82个可屏蔽中断,所以只使用了其中的ISER[0]~ISER[2]
ISER[0]的bit0~bit31分别对应中断0~31。ISER[1]的bit0~27对应中断32~63;ISER[2]的bit0~17对应中断64~81
[5]中断解挂控制寄存器组:ICPR[8]
作用:只读,通过它可以知道当前在执行的中断是哪一个.如果对应位为1,说明该中断正在执行。
(2)PWM输出的视频没有看~