PIC32MZ tutorial -- Change Notification

  In my last post I implement "Key Debounce" with port polling, port polling is not very efficient. And this time, I will use change notification instead of port polling. It generates interrupt and starts debounce when the level of digital port changes, so it will eliminate the MCU load of port polling.

  On my PIC32MZ EC Starter Kit, every I/O port pin (RAx-RKx) can be used as a change notification pin (CNAx-CNKx). The CN pins are configured as follows:

  1.Disable CPU interrupts.
  2.Set the desired CN I/O pin as an input by setting the corresponding TRISx register bits = 1.
  3.Enable the CN Module by setting the ON bit (CNCONx<15>) = 1.
  4.Enable individual CN input pins, enable optional pull-ups or pull-downs.
  5.Read the corresponding PORTx registers to clear the CN interrupt.
  6.Configure the CN Interrupt Priority bits, CNIP<2:0> (IPC6<20:18>), and Sub-priority bits,CNIS<1:0> (IPC6<17:16>).
  7.Clear the CN Interrupt Flag bit, by setting the CNIF bit (IFS1<0>) = 0.
  8.Configure the CN pin interrupt for a specific edge detect using the EDGEDETECT bit in the CNCONx register, and set up edge control using the CNENx/CNNEx bits.
  9.Enable the CN Interrupt Enable bit, by setting the CNIE bit (IEC1<0>) = 1.
10.Enable CPU interrupts.

  The CNSTATx registers indicate whether a change occurred on the corresponding pin since the last read of the PORTx bit. It is ridiculous that data sheet or reference manual mentions CNSTATx register but but gives no figure or details. After so many times retry. I get to know it has to clear CNSTATx bit corresponding to CN pin in the CN interrupt service routine. Otherwise, the interrupt service routine may not work.

  Anyway, I get this change notification application work, and the following is the implementation.

  TIMER module:

void Timer1_Init(void)
{
    T1CON = 0x8010;
    PR1 = 0x30D3;
    IPC1SET = 0x5;
    TMR1 = 0;
    IEC0SET = 0x10;
    IFS0CLR = 0x10;
}

void Timer1_Write(unsigned int value)
{
    TMR1 = value & 0xFFFF;
}

  KEY module ( enable change notification interrupt, debounce function):

#define DEBOUNCE_Input (PORTB & 0x1000)
#define DEBOUNCE_Open() ANSELB = 0xFFFFEFFF
#define DEBOUNCE_IOCtl() CNPUBSET = 0x1000
#define DEBOUNCE_Output LedState
#define DEBOUNCE_ThreholdLow 0
#define DEBOUNCE_ThreholdHigh 100
//extern volatile unsigned char DEBOUNCE_TimeFlag;
extern volatile unsigned char DEBOUNCE_EventStart;

  volatile unsigned char DEBOUNCE_EventStart;
    //volatile unsigned char DEBOUNCE_TimeFlag;
    unsigned long DEBOUNCE_PreInput;
    unsigned int DEBOUNCE_Integrator;

    void Key_Init(void)
    {
        DEBOUNCE_EventStart = 0;
        DEBOUNCE_Integrator = DEBOUNCE_ThreholdHigh / 2;
        //DEBOUNCE_TimeFlag = 0;

        DEBOUNCE_Open();
        DEBOUNCE_IOCtl();
        DEBOUNCE_PreInput = DEBOUNCE_Input;

        CNENBSET = 0x1000;
        IPC29SET = 0x12000000;
        IFS3CLR = 0x800000;
        IEC3SET = 0x800000;
        CNCONBSET = 0x8000;
    }

    void Key_Debounce(void)
    {
          if (DEBOUNCE_EventStart)
          {
                if (DEBOUNCE_Input == 0)
                {
                    if (DEBOUNCE_Integrator-- == DEBOUNCE_ThreholdLow)
                    {
                        DEBOUNCE_Output = 0;
                        DEBOUNCE_PreInput = DEBOUNCE_Input;
                        DEBOUNCE_EventStart = 0;
                        DEBOUNCE_Integrator = DEBOUNCE_ThreholdHigh / 2;
                    }
                }
                else                   //if (DEBOUNCE_Input == 1)
                {
                    if (DEBOUNCE_Integrator++ == DEBOUNCE_ThreholdHigh)
                    {
                        DEBOUNCE_Output = 1;
                        DEBOUNCE_PreInput = DEBOUNCE_Input;
                        DEBOUNCE_EventStart = 0;
                        DEBOUNCE_Integrator = DEBOUNCE_ThreholdHigh / 2;
                    }
                }
          }
    }

  LED module:

#define LED_IOCTL()       TRISHCLR = (1<<0)
#define LED_SETON()       LATHSET = (1<<0)
#define LED_SETOFF()      LATHCLR = (1<<0)
#define LED_ONOFF()       LATHINV = (1<<0)
#define LED_OPEN()        ANSELH &= 0xFFFFFFFE
typedef enum _LED_STATE_t {
        /* Describe structure member. */
        OFF = 0,

        /* Describe structure member. */
        ON = 1

    } LED_STATE_t;
LED_STATE_t PreLedState, LedState;

void Led_Init(void)
{
    LED_OPEN();
    LED_IOCTL();
    LED_SETON();
    LedState = ON;
    PreLedState = LedState;
}

void Led_Scheduler(void)
{
    if (LedState != PreLedState)
    {
        LED_ONOFF();
        PreLedState = LedState;
    }
}

  MAIN module (main function, timer1 ISR, CNB ISR):

#include <xc.h>
#include "Led.h"
#include "Key.h"
#include "Timer.h"
#include "Interrupt.h"
#include <sys/attribs.h>
#include "ConfigurationBits.h"

void __ISR(_CHANGE_NOTICE_B_VECTOR,ipl4AUTO) CNB_Handler(void)
{
    if ((CNSTATB & 0x1000) == 0x1000)
    {
        DEBOUNCE_EventStart = 1;
        CNSTATBCLR = 0x1000;
        unsigned long tmp = DEBOUNCE_Input;
    }
    IFS3CLR = 0x800000;
}

void __ISR(_TIMER_1_VECTOR,ipl1AUTO) Timer1_Handler(void)
{
    //DEBOUNCE_TimeFlag = 1;
    Key_Debounce();
    Timer1_Write(0);
    IFS0CLR = 0x10; // Clear flag
 }

void main(void)
{
    Led_Init();
    Key_Init();
    Timer1_Init();
    Mvec_Interrupt();

    while (1)
    {
        Led_Scheduler();
    }
}
时间: 2024-11-07 07:45:54

PIC32MZ tutorial -- Change Notification的相关文章

PIC32MZ tutorial -- OC Interrupt

In my previous blog "PIC32MZ tutorial -- Output Compare", I shows how to apply Output Compare without interrupt to generate PWM signal. I also tried the Output Compare interrupt. I selected OC to be PWM mode without fault pin (OCM = "110&qu

深入详解Oracle data change notification

深入详解 Oracle  data change notification 1.什么是 Oracle  data change notification  ? 当有多个应用程序或者进程操作同一个数据库时,其中进程1对Oracle中的某个表Table1进行插入.删除.修改等操作,进程2想在第一个进程操作完成后进行相应的操作.有没有什么方法让进程2获取到进程1的操作? 类似进程.多线程的同步机制,或者消息响应机制.在Oracle中也有类似的实现,该机制名称即为:data change notific

PIC32MZ tutorial -- External Interrupt

In my older blog "PIC32MZ tutorial -- Key Debounce", I shows how to acheive key debounce with port polling. At this moment, I write an application which uses External Interrupt.  Therefore, only generates interrupt and starts debounce when the f

PIC32MZ tutorial -- Input Capture

Today I accomplish a simple application for PIC32MZ EC Starter Kit. This application uses Input Capture feature of PIC32MZ. The Input Capture module captures the 32-bit value of the selected Time Base registers when an event occurs at the ICx pin.  T

PIC32MZ tutorial -- 32-bit Timer

The microcontroller is PIC32MZ2048ECH144 on the PIC32MZ EC Starter Kit. This microcontroller has four 32-bit synchronous timers are available by combining Timer2 with Timer3, Timer4 with Timer5, Timer6 with Timer7, and Timer8 with Timer9. The 32-bit

PIC32MZ tutorial -- Output Compare

Output Compare is a powerful feature of embedded world. The PIC32 Output Compare module compares the values stored in the OCxR and/or the OCxRS registers to the value in the selected timer. When a match occurs, the Output Compare module generates an

PIC32MZ tutorial -- Blinky LED

Today I finish the "Blinky LED" application on PIC32MZ starter kit. This application let LED1 blink with 0.5HZ frequence. The pseudo code is like LOOP: LED ON Delay 1 second LED OFF Delay 1 second It uses Timer1 to control the delay time. So fir

iOS中消息的传递机制(KVO、Notification、delegation、block以及target-action)---转载

注1:本文由破船[博客]译自Communication Patterns. 本文目录如下所示: 可用的机制 做出正确的选择 Framework示例 小结 每个应用程序或多或少,都由一些松耦合的对象构成,这些对象彼此之间要想很好的完成任务,就需要进行消息传递.本文将介绍所有可用的消息传递机制,并通过示例来介绍这些机制在苹果的Framework中如何使用,同时,还介绍了一些最佳实践建议,告诉你什么时机该选择使用什么机制. 虽然这一期的主题是关于Foundation Framework的,不过本文中还

iOS开发——OC篇&amp;消息传递机制(KVO/NOtification/Block/代理/Target-Action)

iOS开发中消息传递机制(KVO/NOtification/Block/代理/Target-Action) 今晚看到了一篇好的文章,所以就搬过来了,方便自己以后学习 虽然这一期的主题是关于Foundation Framework的,不过本文中还介绍了一些超出Foundation Framework(KVO和Notification)范围的一些消息传递机制,另外还介绍了delegation,block和target- action. 大多数情况下,消息传递该使用什么机制,是很明确的了,当然了,在某