[MSPM0L1306 LaunchPad 开发套件] 8-定时器的输入捕获
<div class='showpostmsg'><div>这次用mspm0l1306实现的小项目需要用到输入捕获,前面2个帖子也把定时器的其它功能进行了测试,也算是把定时器的功能都试了一遍。TI的定时器还是易用的,包括CCS的初始化功能,还有清晰的函数名,都能帮助用户快速上手。</div><div>在本例中使用输入捕获的目的是测量输入信号的频率。因此使用输入捕获需要用到2个中断:load中断和捕获中断。通过2次捕获之间的时间差,得到信号的频率。</div>
<div>捕获使用的是TIMG1,设置的定时器周期为2S,初始化如下图所示:</div>
<div></div>
<div></div>
<div>中断使用通道0的捕获和定时器的load中断</div>
<div></div>
<div>在load负载中记录load的次数,在捕获时记录当前CCR的值,通过下面这个函数获得CCR的值。</div>
<div><strong>DL_Timer_getCaptureCompareValue</strong>(CAPTURE_0_INST,<em>DL_TIMER_CC_0_INDEX</em>);</div>
<div>通过将每次捕获的时间放入环形数组中,然后在后台的while循环中读取最近两次的计数值得到时间差,从而计算信号的频率。</div>
<div>代码见下方</div>
<div>中断函数</div>
<div>
<pre>
<code>typedef struct {
uint32_t period;
uint32_t ccr;
}TimestampStruct;
typedef struct{
TimestampStruct time;
uint8_t write_index;
uint32_t count;
}TimestampBufStruct;
TimestampBufStruct timestamp_buf;
void CAPTURE_0_INST_IRQHandler()
{
TimestampStruct nowtime;
static uint32_t period_count;
switch(DL_TimerG_getPendingInterrupt(CAPTURE_0_INST)){
case DL_TIMER_IIDX_CC0_DN:
nowtime.period = period_count;
nowtime.ccr = DL_Timer_getCaptureCompareValue(CAPTURE_0_INST,DL_TIMER_CC_0_INDEX);
write_new_timestamp(nowtime);
DL_GPIO_togglePins(USER_PORT,USER_R_LED_PIN);
break;
case DL_TIMER_IIDX_LOAD:
period_count++;
DL_GPIO_togglePins(USER_PORT,USER_R_LED_PIN);
break;
default:
break;
}
}</code></pre>
<p>时间戳写入环形数组的代码</p>
<pre>
<code>void write_new_timestamp(TimestampStruct timestamp)
{
timestamp_buf.time = timestamp;
timestamp_buf.count++;
timestamp_buf.write_index++;
if(timestamp_buf.write_index >= 20){
timestamp_buf.write_index = 0;
}
}</code></pre>
<p>计算频率的代码</p>
<pre>
<code>uint32_t get_timestamp_diff()
{
uint8_t index = timestamp_buf.write_index;
TimestampStruct nowtime,lasttime;
char str1;
uint32_t time_dif = 0;
if(index > 0){
nowtime = timestamp_buf.time;
}else{
nowtime = timestamp_buf.time;
}
if((index -1) > 0){
lasttime = timestamp_buf.time;
}else{
lasttime = timestamp_buf.time;
}
if(nowtime.period == lasttime.period){
time_dif = lasttime.ccr- nowtime.ccr;
}else if(nowtime.period -lasttime.period == 1){
nowtime.ccr = 40000-nowtime.ccr;
lasttime.ccr = 40000-lasttime.ccr;
time_dif = 40000 - lasttime.ccr + lasttime.ccr;
}else{
time_dif = (nowtime.period - lasttime.period -1)*40000;
time_dif += 40000 - lasttime.ccr + lasttime.ccr;
}
return time_dif;
}
float compute_freq()
{
uint32_t diff;
float freq;
if(timestamp_buf.count >= 2){
diff = get_timestamp_diff();
if(diff != 0){
freq =20000.0 /diff;
return freq;
}else{
return 0;
}
}else{
return 0;
}
}</code></pre>
<p>主函数</p>
<pre>
<code>char str ="helo";
float frq;
int i_frq;
int main(void)
{
SYSCFG_DL_init();
// APP_DL_UART_0_init();
NVIC_EnableIRQ(CAPTURE_0_INST_INT_IRQN);
send_multi_data_by_uart((uint8_t*)str,strlen(str));
DL_TimerG_startCounter(CAPTURE_0_INST);
while (1) {
delay_cycles(32000000);
frq = compute_freq();
i_frq = (int)frq;
snprintf(str,50,"freq:%d\r\n",i_frq);
send_multi_data_by_uart((uint8_t*)str,strlen(str));
}
}</code></pre>
<p> </p>
</div>
<div>计算的频率还是比较准的,用示波器输出了1khz的信号,采集到的频率也是1khz。</div>
<div></div>
<div>最后要补充的是,编译器好像不支持浮点数,用想用sprintf函数输出浮点数的值时,会进入硬件错误的死循环中,所以代码改成了输出整型数据。</div>
</div><script> var loginstr = '<div class="locked">查看本帖全部内容,请<a href="javascript:;" style="color:#e60000" class="loginf">登录</a>或者<a href="https://bbs.eeworld.com.cn/member.php?mod=register_eeworld.php&action=wechat" style="color:#e60000" target="_blank">注册</a></div>';
if(parseInt(discuz_uid)==0){
(function($){
var postHeight = getTextHeight(400);
$(".showpostmsg").html($(".showpostmsg").html());
$(".showpostmsg").after(loginstr);
$(".showpostmsg").css({height:postHeight,overflow:"hidden"});
})(jQuery);
} </script><script type="text/javascript">(function(d,c){var a=d.createElement("script"),m=d.getElementsByTagName("script"),eewurl="//counter.eeworld.com.cn/pv/count/";a.src=eewurl+c;m.parentNode.insertBefore(a,m)})(document,523)</script> <p>TI的定时器操作起来不是很复杂</p>
<p>请问下想测50K这些频率高一点的应该怎么配啊?</p>
页:
[1]