如何用C语言复位PIC18?

发布于 2024-07-06 16:39:19 字数 165 浏览 5 评论 0原文

通过 HiTech Pic18 C 编译器使用 C 代码重置 PIC18 的最佳方法是什么?

编辑:

我正在使用

void reset()
{
#asm 
  reset
#endasm
}

,但必须有更好的方法

What is the best way to reset a PIC18 using C code with the HiTech Pic18 C compiler?

Edit:

I am currenlty using

void reset()
{
#asm 
  reset
#endasm
}

but there must be a better way

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

够钟 2024-07-13 16:39:19

编译器通常内置有自己的 Reset() 函数,但它只是完全执行您的函数的操作,并且实际名称可能因编译器而异。

您已经以最好的方式做到了。

The compilers usually have their own reset() function built in, but it just does exactly what your function does, and the actual name may vary from compiler to compiler.

You are already doing it the best possible way.

萤火眠眠 2024-07-13 16:39:19

您的回答是我所知道的最好的方法。 关键是您在函数调用中拥有汇编指令,全部都是单独的。
编译器不会优化包含内联汇编的函数,因此,如果将重置指令内联到非常大的函数中,编译器将不会优化该函数中的任何代码。 您可以通过将 Reset 放入其自己的函数中来避免这种情况。 该函数中的代码不会被优化,但谁在乎呢,因为它是一个很小的函数。

Your answer is the best way I know of. The key is that you have the assembly instruction inside a function call, all by itself.
The compiler will not optimize a function that has inline assembly in it, so if you include the reset instruction inline to a very large function, the compiler will not optimize any of the code in that function. You have avoided this by putting Reset in its own function. The code in this function won't be optimized, but who cares, since it is such a small function.

自在安然 2024-07-13 16:39:19

这里有一个常见问题解答

问:如何重置微控制器?

一种方法是将所有变量重置为
它们的默认值,如 PIC 中列出的
手动的。 然后,使用汇编语言
跳转到位置 0x0000
微。

#asm ljmp 0x0000

#endasm

即使在
在中断内调用或
程序。 PIC 16x 系列微处理器
有 8 个堆栈级别。 每次一个
调用过程,一级堆栈
已用完返回地址。 它
是一个循环缓冲区,所以即使
micro 的深度为 7 个程序级别
在中断时复位
叫,这是新的开始
堆栈缓冲区,并且微将
继续正常进行。

另一种方法是设置看门狗
芯片编程时的定时器,以及
始终使用 CLRWDT() 指令
代码。 当你想要微
复位,停止清除看门狗位
并且微型将在大约之后重置
18 毫秒至 2 秒,具体取决于
预分频器。

There's a FAQ here.

Q: How do I reset the micro?

One way is to reset all variables to
their defaults, as listed in the PIC
manual. Then, use assembly language
to jump to location 0x0000 in the
micro.

#asm ljmp 0x0000

#endasm

This is quite safe to use, even when
called within interrupts or
procedures. The PIC 16x series micros
have 8 stack levels. Each time a
procedure is called, one stack level
is used up for the return address. It
is a circular buffer, so even if the
micro is 7 procedure levels deep and
in an interrupt when a reset is
called, this is the new start of the
stack buffer, and the micro will
continue as per normal.

Another way is to set watchdog the
timer when the chip is programmed, and
use CLRWDT() instructions all through
the code. When you want the micro to
reset, stop clearing the watchdog bit
and the micro will reset after around
18ms to 2 seconds depending on the
prescaler.

苦行僧 2024-07-13 16:39:19

由于 Mike 编辑了 11 年前的这个原始问题,因此原始海报是否需要全面的答案似乎值得怀疑。 事实上,在过去 9 年里,OP 似乎只询问或回答了 2 个有关微控制器的主题。

考虑到所有这些,了解使用使用 Hi-Tech C 或 XC8(现在由 Microchip 称为)编译的代码从复位向量开始执行 PIC18F 控制器的一些方法可能会有所帮助。

该代码已使用 MPLABX v5.25、XC8 v2.05 和 PIC18F45K20 控制器进行了测试。

/*
 * File:     main.c
 * Author:   dan1138
 * Target:   PIC18F45K20
 * Compiler: XC8 v2.05
 *
 *                                                             PIC18F46K20
 *                 +---------+                 +---------+                 +----------+                 +----------+
 *           <>  1 : RC7/RX  :           -- 12 : NC      :           <> 23 : RA4      :           -- 34 : NC       :
 *      LED4 <>  2 : RD4     :           -- 13 : NC      :           <> 24 : RA5      : 32.768KHz -> 35 : RC1/SOSI :
 *      LED5 <>  3 : RD5     :           <> 14 : RB4     :           <> 25 : RE0      :           <> 36 : RC2      :
 *      LED6 <>  4 : RD6     :           <> 15 : RB5/PGM :           <> 26 : RE1      :           <> 37 : RC3      :
 *       GND ->  5 : VSS     :       PGC <> 16 : RB6/PGC :           <> 27 : RE2      :      LED0 <> 38 : RD0      :
 *       3v3 ->  6 : VDD     :       PGD <> 17 : RB7/PGD :       3v3 -> 28 : VDD      :      LED1 <> 39 : RD1      :
 *       SW1 <>  7 : RB0/INT :       VPP -> 18 : RE3/VPP :       GND -> 29 : VSS      :      LED2 <> 40 : RD2      :
 *           <>  8 : RB1     :       POT <> 19 : RA0/AN0 :      4MHz -> 30 : RA7/OSC1 :      LED3 <> 41 : RD3      :
 *           <>  9 : RB2     :           <> 20 : RA1     :      4MHz <- 31 : RA6/OSC2 :           <> 42 : RC4      :
 *           <> 10 : RB3     :           <> 21 : RA2     : 32.767KHz <- 32 : RC0/SOSO :           <> 43 : RC5      :
 *      LED7 <> 11 : RD7     :           <> 22 : RA3     :           -- 33 : NC       :           <> 44 : RC6/TX   :
 *                 +---------+                 +---------+                 +----------+                 +----------+
 *                                                              TQFP-44
 *
 *
 * Created on December 21, 2019, 2:26 PM
 */

/* Target specific configuration words */
#pragma config FOSC = INTIO67, FCMEN = OFF
#pragma config IESO = OFF, PWRT = OFF, BOREN = SBORDIS, BORV = 18
#pragma config WDTEN = OFF, WDTPS = 32768, CCP2MX = PORTC, PBADEN = OFF
#pragma config LPT1OSC = ON, HFOFST = ON
#pragma config MCLRE = ON, STVREN = ON, LVP = OFF, XINST = OFF
#pragma config CP0 = OFF, CP1 = OFF, CP2 = OFF, CP3 = OFF
#pragma config CPB = OFF, CPD = OFF
#pragma config WRT0 = OFF, WRT1 = OFF, WRT2 = OFF, WRT3 = OFF
#pragma config WRTC = OFF, WRTB = OFF, WRTD = OFF
#pragma config EBTR0 = OFF, EBTR1 = OFF, EBTR2 = OFF, EBTR3 = OFF
#pragma config EBTRB = OFF

/* Target specific definitions for special function registers */
#include <xc.h>

/* Declare the system oscillator frequency setup by the code */
#define _XTAL_FREQ (4000000UL)

/* reset instruction */
void ResetMethod_1(void)
{
    asm(" reset");
}

/* long jump to absolute address zero */
void ResetMethod_2(void)
{
    INTCON = 0;
    asm(" pop\n ljmp 0");
}

/* return to absolute address zero */
void ResetMethod_3(void)
{
    INTCON = 0;
    asm(" clrf TOSU\n clrf TOSH\n clrf TOSL\n");
}

/* provoke stackoverflow reset */
void ResetMethod_4(void)
{
    INTCON = 0;
    while (1) 
    {
        asm(" push\n");
    }
}

/* provoke stackunderflow reset */
void ResetMethod_5(void)
{
    INTCON = 0;
    STKPTR = 0;
}

/* clear the program counter */
void ResetMethod_6(void)
{
    INTCON = 0;
    asm(" clrf PCLATU\n clrf PCLATH\n clrf PCL\n");
}

void main(void)
{
    INTCON = 0;             /* Disable all interrupt sources */
    PIE1 = 0;
    PIE2 = 0;
    INTCON3bits.INT1IE = 0;
    INTCON3bits.INT2IE = 0;

    OSCCON = 0x50;          /* set internal oscillator to 4MHz */
    OSCTUNEbits.TUN = 0;    /* use factory calibration of internal oscillator */
    ANSEL = 0;
    ANSELH = 0;
    
    if(!RCONbits.nPOR)
    {
        RCONbits.nPOR = 1;
        LATD = 0;
    }
    
    TRISD = 0;
    /*
     * Application loop
     */
    while(1)
    {
        __delay_ms(500);
        if (LATDbits.LD0 == 0)
        {
            LATDbits.LD0 = 1;
            ResetMethod_1();
        }
        
        if (LATDbits.LD1 == 0)
        {
            LATDbits.LD1 = 1;
            ResetMethod_2();
        }

        if (LATDbits.LD2 == 0)
        {
            LATDbits.LD2 = 1;
            ResetMethod_3();
        }
        
        if (LATDbits.LD3 == 0)
        {
            LATDbits.LD3 = 1;
            ResetMethod_4();
        }

        if (LATDbits.LD4 == 0)
        {
            LATDbits.LD4 = 1;
            ResetMethod_5();
        }

        if (LATDbits.LD5 == 0)
        {
            LATDbits.LD5 = 1;
            ResetMethod_6();
        }
    }
}

As Mike has edited this original question from 11 years ago it seems doubtful the Original Poster needs a comprehensive answer. In fact the OP seems to have asked about or responded on just 2 topics regarding microcontrollers in the past 9 years.

Given all that it may be helpful to look at some of the ways the PIC18F controller can be caused to begin execution from the reset vector with code that compiles with Hi-Tech C or XC8 as it is now called by Microchip.

This code has been tested using MPLABX v5.25, XC8 v2.05 and the PIC18F45K20 controller.

/*
 * File:     main.c
 * Author:   dan1138
 * Target:   PIC18F45K20
 * Compiler: XC8 v2.05
 *
 *                                                             PIC18F46K20
 *                 +---------+                 +---------+                 +----------+                 +----------+
 *           <>  1 : RC7/RX  :           -- 12 : NC      :           <> 23 : RA4      :           -- 34 : NC       :
 *      LED4 <>  2 : RD4     :           -- 13 : NC      :           <> 24 : RA5      : 32.768KHz -> 35 : RC1/SOSI :
 *      LED5 <>  3 : RD5     :           <> 14 : RB4     :           <> 25 : RE0      :           <> 36 : RC2      :
 *      LED6 <>  4 : RD6     :           <> 15 : RB5/PGM :           <> 26 : RE1      :           <> 37 : RC3      :
 *       GND ->  5 : VSS     :       PGC <> 16 : RB6/PGC :           <> 27 : RE2      :      LED0 <> 38 : RD0      :
 *       3v3 ->  6 : VDD     :       PGD <> 17 : RB7/PGD :       3v3 -> 28 : VDD      :      LED1 <> 39 : RD1      :
 *       SW1 <>  7 : RB0/INT :       VPP -> 18 : RE3/VPP :       GND -> 29 : VSS      :      LED2 <> 40 : RD2      :
 *           <>  8 : RB1     :       POT <> 19 : RA0/AN0 :      4MHz -> 30 : RA7/OSC1 :      LED3 <> 41 : RD3      :
 *           <>  9 : RB2     :           <> 20 : RA1     :      4MHz <- 31 : RA6/OSC2 :           <> 42 : RC4      :
 *           <> 10 : RB3     :           <> 21 : RA2     : 32.767KHz <- 32 : RC0/SOSO :           <> 43 : RC5      :
 *      LED7 <> 11 : RD7     :           <> 22 : RA3     :           -- 33 : NC       :           <> 44 : RC6/TX   :
 *                 +---------+                 +---------+                 +----------+                 +----------+
 *                                                              TQFP-44
 *
 *
 * Created on December 21, 2019, 2:26 PM
 */

/* Target specific configuration words */
#pragma config FOSC = INTIO67, FCMEN = OFF
#pragma config IESO = OFF, PWRT = OFF, BOREN = SBORDIS, BORV = 18
#pragma config WDTEN = OFF, WDTPS = 32768, CCP2MX = PORTC, PBADEN = OFF
#pragma config LPT1OSC = ON, HFOFST = ON
#pragma config MCLRE = ON, STVREN = ON, LVP = OFF, XINST = OFF
#pragma config CP0 = OFF, CP1 = OFF, CP2 = OFF, CP3 = OFF
#pragma config CPB = OFF, CPD = OFF
#pragma config WRT0 = OFF, WRT1 = OFF, WRT2 = OFF, WRT3 = OFF
#pragma config WRTC = OFF, WRTB = OFF, WRTD = OFF
#pragma config EBTR0 = OFF, EBTR1 = OFF, EBTR2 = OFF, EBTR3 = OFF
#pragma config EBTRB = OFF

/* Target specific definitions for special function registers */
#include <xc.h>

/* Declare the system oscillator frequency setup by the code */
#define _XTAL_FREQ (4000000UL)

/* reset instruction */
void ResetMethod_1(void)
{
    asm(" reset");
}

/* long jump to absolute address zero */
void ResetMethod_2(void)
{
    INTCON = 0;
    asm(" pop\n ljmp 0");
}

/* return to absolute address zero */
void ResetMethod_3(void)
{
    INTCON = 0;
    asm(" clrf TOSU\n clrf TOSH\n clrf TOSL\n");
}

/* provoke stackoverflow reset */
void ResetMethod_4(void)
{
    INTCON = 0;
    while (1) 
    {
        asm(" push\n");
    }
}

/* provoke stackunderflow reset */
void ResetMethod_5(void)
{
    INTCON = 0;
    STKPTR = 0;
}

/* clear the program counter */
void ResetMethod_6(void)
{
    INTCON = 0;
    asm(" clrf PCLATU\n clrf PCLATH\n clrf PCL\n");
}

void main(void)
{
    INTCON = 0;             /* Disable all interrupt sources */
    PIE1 = 0;
    PIE2 = 0;
    INTCON3bits.INT1IE = 0;
    INTCON3bits.INT2IE = 0;

    OSCCON = 0x50;          /* set internal oscillator to 4MHz */
    OSCTUNEbits.TUN = 0;    /* use factory calibration of internal oscillator */
    ANSEL = 0;
    ANSELH = 0;
    
    if(!RCONbits.nPOR)
    {
        RCONbits.nPOR = 1;
        LATD = 0;
    }
    
    TRISD = 0;
    /*
     * Application loop
     */
    while(1)
    {
        __delay_ms(500);
        if (LATDbits.LD0 == 0)
        {
            LATDbits.LD0 = 1;
            ResetMethod_1();
        }
        
        if (LATDbits.LD1 == 0)
        {
            LATDbits.LD1 = 1;
            ResetMethod_2();
        }

        if (LATDbits.LD2 == 0)
        {
            LATDbits.LD2 = 1;
            ResetMethod_3();
        }
        
        if (LATDbits.LD3 == 0)
        {
            LATDbits.LD3 = 1;
            ResetMethod_4();
        }

        if (LATDbits.LD4 == 0)
        {
            LATDbits.LD4 = 1;
            ResetMethod_5();
        }

        if (LATDbits.LD5 == 0)
        {
            LATDbits.LD5 = 1;
            ResetMethod_6();
        }
    }
}
花桑 2024-07-13 16:39:19

除非编译器供应商的运行时库定义了一个库函数(如果这样的库甚至存在于微控制器世界中......但它应该),那么就不会。 C 本身当然不会帮助你,做“重置”对于 C 来说是一个平台特定的问题,无法涵盖它。

Unless there's a library function defined by the compiler vendor's runtime library (if such a lib even exists in the microcontroller world ... but it should), then no. C itself certainly won't help you out, doing "a reset" is far too much of a platform-specific issue for C to cover it.

雨的味道风的声音 2024-07-13 16:39:19

我使用 ccsinfo.com 编译器,它有一个类似的 API 调用来重置 PIC,但我认为编译器的解决方案会做正确的事情。

I use the ccsinfo.com compiler, which has a similar API call for resetting the PIC, but I would think the compiler's solution would do the right thing.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文