[8/16位单片机] PIC16F18446定时器0设置问题

[复制链接]
392|10
 楼主 | 2019-6-9 09:01 | 显示全部楼层 |阅读模式
    我使用MCC配置了定时器0,时钟源选择Fosc/4,预分频为1024,后分频为5,按照计算定时时间为20.48ms。生成代码后未作修改,测试时却检测不到定时器0的中断,调试时发现已经进入了timer0的初始化,GIE总中断也打开了,T0IE中断也打开了,但在中断管理函数中却没有被执行,请问是不是还有哪里需要设置。另外我还开启了外部中断和串口通讯的中断,这些功能可以正常运行,就是定时器不起作用。
    下面是MCC生成的timer0.c文件:
  1. #include <xc.h>
  2. #include "tmr0.h"
  3. #include "pin_manager.h"

  4. extern uint8_t keys,keyok;
  5. extern uint16_t ms;
  6. /**
  7.   Section: TMR0 APIs
  8. */

  9. void (*TMR0_InterruptHandler)(void);

  10. void TMR0_Initialize(void)
  11. {
  12.     // Set TMR0 to the options selected in the User Interface

  13.     // T0CS FOSC/4; T0CKPS 1:1024; T0ASYNC synchronised;
  14.     T0CON1 = 0x4A;   //0100 1010  0x4A

  15.     // TMR0H 0;
  16.     TMR0H = 0x00;

  17.     // TMR0L 0;
  18.     TMR0L = 0x00;

  19.     // Clear Interrupt flag before enabling the interrupt
  20.     PIR0bits.TMR0IF = 0;

  21.     // Enabling TMR0 interrupt.
  22.     PIE0bits.TMR0IE = 1;

  23.     // Set Default Interrupt Handler
  24.     TMR0_SetInterruptHandler(TMR0_DefaultInterruptHandler);

  25.     // T0OUTPS 1:5; T0EN enabled; T016BIT 8-bit;
  26.     T0CON0 = 0x84;
  27. }

  28. void TMR0_StartTimer(void)
  29. {
  30.     // Start the Timer by writing to TMR0ON bit
  31.     T0CON0bits.T0EN = 1;
  32. }

  33. void TMR0_StopTimer(void)
  34. {
  35.     // Stop the Timer by writing to TMR0ON bit
  36.     T0CON0bits.T0EN = 0;
  37. }

  38. uint8_t TMR0_ReadTimer(void)
  39. {
  40.     uint8_t readVal;

  41.     // read Timer0, low register only
  42.     readVal = TMR0L;

  43.     return readVal;
  44. }

  45. void TMR0_WriteTimer(uint8_t timerVal)
  46. {
  47.     // Write to Timer0 registers, low register only
  48.     TMR0L = timerVal;
  49. }

  50. void TMR0_Reload(uint8_t periodVal)
  51. {
  52.    // Write to Timer0 registers, high register only
  53.    TMR0H = periodVal;
  54. }

  55. void TMR0_ISR(void)
  56. {
  57.     static volatile uint16_t CountCallBack = 0;
  58.     IO_RA2_Toggle();
  59.     // clear the TMR0 interrupt flag
  60.     PIR0bits.TMR0IF = 0;
  61.     // callback function - called every 49th pass
  62.     //回调函数-每隔49次调用
  63.     if (++CountCallBack >= TMR0_INTERRUPT_TICKER_FACTOR)
  64.     {
  65.         // ticker function call Ticker函数调用
  66.         TMR0_CallBack();

  67.         // reset ticker counter 重置票务计数器
  68.         CountCallBack = 0;
  69.     }

  70.     // add your TMR0 interrupt custom code
  71.     ms++;
  72.     if(0==keyok){         //keyok=0表明无按键事件
  73.         if(0==IO_RC2_GetValue()){
  74.             if(keys<128)
  75.                 keys++;   //按键计数
  76.         }
  77.         else{
  78.             if(keys>0)
  79.                 keyok = 1;//按键松开,建立事件标志
  80.         }
  81.     }
  82.    
  83. }

  84. void TMR0_CallBack(void)
  85. {
  86.     // Add your custom callback code here

  87.     if(TMR0_InterruptHandler)
  88.     {
  89.         TMR0_InterruptHandler();
  90.     }
  91. }

  92. void TMR0_SetInterruptHandler(void (* InterruptHandler)(void)){
  93.     TMR0_InterruptHandler = InterruptHandler;
  94. }

  95. void TMR0_DefaultInterruptHandler(void){
  96.     // add your TMR0 interrupt custom code
  97.     // or set custom function using TMR0_SetInterruptHandler()
  98. }
复制代码

    下面是中断处理函数,也是自动生成的,我在其中添加了翻转LED灯的语句,以便观察,同时在此设置断点,调试时不会执行到此处:
  1. #include "interrupt_manager.h"
  2. #include "mcc.h"
  3. #include "pin_manager.h"

  4. void __interrupt() INTERRUPT_InterruptManager (void)
  5. {
  6.     // interrupt handler
  7.     IO_RA2_Toggle();
  8.     if(PIE0bits.TMR0IE == 1 && PIR0bits.TMR0IF == 1)
  9.     {
  10.         TMR0_ISR();
  11.     }
  12.     else if(PIE0bits.INTE == 1 && PIR0bits.INTF == 1)
  13.     {
  14.         INT_ISR();
  15.     }
  16.     else
  17.     {
  18.         //Unhandled Interrupt
  19.     }
  20. }
复制代码

    下面是主程序,按照初始化,开总中断,开定时器0中断,进入while循环的步骤执行,调试时能够顺利进入循环:
#include "mcc_generated_files/mcc.h"

uint8_t keys,keyok,mode,rxData;
uint16_t ms;

void delay_ms(uint16_t times);
/*
                         Main application
*/
void main(void)
{
    // initialize the device
    SYSTEM_Initialize();

    // When using interrupts, you need to set the Global and Peripheral Interrupt Enable bits
    // Use the following macros to:

    // Enable the Global Interrupts启用全局中断(INTCONbits.GIE = 1)。
    INTERRUPT_GlobalInterruptEnable();

    // Enable the Peripheral Interrupts启用外围设备中断(INTCONbits.PEIE = 1)
    INTERRUPT_PeripheralInterruptEnable();

    // Disable the Global Interrupts
    //INTERRUPT_GlobalInterruptDisable();

    // Disable the Peripheral Interrupts
   
    IO_RA2_SetLow();
    for(mode=0;mode<6;mode++){
        delay_ms(500);
        IO_RA2_Toggle();
    }
    mode = 33;
    IO_RA2_SetHigh();
    //INTERRUPT_PeripheralInterruptDisable();
    TMR0_StartTimer();      //T0CON0bits.T0EN = 1;
   
    while (1)
    {
        // Add your application code
        if(keyok>0){
            EUSART1_Write(keys);
            keys = 0;
            keyok = 0;  //取消按键事件标志
        }
        if(ms>5){
            ms = 0;
            mode++;
            if(mode>120)
                mode = 33;
            EUSART1_Write(mode);
        }
        if(0==IO_RC2_GetValue()){
            IO_RA2_SetLow();
            delay_ms(200);
            IO_RA2_SetHigh();
        }
        // Logic to echo received data
        if(EUSART1_is_rx_ready())
        {
            IO_RA2_SetLow();
            rxData = EUSART1_Read();
            if(EUSART1_is_tx_ready())
            {
                EUSART1_Write(rxData);
            }
//            delay_ms(500);
            IO_RA2_SetHigh();
        }
    }
}

void delay_ms(uint16_t times)
{
    uint16_t t,r;
    for(t=times;t>0;t--)
        for(r=110;r>0;r--);
}
    这是整个项目打包:
alarm.rar (1006.95 KB, 下载次数: 3)

使用特权

评论回复
 楼主 | 2019-6-9 17:15 | 显示全部楼层
找到原因了,原来是定时器0的时钟源选择与系统配置的不一致,修改成系统配置之后就正常了。
就此结贴。

使用特权

评论回复
| 2019-6-10 08:21 | 显示全部楼层

使用特权

评论回复
| 2019-6-10 17:09 | 显示全部楼层
楼主现在成长迅速啊

使用特权

评论回复
 楼主 | 2019-6-10 22:05 | 显示全部楼层
奔波儿熊 发表于 2019-6-10 17:09
楼主现在成长迅速啊

谢谢鼓励!拿到了板子,想尽快熟悉,只有反复操练。

使用特权

评论回复
| 2019-6-11 19:44 | 显示全部楼层
前后一致很重要啊

使用特权

评论回复
 楼主 | 2019-6-11 21:21 | 显示全部楼层
643757107 发表于 2019-6-11 19:44
前后一致很重要啊

是啊,就因为这个问题,浪费了几天时间。

使用特权

评论回复
| 2019-6-12 15:12 | 显示全部楼层
楼主用的是中断吗

使用特权

评论回复
| 2019-6-12 15:17 | 显示全部楼层
楼主能说说怎么找到的原因吗 我也好借鉴一下

使用特权

评论回复
 楼主 | 2019-6-12 16:05 | 显示全部楼层
zljiu 发表于 2019-6-12 15:12
楼主用的是中断吗

是的,通过定时器产生的中断来处理按键。

使用特权

评论回复
 楼主 | 2019-6-12 16:07 | 显示全部楼层
coshi 发表于 2019-6-12 15:17
楼主能说说怎么找到的原因吗 我也好借鉴一下

原因在2楼已经说过了,是时钟源选择与系统配置不一致。具体可参考我的这个帖子:http://bbs.21ic.com/icview-2821656-1-1.html

使用特权

评论回复
扫描二维码,随时随地手机跟帖
您需要登录后才可以回帖 登录 | 注册

本版积分规则

我要发帖 投诉建议 创建版块 申请版主

快速回复

您需要登录后才可以回帖
登录 | 注册
高级模式

论坛热帖

在线客服 快速回复 返回顶部 返回列表