PIC 端口行为随机
PIC ports behaves randomly
我已经尝试了几个小时来点亮按钮上的简单 LED,但没有成功。由于某种原因,引脚似乎随机变低和变高。
我正在使用 MPLAB X IDE v5.54 和 PIC12F1822。
谁能发现我的错误?
代码如下:
// CONFIG1
#pragma config FOSC = ECH // Oscillator Selection (ECH, External Clock, High Power Mode (4-32 MHz): device clock supplied to CLKIN pin)
#pragma config WDTE = ON // Watchdog Timer Enable (WDT enabled)
#pragma config PWRTE = OFF // Power-up Timer Enable (PWRT disabled)
#pragma config MCLRE = ON // MCLR Pin Function Select (MCLR/VPP pin function is MCLR)
#pragma config CP = OFF // Flash Program Memory Code Protection (Program memory code protection is disabled)
#pragma config CPD = OFF // Data Memory Code Protection (Data memory code protection is disabled)
#pragma config BOREN = ON // Brown-out Reset Enable (Brown-out Reset enabled)
#pragma config CLKOUTEN = OFF // Clock Out Enable (CLKOUT function is disabled. I/O or oscillator function on the CLKOUT pin)
#pragma config IESO = ON // Internal/External Switchover (Internal/External Switchover mode is enabled)
#pragma config FCMEN = ON // Fail-Safe Clock Monitor Enable (Fail-Safe Clock Monitor is enabled)
// CONFIG2
#pragma config WRT = OFF // Flash Memory Self-Write Protection (Write protection off)
#pragma config PLLEN = ON // PLL Enable (4x PLL enabled)
#pragma config STVREN = ON // Stack Overflow/Underflow Reset Enable (Stack Overflow or Underflow will cause a Reset)
#pragma config BORV = LO // Brown-out Reset Voltage Selection (Brown-out Reset Voltage (Vbor), low trip point selected.)
#pragma config LVP = ON // Low-Voltage Programming Enable (Low-voltage programming enabled)
#include <xc.h>
#define _XTAL_FREQ 8000000 // SET frequency as 8000000 bit because of the 8 MHz clock
int main(int argc, char** argv) {
OSCCON = 0xF0; // Internal oscillator 8MHz and PLL enabled
ADCON0 = 0; // Disable ADC module
ANSELAbits.ANSA2 = 0; // SET LED PIN to Digital
ANSELAbits.ANSA4 = 0; // SET Button pin to Digital
TRISAbits.TRISA2 = 0; // LED bit is output
TRISAbits.TRISA4 = 1; // Button bit is input
PORTAbits.RA4 = 0; // Button bit low initial
PORTAbits.RA2 = 0; // LED bit low initial
while (1) {
while (PORTAbits.RA4 == 0); // Wait until button is pressed
__delay_ms(100); // wait 100ms
PORTAbits.RA2 = 1; // Light up the LED
__delay_ms(100); // wait 100ms
while (PORTAbits.RA4 == 1); // Wait until button release
__delay_ms(100); // wait 100ms
PORTAbits.RA2 = 0; // Turn off the LED
__delay_ms(100); // wait 100ms
}
return (EXIT_SUCCESS);
}
我尝试了很多方法,例如:
- 天知道修改配置多少次
- 使所有引脚一一输入、输出、数字、模拟等
我想不出别的了。
任何帮助将不胜感激。
编辑 1
这是我拥有的最新代码。这个随机打开和关闭 LED。我还禁用了看门狗定时器:
// CONFIG1
#pragma config FOSC = ECH // Oscillator Selection (ECH, External Clock, High Power Mode (4-32 MHz): device clock supplied to CLKIN pin)
#pragma config WDTE = OFF // Watchdog Timer Enable (WDT disabled)
#pragma config PWRTE = OFF // Power-up Timer Enable (PWRT disabled)
#pragma config MCLRE = ON // MCLR Pin Function Select (MCLR/VPP pin function is MCLR)
#pragma config CP = OFF // Flash Program Memory Code Protection (Program memory code protection is disabled)
#pragma config CPD = OFF // Data Memory Code Protection (Data memory code protection is disabled)
#pragma config BOREN = ON // Brown-out Reset Enable (Brown-out Reset enabled)
#pragma config CLKOUTEN = OFF // Clock Out Enable (CLKOUT function is disabled. I/O or oscillator function on the CLKOUT pin)
#pragma config IESO = ON // Internal/External Switchover (Internal/External Switchover mode is enabled)
#pragma config FCMEN = ON // Fail-Safe Clock Monitor Enable (Fail-Safe Clock Monitor is enabled)
// CONFIG2
#pragma config WRT = OFF // Flash Memory Self-Write Protection (Write protection off)
#pragma config PLLEN = ON // PLL Enable (4x PLL enabled)
#pragma config STVREN = ON // Stack Overflow/Underflow Reset Enable (Stack Overflow or Underflow will cause a Reset)
#pragma config BORV = LO // Brown-out Reset Voltage Selection (Brown-out Reset Voltage (Vbor), low trip point selected.)
#pragma config LVP = ON // Low-Voltage Programming Enable (Low-voltage programming enabled)
#include <xc.h> // include standard header file
// Definitions
#define _XTAL_FREQ 16000000 // this is used by the __delay_ms(xx) and __delay_us(xx) functions
void main() {
// set up oscillator control register
OSCCONbits.SPLLEN = 0; // PLL is disabled
OSCCONbits.IRCF = 0x0F; //set OSCCON IRCF bits to select OSC frequency=16Mhz
OSCCONbits.SCS = 0x02; //set the SCS bits to select internal oscillator block
ANSELAbits.ANSA0 = 0; // Set to digital
ANSELAbits.ANSA1 = 0; // Set to digital
ANSELAbits.ANSA2 = 0; // Set to digital
ANSELAbits.ANSA4 = 0; // Set to digital
// Set up I/O pins
// PORT A Assignments
TRISAbits.TRISA0 = 0; // RA0 = Digital Voltage out
TRISAbits.TRISA1 = 0; // RA1 = Digital Voltage out
TRISAbits.TRISA2 = 0; // RA2 = Digital Voltage out
TRISAbits.TRISA3 = 0; // RA3 = Digital Voltage out
TRISAbits.TRISA4 = 1; // RA4 = Digital Voltage in
TRISAbits.TRISA5 = 0; // RA0 = Digital Voltage out
PORTAbits.RA0 = 0;
PORTAbits.RA1 = 0;
PORTAbits.RA2 = 0;
PORTAbits.RA3 = 0;
PORTAbits.RA4 = 0;
PORTAbits.RA5 = 0;
// Set up ADC
ADCON0 = 0; // ADC is off
for (;;) {
__delay_ms(100); // wait 100ms
if (PORTAbits.RA4 == 0) {
LATAbits.LATA2 = 0;
} else {
LATAbits.LATA2 = 1;
}
}
}
好的,这是我观察到的。当按下按钮时,LED 永远不会关闭,但当按钮未按下时,它会随机打开或关闭。
在输入上观察到的随机值问题通常是由浮动输入引起的。如果输入不是由输出或某种源驱动,则认为输入处于 浮动 状态。在这种情况下,浮动输入就像天线一样,它可以随机获得任何电压电平,并且连接到它的逻辑在 1 和 0 之间随机切换。
似乎大多数时候,电子学和 uC 初学者是在尝试使用按钮时才第一次了解它们。我的经历很相似。当我的手指靠近按钮时输入被触发,但在我真正按下甚至触摸它之前。后来观察到uC的相邻输出管脚变化也能触发
幸运的是,解决方案很简单。只需加一个上拉或下拉电阻,即使按键未按下,输出也由VDD或GND驱动。上拉似乎更受欢迎(我不确定为什么),因此您通常以这样的方式连接按钮,即在按下按钮时将输入引脚拉至地面,并在按钮之间提供一个上拉电阻引脚和 VDD。在这种情况下,您的程序逻辑在按下按钮时将输入读取为 0。
顺便说一句,您可以将引脚直接连接到 VDD 以防止其悬空。但在这种情况下,按下按钮会将 VDD 短路到 GND,使 VDD 崩溃并重置 uC。这也会损坏电源调节器(实际上它们中的大多数都有热关断保护自己)、按钮本身或电线(或 PCB 上的走线)。这就是为什么你需要一个电阻。
大多数微控制器还提供内部弱上拉,可以通过软件激活。在这里,weak 意味着这些电阻器具有高值(如 100k 欧姆)并且它们不会 strongly 拉动引脚。如果您需要更强大的(例如拉起通信线路),您可能需要使用外部的。
一些较新的uC也可能提供内部弱下拉电阻。 STM32 uC 具有此功能。您的 PIC12F1822 只有上拉电阻,但幸运的是它们可以单独控制。在一些较旧的 PIC 型号中,您只有一个开关来激活 PORTB 所有引脚上的上拉。
要在 RA4 上激活内部弱上拉:
OPTION_REGbits.nWPUEN = 0; // Global pull-up enable bit (inverted)
WPUAbits.WPUA4 = 1; // Individual pin pull-up enable bit
我已经尝试了几个小时来点亮按钮上的简单 LED,但没有成功。由于某种原因,引脚似乎随机变低和变高。
我正在使用 MPLAB X IDE v5.54 和 PIC12F1822。 谁能发现我的错误?
代码如下:
// CONFIG1
#pragma config FOSC = ECH // Oscillator Selection (ECH, External Clock, High Power Mode (4-32 MHz): device clock supplied to CLKIN pin)
#pragma config WDTE = ON // Watchdog Timer Enable (WDT enabled)
#pragma config PWRTE = OFF // Power-up Timer Enable (PWRT disabled)
#pragma config MCLRE = ON // MCLR Pin Function Select (MCLR/VPP pin function is MCLR)
#pragma config CP = OFF // Flash Program Memory Code Protection (Program memory code protection is disabled)
#pragma config CPD = OFF // Data Memory Code Protection (Data memory code protection is disabled)
#pragma config BOREN = ON // Brown-out Reset Enable (Brown-out Reset enabled)
#pragma config CLKOUTEN = OFF // Clock Out Enable (CLKOUT function is disabled. I/O or oscillator function on the CLKOUT pin)
#pragma config IESO = ON // Internal/External Switchover (Internal/External Switchover mode is enabled)
#pragma config FCMEN = ON // Fail-Safe Clock Monitor Enable (Fail-Safe Clock Monitor is enabled)
// CONFIG2
#pragma config WRT = OFF // Flash Memory Self-Write Protection (Write protection off)
#pragma config PLLEN = ON // PLL Enable (4x PLL enabled)
#pragma config STVREN = ON // Stack Overflow/Underflow Reset Enable (Stack Overflow or Underflow will cause a Reset)
#pragma config BORV = LO // Brown-out Reset Voltage Selection (Brown-out Reset Voltage (Vbor), low trip point selected.)
#pragma config LVP = ON // Low-Voltage Programming Enable (Low-voltage programming enabled)
#include <xc.h>
#define _XTAL_FREQ 8000000 // SET frequency as 8000000 bit because of the 8 MHz clock
int main(int argc, char** argv) {
OSCCON = 0xF0; // Internal oscillator 8MHz and PLL enabled
ADCON0 = 0; // Disable ADC module
ANSELAbits.ANSA2 = 0; // SET LED PIN to Digital
ANSELAbits.ANSA4 = 0; // SET Button pin to Digital
TRISAbits.TRISA2 = 0; // LED bit is output
TRISAbits.TRISA4 = 1; // Button bit is input
PORTAbits.RA4 = 0; // Button bit low initial
PORTAbits.RA2 = 0; // LED bit low initial
while (1) {
while (PORTAbits.RA4 == 0); // Wait until button is pressed
__delay_ms(100); // wait 100ms
PORTAbits.RA2 = 1; // Light up the LED
__delay_ms(100); // wait 100ms
while (PORTAbits.RA4 == 1); // Wait until button release
__delay_ms(100); // wait 100ms
PORTAbits.RA2 = 0; // Turn off the LED
__delay_ms(100); // wait 100ms
}
return (EXIT_SUCCESS);
}
我尝试了很多方法,例如:
- 天知道修改配置多少次
- 使所有引脚一一输入、输出、数字、模拟等
我想不出别的了。
任何帮助将不胜感激。
编辑 1
这是我拥有的最新代码。这个随机打开和关闭 LED。我还禁用了看门狗定时器:
// CONFIG1
#pragma config FOSC = ECH // Oscillator Selection (ECH, External Clock, High Power Mode (4-32 MHz): device clock supplied to CLKIN pin)
#pragma config WDTE = OFF // Watchdog Timer Enable (WDT disabled)
#pragma config PWRTE = OFF // Power-up Timer Enable (PWRT disabled)
#pragma config MCLRE = ON // MCLR Pin Function Select (MCLR/VPP pin function is MCLR)
#pragma config CP = OFF // Flash Program Memory Code Protection (Program memory code protection is disabled)
#pragma config CPD = OFF // Data Memory Code Protection (Data memory code protection is disabled)
#pragma config BOREN = ON // Brown-out Reset Enable (Brown-out Reset enabled)
#pragma config CLKOUTEN = OFF // Clock Out Enable (CLKOUT function is disabled. I/O or oscillator function on the CLKOUT pin)
#pragma config IESO = ON // Internal/External Switchover (Internal/External Switchover mode is enabled)
#pragma config FCMEN = ON // Fail-Safe Clock Monitor Enable (Fail-Safe Clock Monitor is enabled)
// CONFIG2
#pragma config WRT = OFF // Flash Memory Self-Write Protection (Write protection off)
#pragma config PLLEN = ON // PLL Enable (4x PLL enabled)
#pragma config STVREN = ON // Stack Overflow/Underflow Reset Enable (Stack Overflow or Underflow will cause a Reset)
#pragma config BORV = LO // Brown-out Reset Voltage Selection (Brown-out Reset Voltage (Vbor), low trip point selected.)
#pragma config LVP = ON // Low-Voltage Programming Enable (Low-voltage programming enabled)
#include <xc.h> // include standard header file
// Definitions
#define _XTAL_FREQ 16000000 // this is used by the __delay_ms(xx) and __delay_us(xx) functions
void main() {
// set up oscillator control register
OSCCONbits.SPLLEN = 0; // PLL is disabled
OSCCONbits.IRCF = 0x0F; //set OSCCON IRCF bits to select OSC frequency=16Mhz
OSCCONbits.SCS = 0x02; //set the SCS bits to select internal oscillator block
ANSELAbits.ANSA0 = 0; // Set to digital
ANSELAbits.ANSA1 = 0; // Set to digital
ANSELAbits.ANSA2 = 0; // Set to digital
ANSELAbits.ANSA4 = 0; // Set to digital
// Set up I/O pins
// PORT A Assignments
TRISAbits.TRISA0 = 0; // RA0 = Digital Voltage out
TRISAbits.TRISA1 = 0; // RA1 = Digital Voltage out
TRISAbits.TRISA2 = 0; // RA2 = Digital Voltage out
TRISAbits.TRISA3 = 0; // RA3 = Digital Voltage out
TRISAbits.TRISA4 = 1; // RA4 = Digital Voltage in
TRISAbits.TRISA5 = 0; // RA0 = Digital Voltage out
PORTAbits.RA0 = 0;
PORTAbits.RA1 = 0;
PORTAbits.RA2 = 0;
PORTAbits.RA3 = 0;
PORTAbits.RA4 = 0;
PORTAbits.RA5 = 0;
// Set up ADC
ADCON0 = 0; // ADC is off
for (;;) {
__delay_ms(100); // wait 100ms
if (PORTAbits.RA4 == 0) {
LATAbits.LATA2 = 0;
} else {
LATAbits.LATA2 = 1;
}
}
}
好的,这是我观察到的。当按下按钮时,LED 永远不会关闭,但当按钮未按下时,它会随机打开或关闭。
在输入上观察到的随机值问题通常是由浮动输入引起的。如果输入不是由输出或某种源驱动,则认为输入处于 浮动 状态。在这种情况下,浮动输入就像天线一样,它可以随机获得任何电压电平,并且连接到它的逻辑在 1 和 0 之间随机切换。
似乎大多数时候,电子学和 uC 初学者是在尝试使用按钮时才第一次了解它们。我的经历很相似。当我的手指靠近按钮时输入被触发,但在我真正按下甚至触摸它之前。后来观察到uC的相邻输出管脚变化也能触发
幸运的是,解决方案很简单。只需加一个上拉或下拉电阻,即使按键未按下,输出也由VDD或GND驱动。上拉似乎更受欢迎(我不确定为什么),因此您通常以这样的方式连接按钮,即在按下按钮时将输入引脚拉至地面,并在按钮之间提供一个上拉电阻引脚和 VDD。在这种情况下,您的程序逻辑在按下按钮时将输入读取为 0。
顺便说一句,您可以将引脚直接连接到 VDD 以防止其悬空。但在这种情况下,按下按钮会将 VDD 短路到 GND,使 VDD 崩溃并重置 uC。这也会损坏电源调节器(实际上它们中的大多数都有热关断保护自己)、按钮本身或电线(或 PCB 上的走线)。这就是为什么你需要一个电阻。
大多数微控制器还提供内部弱上拉,可以通过软件激活。在这里,weak 意味着这些电阻器具有高值(如 100k 欧姆)并且它们不会 strongly 拉动引脚。如果您需要更强大的(例如拉起通信线路),您可能需要使用外部的。
一些较新的uC也可能提供内部弱下拉电阻。 STM32 uC 具有此功能。您的 PIC12F1822 只有上拉电阻,但幸运的是它们可以单独控制。在一些较旧的 PIC 型号中,您只有一个开关来激活 PORTB 所有引脚上的上拉。
要在 RA4 上激活内部弱上拉:
OPTION_REGbits.nWPUEN = 0; // Global pull-up enable bit (inverted)
WPUAbits.WPUA4 = 1; // Individual pin pull-up enable bit