c - 如何检测PIC中的周期性GPIO变化
问题描述
我正在使用带有 MPLAB X IDE 的 PIC12F675 微控制器。我试图通过用光敏电阻监控 LED 来检测机器的状态。我有电路工作,当机器的 LED 亮起时,我的芯片正在获取输入并打开自己的 LED 以匹配。我现在没有使用中断,而是不断地轮询光敏电阻电路的输入。
当机器开启时,LED 的两种可能状态是闪烁和开启。机器通电时,它永远不会只是关闭。
我可以使用中断,但我陷入了如何在轮询时等待一定时间的想法。我正在监控的 LED 大约每秒闪烁两次。所以我需要观察一秒钟,然后如果在那一秒钟内的任何时候引脚变低,则将其记录为“关闭”。(输入引脚上有一个下拉电阻。)
我对C不是很有经验,只用它来编写像这样的小芯片来完成小任务。C 的某些特性或功能对此有用吗?或者在我忽略的逻辑中是否有某种方式?请帮我弄清楚如何检测闪烁的灯与 ON 灯。
到目前为止,这是我的代码:
// PIC12F675 Configuration Bit Settings
// 'C' source line config statements
// CONFIG
#pragma config FOSC = INTRCIO // Oscillator Selection bits (INTOSC oscillator: CLKOUT function on GP4/OSC2/CLKOUT pin, I/O function on GP5/OSC1/CLKIN)
#pragma config WDTE = OFF // Watchdog Timer Enable bit (WDT enabled)
#pragma config PWRTE = ON // Power-Up Timer Enable bit (PWRT disabled)
#pragma config MCLRE = OFF // GP3/MCLR pin function select (GP3/MCLR pin function is MCLR)
#pragma config BOREN = OFF // Brown-out Detect Enable bit (BOD enabled)
#pragma config CP = OFF // Code Protection bit (Program Memory code protection is disabled)
#pragma config CPD = OFF // Data Code Protection bit (Data memory code protection is disabled)
#define _XTAL_FREQ 4000000
#include <xc.h>
#include <stdlib.h>
#include <htc.h>
void init_ports(void) {
ANSEL = 0x00; // Set ports as digital IO not analog input.
ADCON0 = 0x00; // Shut off ADC.
CMCON = 0x07; // Shut off comparator.
VRCON = 0x00; // Shut off the voltage reference.
TRISIO = 0xA; // All GPIO pins output except 1&3.
GPIO = 0x00; // Make all pins LOW
T0IE = 0; // Disable timer interrupt.
GPIE = 0; // GPIO port change interrupt
GIE = 0; // Global interrupt for recognition of interrupts.
}
void main(void) {
init_ports();
/* Wait 1 second for power up. */
__delay_ms(1000);
while(1) {
// Check for input on GPIO 1
if (GPIO & 0b000010) {
// Turn on the LED on GPIO 4
GP4 = 1;
}
else{
// Turn off the LED on GPIO 4
GP4 = 0;
}
}
}
解决方案
您甚至不必使用中断来跟踪时间。您所要做的就是设置一个自由运行的计时器,然后计时器将为您保留时间。您只需在需要时读取计时器,并保存当前时间值。因此,当您检测到输入发生变化时,您会比较您首先读取计时器值和当前计时器值之间的经过时间。请注意,我们在这里使用的“时间”一词不是指小时或分钟。它只是您将为滴答事件定义的时间基准,即 1 毫秒。例如,使用 PIC12F675 的 Timer0 模块,您可以生成这个时基。您只需要添加 Timer0 初始化函数并重建您的主代码。让我告诉你如何通过修改你自己的代码......
// PIC12F675 Configuration Bit Settings
// 'C' source line config statements
// CONFIG
#pragma config FOSC = INTRCIO // Oscillator Selection bits (INTOSC oscillator: CLKOUT function on GP4/OSC2/CLKOUT pin, I/O function on GP5/OSC1/CLKIN)
#pragma config WDTE = OFF // Watchdog Timer Enable bit (WDT enabled)
#pragma config PWRTE = ON // Power-Up Timer Enable bit (PWRT disabled)
#pragma config MCLRE = OFF // GP3/MCLR pin function select (GP3/MCLR pin function is MCLR)
#pragma config BOREN = OFF // Brown-out Detect Enable bit (BOD enabled)
#pragma config CP = OFF // Code Protection bit (Program Memory code protection is disabled)
#pragma config CPD = OFF // Data Code Protection bit (Data memory code protection is disabled)
#define _XTAL_FREQ 4000000
#include <xc.h>
#include <stdlib.h>
#include <htc.h>
void init_ports(void) {
ANSEL = 0x00; // Set ports as digital IO not analog input.
ADCON0 = 0x00; // Shut off ADC.
CMCON = 0x07; // Shut off comparator.
VRCON = 0x00; // Shut off the voltage reference.
TRISIO = 0xA; // All GPIO pins output except 1&3.
GPIO = 0x00; // Make all pins LOW
T0IE = 0; // Disable timer interrupt.
GPIE = 0; // GPIO port change interrupt
GIE = 0; // Global interrupt for recognition of interrupts.
}
/**
* Init timer0 for 1 ms overflow @4MHz by setting:
* prescaler to 1:4
* reload value to 6
* and assign the prescaler to the Timer0
*/
#define XTAL_FREQ_MHz (_XTAL_FREQ / 1000000)
#define T0_PRESCALER 4
#define T0_OVERFLOW_RATE 1000 // in microseconds
#define SECOND (1000000 / T0_OVERFLOW_RATE)
// Now calculate the TMR0 reload value for a 1 ms time base
#define T0_RELOAD_VALUE 256 - ((T0_OVERFLOW_RATE * XTAL_FREQ_MHz ) / (T0_PRESCALER * 4))
unsigned int ticks = 0; // Variable to keep time up to 65 seconds
unsigned int lastOffTime = 0; // Variable to record last OFF time
char lastState = 0, newState = 0; // Variable to hold new and last state of the pin
char offDetected = 0;
void init_timer0(void) {
OPTION_REG = 0xC1;
TMR0 = T0_RELOAD_VALUE; // in this case must be 6
INTCONbits.T0IE = 0; // No timer interrupts
INTCONbits.T0IF = 0; // Clear the flag for polling
}
void main(void) {
init_ports();
/* Wait 1 second for power up. */
__delay_ms(1000);
init_timer0();
while(1) {
// In the main loop first check the 1 ms
while(!INTCONbits.T0IF); // Wait for the 1 ms time to elapse
// 1 ms has elapsed proceed
INTCONbits.T0IF = 0; // First clear the flag for the next use
TMR0 = T0_RELOAD_VALUE; // Reload timer value
ticks++; // Count every 1 ms ticks, don't worry for overflow
// Then check your inputs in each tick for once
// Check for input on GPIO 1
if (GPIO & 0b000010) {
newState = 1;
// Turn on the LED on GPIO 4
GP4 = 1;
}
else{
newState = 0;
}
// Now check out the state changes, here is the OFF-control logic
if(newState != lastState){
if(newState == 0){
// Here you detect when LED is off then record the last off time
// First check if the time elapsed is more than 1 second
lastOffTime = ticks; // Read current ticks
offDetected = 1; // set the flag in order to keep track of time
} else {
offDetected = 0; // clear this flag to prevent checking time elapse
}
lastState = newState; // Save the newState
}
if(offDetected && (ticks - lastOffTime) > SECOND) {
/*
* If the program flow reaches here, it means that the GPIO signal has shut off
* more than 1 second, so do the necesary logic here like turning off
* the indicator LED
*/
GP4 = 0; // Turn off the LED on GPIO 4
offDetected = 0; // Clear the flag so that it does not enter here anymore
}
}
}
希望它对您的目的有所帮助。上面的代码在 MPLAB 仿真中进行了测试,并通过了仿真测试。你在你的真实硬件中测试它,如果你遇到任何问题,请告诉我。祝你好运!
推荐阅读
- c - 如何检查GLUT中是否未按下键?
- java - Java-字符数组接受整个字符串,即使声明的大小较小
- android - 通过 ADB 和端口 5555 控制另一个设备
- python - 在不使用 fstrings 修改精度的情况下从 float 中删除尾随 `.0`
- ruby - 如何检查在另一个方法 rspec 中调用的方法的返回值?
- snowflake-cloud-data-platform - 雪花拉动 MaestroQA 数据
- shell - MobaXtern - 如何在 Moba 自己的 bash 终端中运行 bash shell 脚本?
- sql - Access 或 SQL:需要帮助从在查询中动态选择字段名称的字段返回数据
- api - 无法将 APIMan 中的端点 URL 更改为公共 IP
- flutter - “FirebaseMessaging”类没有默认构造函数 Flutter 2