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 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的更多相关文章
- PIC32MZ tutorial -- OC Interrupt
In my previous blog "PIC32MZ tutorial -- Output Compare", I shows how to apply Output Comp ...
- PIC32MZ tutorial -- External Interrupt
In my older blog "PIC32MZ tutorial -- Key Debounce", I shows how to acheive key debounce w ...
- PIC32MZ tutorial -- Input Capture
Today I accomplish a simple application for PIC32MZ EC Starter Kit. This application uses Input Capt ...
- PIC32MZ tutorial -- Hello World
Today I implement "Hello World" on PIC32MZ EC starter kit. The application of "Hello ...
- PIC32MZ tutorial -- UART Communication
At this moment, I accomplish the interface of UART communication for PIC32MZ EC Starter Kit. This in ...
- PIC32MZ tutorial -- Watchdog Timer
Watchdog is a very necessary module for embedded system. Someone said that embedded system operates ...
- PIC32MZ tutorial -- Output Compare
Output Compare is a powerful feature of embedded world. The PIC32 Output Compare module compares the ...
- PIC32MZ tutorial -- 32-bit Timer
The microcontroller is PIC32MZ2048ECH144 on the PIC32MZ EC Starter Kit. This microcontroller has fou ...
- PIC32MZ tutorial -- Key Debounce
Today I accomplish a application on PIC32MZ EC Starter Kit. The feature of application is to light u ...
随机推荐
- SPOJ BALNUM
一开始题看错了...dp[pos][sets][viss],其中sets表示出现次数,viss表示出现没有. #include<iostream> #include<cstdio&g ...
- RabbitMQ/JAVA 客户端连接测试
这里是一个简单的helloworld测试. 这里在eclipse平台中实现 细节不再赘述.重点是导入rabbitmq-java-client的jar包 下载地址:http://www.rabbitmq ...
- Unity Sprite转Prefab
新项目使用Unity5.X,遇到了一些问题,其中就有Sprite的管理更新问题,查了一些资料,Mono推荐的是转为Prefab处理. 看了一些国外同行的处理方法,分析了一个编辑器插件脚本.学到了一些技 ...
- 避免每次输入bundler Exec命令
bundle在ruby的世界里是个好东西,它可以用来管理应用程序的依赖库.它能自动的下载和安装指定的gem,也可以随时更新指定的gem. rvm则是一个命令行工具,能帮助你轻松的安装,管理多个ruby ...
- Valgrind的多线程调试工具
Valgrind的多线程调试工具 Helgrind是Valgrind的一个重点功能 本节主要针对与多线程基本安全问题进行检测:[所有的代码环境都是在POSIX_THREAD模式下] 写线程代码时 经 ...
- kallisto:Near-optimal RNA-Seq quantification
Near-optimal RNA-Seq quantification https://pachterlab.github.io/kallisto 文章标题: Pseudoalignment fo ...
- JQUERY知识总结
1, 让页面上某一个已存在的SELECT被选中的JQuery写法 $("#test").find("option[value='3']").prop(&quo ...
- 使用Condition Variables 实现一个线程安全队列
使用Condition Variables实现一个线程安全队列 测试机: i7-4800MQ .7GHz, logical core, physical core, 8G memory, 256GB ...
- LuManager 2.0.97 设置shopex 手机版waptouch,绑定二级目录
1.步骤,先要把主站的 限制目录访问那个勾选,去掉 2.创建新网站,不需要ftp,直接设置网站目录“/home/主站目录/waptouch” 3.保存
- document.write 动态加载 script 脚本时,特殊异常
项目中有个JS,需要动态引入. 写法如下: <script> document.write('<script src="http://www.z4.com/js/xxxx. ...