本帖最后由 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)。
我测试时是通过串口通讯将按键值发送到电脑端来观看,下图是串口调试助手获得的按键数据:
|