第〇九天 2015年07月30日 周四 例程:定时器中断实验
1.定时计数器分类:STM32F4定时器有TIME1和TIME8等高级定时器,也有TIME2~TIME5、TIME9~TIME14等通用定时器,还有TIME6和TIME7等基本定时器,总共有14个之多。
2.三种定时器区别
3.频率:物质在1s内周期变化的次数叫做频率。常用f表示,单位为Hz,与周期成倒数关系,即1Hz=1/s。为加深记忆,按部就班计算,1KHz即为1s变化1000次,即1ms变化1次1KHz = 1/ms,同理1MHz = 1/us。
4.溢出Tout时间计算公式: Tout = ((arr+1)*(psc+1))/Tclk;
其中,arr为自动重装值;
psc为时钟预分频数;
Tclk为输入时钟频率,本例程TIME3为84Mhz。
根据例程,当psc为(8400-1)时,即进行8400分频,此时技术频率为84MHz/8400 = 10KHz,也就是1s计数10K次,每次计数需耗时1/10000(s)。计数arr次需耗时arr*(1/10000)(s),等效于arr*(1/10)(ms),所以,当arr为(5000-1)时,每次溢出需5000*(1/10)(ms),即500ms。
5.例程中,将两个指示灯分别用于主函数和中断中闪烁,可以在此基础上,通过定义一个全局标志变量flag来使两个指示灯几乎同步,观察延时函数和定时计数器两者是否吻合。
定义一个全局变量flag以后,进行如下调整:其一,在中断函数中添加flag
void
TIM3_IRQHandler(void)
{
if(TIM3->SR & 0X0001)
{
LED1 = !LED1;
flag = 1; //一旦进入中断则置位同步标志位
}
TIM3->SR &= ~(1 << 0);
}
其二,将主函数进行一些调整
while(1)
{
while(flag == 0) //等待同步标志位置位
{
delay_us(2);
}
LED0 = !LED0;
delay_ms(500);
}
此时主函数小灯闪烁频率为1s,定时计数器溢出时间为500ms,定时计数器一旦中断则置位标志位,两个小灯几乎同步开始闪烁,两者误差不超过2us,实际测试可以观察到两个小灯同步进行闪烁。此时我们将主函数中delay_ms(500)改为delay_ms(400),则可以观察到LED0每闪烁5次的同时LED1恰好闪烁4次,与预期一致,说明定时计数器与延时函数两者之间是协调的,如果有秒表等设备进行监测,应该会发现它们都是准确的。
位段
1.信息的存取一般以字节为单位。实际上,有时存储一个信息不必用一个或多个字节,如真、假二值判断。在计算机用于过程控制、参数检测或数据通信领域时,控制信息只占一个字节中的一个或几个二进制位,常常可以在一个字节中放几个信息。
2.位段:C语言允许在一个结构中以位为单位来指定成员所占内存长度,这种以位为单位的成员成为位段或位域(bit field)。利用位段能够用较少位数存储数据。
3.位段变量与结构变量定义类似。位段示意图
4.注意事项
其一,位段成员类型必须指定为unsigned或int类型;
其二,若某一位段要从另一个字开始存放,可用以下形式定义
unsigned a:1;
unsigned b:2;//一个存储单元
unsigned:0;
unsigned c:3;//另一存储单元
a、b、c应连续存放在一个存储单元中,由于用了长度为0的位段,其作用是使下一个位段从下一个存储单元开始存放。因此,只将a、b存储在一个存储单元中,c另存在下一个单元(“存储单元”可能是一个字节,也可能是2个字节,视不同的编译系统而异)。
其三, 一个位段必须存储在同一个存储单元中,不能跨两个单元,如果第一个单元空间不能容纳下一个位段,则该空间不用,而从下一个单元起存放该位段。
其四,位段的长度不能大于存储单元的长度,也不能定义位段数组。
其五,位段可以在数值表达式中引用,它会被系统自动地转换成整型数。
5.同结构一样,我们可以把工程中仅需要几位来表示且功能性质比较相似的变量统一放在一块,节省空间的同时也便于管理。例如,程序中可能需要很多标志位,我们把这些标志位统一放在一个位段中,根据需要可以不断添加和去除,使其整体统一,框架清晰明了。
|