0

微控制器 PIC16F887 // 任务说:编写程序,该程序将反转 PORTB 并使其输出端口,并且每隔一秒它将在 Led Diods 上进行反向 ON/OFF

这是我的代码:

unsigned cnt ;

void interrupt(){
     if(TMR0IF_bit){ //if there is interrupt in timer0
      cnt++;         //increase the counter
      TMR0IF_bit=0;  //reset the timer
      TMR0 = 96;     //set the TMR0 to its default value
     }
}

void main() {
ANSEL = 0;
ANSELH = 0;
OPTION_REG = 0b00000100; //1:32 prescalar (last 3 bits are 100)
INTCON = 0xA0;          //enable interrupt generated by TMR0
TRISB = 0x00;           //make PORTB output port
PORTB = 0xFF;           //set PORTB to 1s
cnt =0;                 //initialize counter
TMR0 = 96;              //starting value of TMR0

do{
if(cnt==391){           
 PORTB = ~PORTB;       //invert PORTB
 cnt=0;                //reset the timer
}
cnt++;                 //increase counter if its not 391
}while(1);
}

重要 TMR0 = 96 是起始值,256-96 = 160 OPTION_REG = 1:32 所以预标量是 32 我们需要接近 2M 因为 2M 指令就像他们说的那样接近 1 秒

2 000 000 / 32 (prescalar) * 160 (256-96) = ~ 391 所以当计数器达到 391 时一秒钟的延迟应该是 2M / 32 * 160 但是当我以 8Mhz 模拟启动它时,LED DIODS 在更快的时间内反转超过 1 秒。

所以你能帮我弄清楚问题出在哪里,以及如何让它每秒钟都反转。谢谢

4

2 回答 2

0

从要求回答这个家庭作业问题到现在已经 7 个月了。几乎每个学期都会分配这个问题的一个变体,所以这里有一个可能的解决方案供你剽窃:

/*
 * file:        main.c
 * author:      dan1138
 * target:      PIC16F887
 * IDE:         MPLAB 8 v8.92
 * Compiler:    XC8 v1.45
 *
 * Description:
 *  program that will invert PORTB and will make
 *  it output port and in every SECOND it will make
 *  inverse ON/OFF on the Led Diodes.
 */
#include <xc.h>

/* Setup Configuration word 1 for the PIC16F887 */
__CONFIG( FOSC_INTRC_NOCLKOUT & WDTE_ON & PWRTE_OFF & MCLRE_ON & CP_OFF & CPD_OFF & BOREN_OFF & IESO_OFF & FCMEN_OFF & LVP_OFF );

/* Setup Configuration word 2 for the PIC16F887 */
__CONFIG( BOR4V_BOR21V & WRT_OFF );

#define FSYS 8000000L       /* target device system clock freqency */
#define FCYC (FSYS/4L)      /* target device instruction clock freqency */

#define _XTAL_FREQ FSYS     /* required for XC8 delay macros */

#define TIMER0_RELOAD_VALUE (250u)
/*
 * Handle Interrupt Events
 */
void interrupt ISR_Handler( void )
{
    static unsigned short OneSecondTick = 0;

    if(INTCONbits.TMR0IE)
    {
        if(INTCONbits.TMR0IF)
        {
            INTCONbits.TMR0IF = 0;
            TMR0 -= (TIMER0_RELOAD_VALUE - 3u);

            if(OneSecondTick == 0)
            {
                OneSecondTick = (FCYC / TIMER0_RELOAD_VALUE);
                PORTB ^= 0xFF;
            }
            OneSecondTick--;
        }
    }
}
/*
 * Main application
 */
void main(void)
{
    /* Initialisation */
    INTCON = 0x00;
    PIE1   = 0x00;
    PIE2   = 0x00;

    OSCCON = 0x70;          /* select 8MHz internal clock */
    CLRWDT();

    PORTA = 0x00;
    PORTB = 0x00;
    PORTC = 0x00;
    PORTD = 0x00;
    PORTE = 0x00;

    TRISA = 0x00;
    TRISB = 0x00;
    TRISC = 0xC0;  /* TRISC Bits 7 and 6 must be inputs when UART is used */
    TRISD = 0x00;
    TRISE = 0x00;

    OPTION_REG = 0xDF; /* PORTB pull up off, INT on low to high edge,           */
                       /* TMR0 clock is FCYC, WDT has prescaler, WDT rate 1:128 */

    /* Disable all analog inputs and use for digital I/O */
    ANSEL  = 0x00;
    ANSELH = 0x00;
    ADCON0 = 0xC0;
    ADCON1 = 0x00;

    /* Disable comparators */
    CM1CON0 = 0x00;
    CM2CON0 = 0x00;
    VRCON   = 0x00;

    /* Initialize TIMER0 */
    INTCONbits.TMR0IF = 0;
    INTCONbits.TMR0IE = 1;

    /* enable system interrupts */
    GIE   = 1;

    /* Application loop */
    for(;;)
    {
        CLRWDT();
    }
}

也许导师会为下学期提出新的作业。

于 2018-07-23T08:15:01.223 回答
0

建议您仔细阅读 PIC16F 系列的数据表。在开始使用之前了解每个寄存器及其意义非常重要

您已经提到,如果您从 while 循环中删除 cnt 的增量,则需要超过 10 秒,这清楚地表明,时钟,TMR0 值和循环值不同步。

对于下面链接中解释的简单计时器实现,这可能会对您有所帮助

http://www.microcontrollerboard.com/pic-timer0-tutorial.html

苏迪

于 2017-12-05T03:43:42.910 回答