donatello1996 发表于 2019-8-4 23:16

【麦昆试用】迟来的第四帖——试用Arduino IDE开发环境&定时器中断

<p>这个标题的因果关系应该反过来说,因为我想调通microbit主控板的定时器中断,在网上寻求答案,最终得知最便捷的方式是通过Arduino IDE开发环境实现,因为这个开发环境可以从开源社区下载安装一切纳入Arduino家族的开发板的资源并获得充足支持,在观看完代码之后,我发现Arduino IDE开源库里面对于microbit主控板的定时器中断例程实际上也是通过控制板上主控单片机nrf51822的寄存器实现的,将寄存器操作封装成类和对象的操作,正是Arduino开发的最常见操作。</p>

<p>首先下载Arduino IDE开发环境,这个不用多赘述,直接在arduino.cc官网下载即可,下载安装Arduino IDE这步很简单,安装Demo例程也很简单,难点在于安装器件支持包,这里先简单介绍下怎么安装micro:bit的DEMO例程。</p>

<p>打开ArduinoIDE,打开项目-&gt;库,搜索micro:bit,即可找到micro:bit所对应的Demo例程:</p>

<p></p>

<p>这个例程下有齐了micro:bit板子的大部分BSP(板级)Demo,如blink闪灯,定时器,按键,蓝牙控制器等,我选择这期主题&mdash;&mdash;定时器,打开timerdemo:</p>

<p></p>

<p>然后到了最麻烦的一步(这步难度不高,就是很麻烦),那就是ArduinoIDE软件内部安装器件支持包了,这个跟电脑所在的网络环境息息相关,稍微有点差错都会下载失败,我被这个折腾了很久,最终是用公司的网络艰难完成的器件支持包安装,这里推荐大家使用离线安装的方式,离线安装方式繁琐但可以绕开ArduinoIDE内部蛋疼的联网机制:</p>

<p></p>

<p>timerdemo定时器例程写法与普通的KEIL程序如出一辙,使用寄存器方式配置定时器,然后在中断服务函数里面触发,例程使用的是NRF52832主控的定时器2,有两个比较事件,在同一个中断服务函数里面触发:</p>

<p>// This is a &#39;low level&#39; demo showing how to use timer 2 (the only available timer really)<br />
// to blink an LED. This code turned into the matrix handler, so you cant use it and the<br />
// Adafruit_Microbit library at the same time but maybe its useful!</p>

<p>const int COL1 = 3;&nbsp;&nbsp;&nbsp;&nbsp; // Column #1 control<br />
const int LED = 26;&nbsp;&nbsp;&nbsp;&nbsp; // &#39;row 1&#39; led</p>

<p><br />
void start_timer(void)<br />
{&nbsp;&nbsp; &nbsp;<br />
&nbsp; NRF_TIMER2-&gt;MODE = TIMER_MODE_MODE_Timer;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Set the timer in Counter Mode<br />
&nbsp; NRF_TIMER2-&gt;TASKS_CLEAR = 1;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // clear the task first to be usable for later<br />
&nbsp; NRF_TIMER2-&gt;PRESCALER&nbsp;&nbsp; = 8; &nbsp;<br />
&nbsp; NRF_TIMER2-&gt;BITMODE = TIMER_BITMODE_BITMODE_16Bit;&nbsp;&nbsp;&nbsp;&nbsp; //Set counter to 16 bit resolution<br />
&nbsp; NRF_TIMER2-&gt;CC = 32000;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //Set value for TIMER2 compare register 0<br />
&nbsp; NRF_TIMER2-&gt;CC = 5;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //Set value for TIMER2 compare register 1<br />
&nbsp;&nbsp; &nbsp;<br />
&nbsp; // Enable interrupt on Timer 2, both for CC and CC compare match events<br />
&nbsp; NRF_TIMER2-&gt;INTENSET = (TIMER_INTENSET_COMPARE0_Enabled &lt;&lt; TIMER_INTENSET_COMPARE0_Pos) | (TIMER_INTENSET_COMPARE1_Enabled &lt;&lt; TIMER_INTENSET_COMPARE1_Pos);<br />
&nbsp; NVIC_EnableIRQ(TIMER2_IRQn);<br />
&nbsp;&nbsp; &nbsp;<br />
&nbsp; NRF_TIMER2-&gt;TASKS_START = 1;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Start TIMER2<br />
}</p>

<p>&nbsp;&nbsp; &nbsp;<br />
/** TIMTER2 peripheral interrupt handler. This interrupt handler is called whenever there it a TIMER2 interrupt<br />
&nbsp;* Don&#39;t mess with this line. really.<br />
&nbsp;*/<br />
&nbsp;extern &quot;C&quot;&nbsp; { void TIMER2_IRQHandler(void) { timer_pal();&nbsp; } }</p>

<p>void timer_pal(void) {<br />
&nbsp; if ((NRF_TIMER2-&gt;EVENTS_COMPARE != 0) &amp;&amp; ((NRF_TIMER2-&gt;INTENSET &amp; TIMER_INTENSET_COMPARE0_Msk) != 0))<br />
&nbsp; {<br />
&nbsp;&nbsp;&nbsp; NRF_TIMER2-&gt;EVENTS_COMPARE = 0;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //Clear compare register 0 event<br />
&nbsp;&nbsp;&nbsp; Serial.println(&quot;TIMER2 Event C0&quot;);<br />
&nbsp; }<br />
&nbsp;<br />
&nbsp; if ((NRF_TIMER2-&gt;EVENTS_COMPARE != 0) &amp;&amp; ((NRF_TIMER2-&gt;INTENSET &amp; TIMER_INTENSET_COMPARE1_Msk) != 0))<br />
&nbsp; {<br />
&nbsp;&nbsp;&nbsp; NRF_TIMER2-&gt;EVENTS_COMPARE = 0;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //Clear compare register 1 event<br />
&nbsp;&nbsp;&nbsp; Serial.println(&quot;TIMER2 Event C1&quot;);<br />
&nbsp; }<br />
}</p>

<p>&nbsp;</p>

<p>void setup() { &nbsp;<br />
&nbsp; Serial.begin(115200);<br />
&nbsp; Serial.println(&quot;microbit is ready!&quot;);</p>

<p>&nbsp; // because the LEDs are multiplexed, we must ground the opposite side of the LED<br />
&nbsp; pinMode(COL1, OUTPUT);<br />
&nbsp; digitalWrite(COL1, LOW);<br />
&nbsp; &nbsp;<br />
&nbsp; pinMode(LED, OUTPUT); &nbsp;</p>

<p>&nbsp; start_timer();<br />
}</p>

<p>void loop(){<br />
&nbsp; Serial.println(&quot;blink!&quot;);<br />
&nbsp; delay(500);<br />
}</p>

<p>&nbsp;</p>

<p>这里小改了一下,波特率改成115200,定时器中断触发里面改成串口打印,看看运行效果:</p>

<p></p>

<p>&nbsp;</p>
页: [1]
查看完整版本: 【麦昆试用】迟来的第四帖——试用Arduino IDE开发环境&定时器中断