使用 PIC16F887 在 MicroC 中反转 PORTB 的值需要 1 秒的延迟
1 second delay to inverse the value of PORTB in MicroC with PIC16F887
微控制器PIC16F887
//
任务说:
编写将反转 PORTB 并使其成为输出端口的程序,并且每隔一秒它将在 LED 二极管
上进行反转 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(预分频)* 160 (256-96) = ~ 391
所以当计数器达到 391 时,一秒延迟应该是 2M / 32 * 160
但是当我在 8Mhz 模拟上启动它时,LED DIODS 反转的时间比 1 秒快得多。
所以你能帮我找出问题所在以及如何让它每秒反转一次吗?谢谢
建议你看一下PIC16F系列的datasheet。在开始使用之前了解每个寄存器及其意义非常重要
你提到,如果你从while循环中去掉cnt的增量,它需要超过10秒,这清楚地表明,时钟,TMR0值和循环值不同步。
下面link解释的简单计时器实现,可能对您有所帮助
http://www.microcontrollerboard.com/pic-timer0-tutorial.html
苏希
从要求回答此作业问题到现在已经 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();
}
}
也许老师们会为下学期提出新的作业。
微控制器PIC16F887 // 任务说: 编写将反转 PORTB 并使其成为输出端口的程序,并且每隔一秒它将在 LED 二极管
上进行反转 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(预分频)* 160 (256-96) = ~ 391 所以当计数器达到 391 时,一秒延迟应该是 2M / 32 * 160 但是当我在 8Mhz 模拟上启动它时,LED DIODS 反转的时间比 1 秒快得多。
所以你能帮我找出问题所在以及如何让它每秒反转一次吗?谢谢
建议你看一下PIC16F系列的datasheet。在开始使用之前了解每个寄存器及其意义非常重要
你提到,如果你从while循环中去掉cnt的增量,它需要超过10秒,这清楚地表明,时钟,TMR0值和循环值不同步。
下面link解释的简单计时器实现,可能对您有所帮助
http://www.microcontrollerboard.com/pic-timer0-tutorial.html
苏希
从要求回答此作业问题到现在已经 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();
}
}
也许老师们会为下学期提出新的作业。