本帖最后由 hu9jj 于 2019-6-10 15:53 编辑
PIC16F18446开发板上只有一个用户按钮,通过开启定时器可以记录用户按键的时间长短,从而达到识别同功能。另外,通过定时器对变量增一的操作,可以控制LED灯闪烁,避免用延时函数造成单片机效率不高。
一、定时器0的开启
进入MCC对定时器0进行配置,这是最方便快捷的设置方法。进入MCC(见下图),这里我就用默认的设置,没有变动。
选择定时器0,预分频选择为1:64,后分频为1:5,定时器选择8位,时钟源选择的与上面系统配置一致的“HFINTOSC”,这里特别提醒,我之前时钟源选择的是Fosc/4,但调试时却反复不成功,最后将时钟源改为与系统配置相同的才调试成功。这是main函数中的代码:
我设置的定时时间为20.48毫秒,但在之后的实际调试时发现定时时间远低于20毫秒,后来是修改了预分频和后分频才勉强达到要求。
下面是自动生成的timer0.c代码,在调试过程中我将预分频改为1:128,后分频改为1:10。
- /**
- TMR0 Generated Driver File
- @Company
- Microchip Technology Inc.
- [url=home.php?mod=space&uid=288409]@file[/url] Name
- tmr0.c
- @Summary
- This is the generated driver implementation file for the TMR0 driver using PIC10 / PIC12 / PIC16 / PIC18 MCUs
- @Description
- This source file provides APIs for TMR0.
- Generation Information :
- Product Revision : PIC10 / PIC12 / PIC16 / PIC18 MCUs - 1.76
- Device : PIC16F18446
- Driver Version : 3.10
- The generated drivers are tested against the following:
- Compiler : XC8 2.00
- MPLAB : MPLAB X 5.10
- */
- /*
- (c) 2018 Microchip Technology Inc. and its subsidiaries.
-
- Subject to your compliance with these terms, you may use Microchip software and any
- derivatives exclusively with Microchip products. It is your responsibility to comply with third party
- license terms applicable to your use of third party software (including open source software) that
- may accompany Microchip software.
-
- THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, WHETHER
- EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, INCLUDING ANY
- IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, AND FITNESS
- FOR A PARTICULAR PURPOSE.
-
- IN NO EVENT WILL MICROCHIP BE LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE,
- INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND
- WHATSOEVER RELATED TO THE SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP
- HAS BEEN ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO
- THE FULLEST EXTENT ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL
- CLAIMS IN ANY WAY RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT
- OF FEES, IF ANY, THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS
- SOFTWARE.
- */
- /**
- Section: Included Files
- */
- #include <xc.h>
- #include "tmr0.h"
- #include "pin_manager.h"
- extern char keys,keyok;
- extern int ms;
- /**
- Section: TMR0 APIs
- */
- void (*TMR0_InterruptHandler)(void);
- void TMR0_Initialize(void)
- {
- // Set TMR0 to the options selected in the User Interface
- // T0CS HFINTOSC; T0CKPS 1:64; T0ASYNC synchronised;
- T0CON1 = 0x67; //0x66 T0CKPS=1:128
- // TMR0H 31;
- TMR0H = 0x1F;
- // TMR0L 0;
- TMR0L = 0x00;
- // Clear Interrupt flag before enabling the interrupt
- PIR0bits.TMR0IF = 0;
- // Enabling TMR0 interrupt.
- PIE0bits.TMR0IE = 1;
- // Set Default Interrupt Handler
- TMR0_SetInterruptHandler(TMR0_DefaultInterruptHandler);
- // T0OUTPS 1:5; T0EN enabled; T016BIT 8-bit;
- T0CON0 = 0x89; //0x84 T0OUTPS=1:10
- }
- void TMR0_StartTimer(void)
- {
- // Start the Timer by writing to TMR0ON bit
- T0CON0bits.T0EN = 1;
- }
- void TMR0_StopTimer(void)
- {
- // Stop the Timer by writing to TMR0ON bit
- T0CON0bits.T0EN = 0;
- }
- uint8_t TMR0_ReadTimer(void)
- {
- uint8_t readVal;
- // read Timer0, low register only
- readVal = TMR0L;
- return readVal;
- }
- void TMR0_WriteTimer(uint8_t timerVal)
- {
- // Write to Timer0 registers, low register only
- TMR0L = timerVal;
- }
- void TMR0_Reload(uint8_t periodVal)
- {
- // Write to Timer0 registers, high register only
- TMR0H = periodVal;
- }
- void TMR0_ISR(void)
- {
- static volatile uint16_t CountCallBack = 0;
- ms++;
- if(0==IO_RC2_GetValue()){
- if(0==keyok & keys<255)
- keys++;
- }
- else{
- if(keys>0)
- keyok = 1;
- }
- // clear the TMR0 interrupt flag
- PIR0bits.TMR0IF = 0;
- // callback function - called every 8th pass
- if (++CountCallBack >= TMR0_INTERRUPT_TICKER_FACTOR)
- {
- // ticker function call
- TMR0_CallBack();
- // reset ticker counter
- CountCallBack = 0;
- }
- // add your TMR0 interrupt custom code
- }
- void TMR0_CallBack(void)
- {
- // Add your custom callback code here
- if(TMR0_InterruptHandler)
- {
- TMR0_InterruptHandler();
- }
- }
- void TMR0_SetInterruptHandler(void (* InterruptHandler)(void)){
- TMR0_InterruptHandler = InterruptHandler;
- }
- void TMR0_DefaultInterruptHandler(void){
- // add your TMR0 interrupt custom code
- // or set custom function using TMR0_SetInterruptHandler()
- }
- /**
- End of File
- */
二、多功能按键
开启了定时器0后,我通过定时器0对按键功能进行了扩展,使得可以分辨用户按键时间的长短,达到扩展按键功能的目的。
我是通过两个全局变量,变量keyok置位表示用户有按键事件,变量keys则表示按下的时间长短。在我的例子中,快速点击按键返回的值大约10以内,按下4~5秒释放后大约为250左右,根据这个返回值就可以划分为若干个范围,根据我的测试至少可以分为四种按键状态,分别是:快速点击(keys<20)、短按(20<keys<50)、长按(50<keys<150)、超长按(keys>150)。
我测试时是通过串口通讯将按键值发送到电脑端来观看,下图是串口调试助手获得的按键数据:
|