打印
[PIC®/AVR®/dsPIC®产品]

PIC18F67K22时钟配置

[复制链接]
1304|21
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
主要问题:想使用定时器0中断,并且配置LED2一秒钟变化一次,时钟想配置内部16M,现在的问题是LED2用示波器观测时1.12秒变化一次,目前还没找到问题,求助各位,已经三天了!

/********************部分配置字

#pragma config RETEN = ON   
#pragma config INTOSCSEL = HIGH
#pragma config SOSCSEL = DIG   
#pragma config XINST = OFF     

// CONFIG1H
#pragma config FOSC = INTIO2   
#pragma config PLLCFG = OFF   
#pragma config FCMEN = OFF   
#pragma config IESO = OFF      

// CONFIG2L
#pragma config PWRTEN = OFF     
#pragma config BOREN = SBORDIS
#pragma config BORV = 3         // Brown-out Reset Voltage bits (1.8V)
#pragma config BORPWR = ZPBORMV // BORMV Power level (ZPBORMV instead of BORMV is selected)

// CONFIG2H
#pragma config WDTEN = OFF      // Watchdog Timer (WDT disabled in hardware; SWDTEN bit disabled)
#pragma config WDTPS = 16  // Watchdog Postscaler (1:1048576)

// CONFIG3L
#pragma config RTCOSC = INTOSCREF // RTCC Clock Select (RTCC uses INTOSCREF)

// CONFIG3H
#pragma config CCP2MX = PORTC   // CCP2 Mux (RC1)
#pragma config MSSPMSK = MSK7   // MSSP address masking (7 Bit address masking mode)
#pragma config MCLRE = ON       // Master Clear Enable (MCLR Enabled, RG5 Disabled)

// CONFIG4L
#pragma config STVREN = ON      // Stack Overflow Reset (Enabled)
#pragma config BBSIZ = BB2K     // Boot Block Size (2K word Boot Block size)

********************/

/************************时钟配置部分
IRCF2 = 1;
    IRCF1 = 1;
    IRCF0 = 1;                                                                  //内部16M时钟
    SCS1 = 1;
    PLLEN = 0;                                                                  //不4倍频
    SOSCRUN = 0;
    MFIOSEL = 0;
    //OSCTUNE = 0X80;
    while(!HFIOFS);

************************/

/***********************定时器配置部分
void Time0InitConfig()
{
    T08BIT = 0;                                                                 //16位定时器
    T0CS = 0;                                                                   //内部1/4FOSC时钟
   
    T0PS2 = 0;
    T0PS1 = 0;
    T0PS0 = 1;                                                                  //预分频器1/4分频
   
    PSA = 0;                                                                    //设置使用预分频器的频率
   
    TMR0L = 0x9c;
    TMR0H = 0xff;
    //TMR0 = 156;                                                                 //定时100us
    TMR0IE = 1;                                                                 //启动中断
    TMR0ON = 1;                                                                 //开启定时器中断
    TMR0IF = 0;
}
***********************/
/************定时器中断
void Tmr0Interrupt_ISR()
{
    static uint x;
    if(TMR0IF == 1)
    {        
        TMR0IF = 0;
        TMR0L = 0x9c;
        TMR0H = 0xff;
        BeepWork();
        x++;
        if(x <= 10000)
            LED2 = 0;
        else if(x <= 20000)
            LED2 = 1;
        else
            x = 0;
    }
}
/************

使用特权

评论回复
沙发
奔波儿熊| | 2019-9-10 14:23 | 只看该作者
先别累加, 看看一次中断的测量值和理论值各是多少?

使用特权

评论回复
评论
WUQIMENG 2019-9-10 14:31 回复TA
理论值是100us进去一次,实际值是112us进去一次 
WUQIMENG 2019-9-10 14:25 回复TA
好的,我试试 
板凳
北极风| | 2019-9-10 14:27 | 只看该作者
定时器可以0.5s中断一次呀。

建议用MCC配置和生成基本的程序,自己再修改。

使用特权

评论回复
评论
WUQIMENG 2019-9-10 16:54 回复TA
用MCC配置的代码也是这样子 
WUQIMENG 2019-9-10 14:32 回复TA
我看看,还没有用过MCC这个东西 
地板
奔波儿熊| | 2019-9-10 16:58 | 只看该作者
可能是时钟误差

使用特权

评论回复
评论
WUQIMENG 2019-9-10 17:07 回复TA
误差有点大吧~!!!而且我有接外部4M晶振啊,都一样 
5
lcczg| | 2019-9-10 17:09 | 只看该作者
这个原因应该是从中断触发到在中断里面重新赋值TMR0L = 0x9c; TMR0H = 0xff的延迟引起; 这是因为进入中断以及中断中执行到TMR0赋值指令都是需要时间的。这个延迟时间应该就是112-100=12uS. 你可以将Timer的时基变大,例如256分频。另外尽量将中断周期加长,使TMR0的值尽可能小,这样周期就得到加长,最好是直接1秒中断一次。在256分频时,取TMR0=0xC2F7应该可以了。

使用特权

评论回复
评论
WUQIMENG 2019-9-10 17:23 回复TA
赋值指令也不用这么久的时间吧!PIC16都不会出这个问题。12us太长了,而且我是用来做项目~一秒不现实啊 
6
奔波儿熊| | 2019-9-10 17:35 | 只看该作者
我看你用的内部16M啊,外部的4M用了吗? 如果是内部的 时钟误差 + 中断延迟 + 指令执行时间 差不多吧

使用特权

评论回复
评论
奔波儿熊 2019-9-11 10:36 回复TA
@WUQIMENG :公司不方便啊,电脑没装qq 
7
CoolSilicon| | 2019-9-11 09:12 | 只看该作者
为啥不尝试MCC生产代码??
简单又实用~~~还不用你这样来回折腾.....

使用特权

评论回复
8
CoolSilicon| | 2019-9-11 09:14 | 只看该作者
方便又实用..

PIC18F67K22.zip

31.74 KB

使用特权

评论回复
评论
CoolSilicon 2019-9-11 13:59 回复TA
@WUQIMENG :你需求的是1s或者2s的中断, 1. 要么直接设置一个1s或者2s的中断, 那么进中断的时候几个指令周期的误差, 相对于s单位来说, 可以忽略不计了. 2. 你非要用100us这样的小单位的计数累加, 来实现1s或2s的中断, 那么, MCU会中断的非常频繁, 并且对delay要求非常严格, 你要手动补偿, 补偿不准的话, 误差还会累积. 如果非要用这种方法做, 时间累计单位用100ms或200ms吧... 
WUQIMENG 2019-9-11 09:52 回复TA
用过了,一样这个效果,然后经过多次测试~确实是又14个时钟周期的误差,不管我延时多久,总是有14个时钟误差在里面 
WUQIMENG 2019-9-11 09:52 回复TA
用过了,一样这个效果,然后经过多次测试~确实是又14个时钟周期的误差,不管我延时多久,总是有14个时钟误差在里面 
9
奔波儿熊| | 2019-9-11 10:35 | 只看该作者
楼主你看看这个帖子就明白了 , 这个帖子里是9us https://bbs.21ic.com/icview-2854688-1-1.html

使用特权

评论回复
10
WUQIMENG|  楼主 | 2019-9-11 14:19 | 只看该作者

这个~没说是要1S延时,要100us,1s我是用来测试的

使用特权

评论回复
11
奔波儿熊| | 2019-9-11 14:57 | 只看该作者
楼主还可以提高主频试试,还可以调整编译器的优化等级看看,  没其他太好的办法

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

1

主题

12

帖子

0

粉丝