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 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 = ;
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 = ;
DEBOUNCE_Integrator = DEBOUNCE_ThreholdHigh / ;
//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 == )
{
if (DEBOUNCE_Integrator-- == DEBOUNCE_ThreholdLow)
{
DEBOUNCE_Output = ;
DEBOUNCE_PreInput = DEBOUNCE_Input;
DEBOUNCE_EventStart = ;
DEBOUNCE_Integrator = DEBOUNCE_ThreholdHigh / ;
}
}
else //if (DEBOUNCE_Input == 1)
{
if (DEBOUNCE_Integrator++ == DEBOUNCE_ThreholdHigh)
{
DEBOUNCE_Output = ;
DEBOUNCE_PreInput = DEBOUNCE_Input;
DEBOUNCE_EventStart = ;
DEBOUNCE_Integrator = DEBOUNCE_ThreholdHigh / ;
}
}
}
}

  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 = , /* Describe structure member. */
ON = } 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 = ;
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();
IFS0CLR = 0x10; // Clear flag
} void main(void)
{
Led_Init();
Key_Init();
Timer1_Init();
Mvec_Interrupt(); while ()
{
Led_Scheduler();
}
}

  The application runs well on PIC32MZ EC Starter Kit, SW1(connects to RB12) pressed, LED1(RH0) is off, SW1 released, LED1 is on.

PIC32MZ tutorial -- Change Notification的更多相关文章

  1. PIC32MZ tutorial -- OC Interrupt

    In my previous blog "PIC32MZ tutorial -- Output Compare", I shows how to apply Output Comp ...

  2. PIC32MZ tutorial -- External Interrupt

    In my older blog "PIC32MZ tutorial -- Key Debounce", I shows how to acheive key debounce w ...

  3. PIC32MZ tutorial -- Input Capture

    Today I accomplish a simple application for PIC32MZ EC Starter Kit. This application uses Input Capt ...

  4. PIC32MZ tutorial -- Hello World

    Today I implement "Hello World" on PIC32MZ EC starter kit. The application of "Hello ...

  5. PIC32MZ tutorial -- UART Communication

    At this moment, I accomplish the interface of UART communication for PIC32MZ EC Starter Kit. This in ...

  6. PIC32MZ tutorial -- Watchdog Timer

    Watchdog is a very necessary module for embedded system. Someone said that embedded system operates ...

  7. PIC32MZ tutorial -- Output Compare

    Output Compare is a powerful feature of embedded world. The PIC32 Output Compare module compares the ...

  8. PIC32MZ tutorial -- 32-bit Timer

    The microcontroller is PIC32MZ2048ECH144 on the PIC32MZ EC Starter Kit. This microcontroller has fou ...

  9. PIC32MZ tutorial -- Key Debounce

    Today I accomplish a application on PIC32MZ EC Starter Kit. The feature of application is to light u ...

随机推荐

  1. 安装java后的环境变量配置

    安装java后的环境变量配置- 自定义安装目录可能会带来一些烦恼,配置环境变量可能很难找对目录,所以倒不如干脆就用默认的安装目录,记住它,安装完java之后去到那个路径把路径复制, 然后进行环境变量配 ...

  2. 简单的线性分类——MATLAB,python3实现

    看李政轩老师讲的Kernel,讲的非常好!前面有几道作业题,用MATLAB简单做了下,不知道对不对,错误之处还请指出. 题目是这样的. 一.MATLAB版本: clear; clc % 生成train ...

  3. CentOS上的RabbitMQ安装

    1. erlang安装配置(这里我们在opt目录下进行安装配置) cd /opt 安装依赖文件: yum install gcc glibc-devel make ncurses-devel open ...

  4. JSP 数据库连接类 MySql数据库

    数据库连接类的主要功能是连接数据库并且获得连接对象,以及关闭数据库.通过创建该类的实例,调用其中的方法,以避免重复操作. package chapter13; import java.sql.*; p ...

  5. 诺基亚XL中Intent.ACTION_VIEW无效的问题

    今天测试播放视频的时候,发现在诺基亚XL机型里不能弹出视频应用列表. 我的代码是: Intent intent = new Intent(Intent.ACTION_VIEW); intent.set ...

  6. python数据结构与算法——队列

    队列结构可以使用数组来模拟,只需要设定头和尾的两个标记 参考自<啊哈> # 按书中的代码会出现索引越界的问题(书中申请了超量的空间) # 尝试令tai初始为len(q)-1则不会出错但少了 ...

  7. 给JavaScript初学者的24条最佳实践(share)

    不错的文章,留个备份 原文链接: net.tutsplus   翻译: 伯乐在线- yanhaijing译文链接: http://blog.jobbole.com/53199/ 作为“30 HTML和 ...

  8. GridView中的GridView1_RowCommand事件

    GridView1_RowCommand事件是GridView中生成事件时激发 比如说页面中有一个按钮给他设置CommandName属性 <asp:Button ID="btnCheH ...

  9. http和htpps

    http(超文本传输协议)是一个基于请求与响应模式的.无状态的.应用层的协议.  HTTPS   基于安全套接字层的超文本传输协议 或者是 HTTP over SSL **HTTP 和 HTTPS相同 ...

  10. 面试题一 链表中倒数第k个结点

    void findLastK(LinkedNode head, int k, int n){ if (head == NULL || k == 0) return; LinkedNode t1 = h ...