728x90

Showing posts with label Interrupt. Show all posts
Showing posts with label Interrupt. Show all posts

Tuesday, January 27, 2026

ATMega644P Pin Change Interrupt Example

Overview

In previous post I introduce about external interrupt of the ATMega644P that has only three interrupt source with software select-able. Additionally to the external interrupt the this chip has four more interrupt source that is the Pin Change Interrupt (PCINTXX). It triggers whenever there is any logic change at each pins. 

ATMega644P Pin Change Interrupt Example

The Pin change interrupt PCI3 will trigger if any enabled PCINT31:24 pin toggle, Pin change
interrupt PCI2 will trigger if any enabled PCINT23:16 pin toggles, Pin change interrupt PCI1 if
any enabled PCINT15:8 toggles and Pin change interrupts PCI0 will trigger if any enabled
PCINT7:0 pin toggles. PCMSK3, PCMSK2, PCMSK1 and PCMSK0 Registers control which pins contribute to the pin change interrupts. Pin change interrupts on PCINT31:0 are detected asynchronously. This implies that these interrupts can be used for waking the part also from sleep modes other than Idle mode. 

ATMega644P Input Output Programming Example
ATMega644P 40-Pin DIP Pin Diagram

However any logic change from high to low or even from low to high can generate interrupt. To select any logic level the programmer must mask one logic level.

The Pin Change Interrupt source are distinct from external interrupt so they are grouped in different registers. These are some essential registers relate to PCINTXX:

  1. PCICR – Pin Change Interrupt Control Register 
  2. PCIFR – Pin Change Interrupt Flag Register 
  3. PCMSK3 – Pin Change Mask Register 3 
  4. PCMSK2 – Pin Change Mask Register 2 
  5. PCMSK1 – Pin Change Mask Register 1 
  6. PCMSK0 – Pin Change Mask Register 0 

To use any interrupt source the programmer must enable it, write the ISR and test its interrupt flag. 

ATMega644P Pin Change Interrupt Example
Relevant Registers

 

Pin Change Interrupt Programming in C

Using AVR-LibC in Microchip Studio the programming of this interrupt source could be done from scratch just like we state it above. 

ATMega644P Pin Change Interrupt Example
Schematic

In this example the interrupt source is at PortD (PCINT31:24). That's the Pin Change Interrupt 3. Each time the logic low level is detected the ISR will toggle the LED connects to PortB. PC0 blinks a LED for every 500ms.

  1. /*
  2. * 5-PCINT_2_LED.c
  3. *
  4. * Created: 1/27/2026 10:10:26 AM
  5. * Author : Admin
  6. */

  7. #include <avr/io.h>
  8. #include <avr/interrupt.h>
  9. #include <util/delay.h>
  10. #define F_CPU 16000000UL

  11. volatile uint8_t mask=0;

  12. int main(void)
  13. {
  14. /* Replace with your application code */
  15. DDRB=0xFF;
  16. DDRC=0xFF;
  17. DDRD=0x00;
  18. PIND=0xFF;
  19. PCICR=0x08;
  20. PCMSK3=0xFF;
  21. sei();
  22. while (1)
  23. {
  24. PORTC^=0x01;
  25. _delay_ms(500);
  26. }
  27. }

  28. /*Pin Change Interrupt ISR*/
  29. ISR(PCINT3_vect){
  30. switch(PIND){
  31. case 0xFE: PORTB^=0x01;
  32. break;
  33. case 0xFD: PORTB^=0x02;
  34. break;
  35. case 0xFB: PORTB^=0x04;
  36. break;
  37. case 0xF7: PORTB^=0x08;
  38. break;
  39. case 0xEF: PORTB^=0x10;
  40. break;
  41. case 0xDF: PORTB^=0x20;
  42. break;
  43. case 0xBF: PORTB^=0x40;
  44. break;
  45. case 0x7F: PORTB^=0x80;
  46. break;
  47. }
  48. }


In Proteus VSM this program run correctly. In physical Hardware I has some switches bouncing problems.

ATMega644P Pin Change Interrupt Example
Test Program

I tested this program on my AVR Prototype Board that offered by PCBWay.com

I have been using PCBWay for many years now. PCBWay fabricate PCBs at low cost, fast processing time for only 24 hours, and fast delivery time using any carrier options. This double side 10cmx10cm can be fabricate at only 5USD for 5 to 10pcs by PCBWay. It's a standard PCB with silk screen and solder mask.

A DIY dsPIC30F2010 and dsPIC30F1010 Prototype Board with Programmer
10 PCBs for only 5USD
 

For different size of PCB we can instantly quote on PCBWay website using a zip PCB Gerber file without account.

A DIY dsPIC30F2010 and dsPIC30F1010 Prototype Board with Programmer
PCBWay Instant Quote


I tested this demo example on my AVR Prototype Board.

 

Monday, January 26, 2026

ATMega644P External Interrupt Programming

Overview

An interrupt is a notification for CPU of a micro-controller. It happen very fast commanding the CPU to execute the routine in the Interrupt Service Routine (ISR) handler without waiting for next instruction execution . This mechanism make the program execution more responsive and effective.

ATMega644P External Interrupt Programming

The ATMega644P has many interrupt source each corresponds to their interrupt vector number.

ATMega644P External Interrupt Programming
Interrupt Vectors in ATmega644

An interrupt source could happen whenever the user's program enable it and properly configure it. 

External Interrupt Programming in C

The Atmega644P has three external interrupt sources, INT0( PD2), INT1(PD3) and INT2(PB2). These interrupt sources are use to detect edge(falling or rising) and logic level (Low or High). Their interrupt vector addresses are list in the figure above.

I Microchip Studio that use the AVR-LibC tool-chain the programmer doesn't need to remember the address number of each source. All of them have a readable name specified the compiler.

The programmer must modify these registers to enable the external interrupts.

  1. EICRA – External Interrupt Control Register A ( Modes: edge or logic level)
  2. EIMSK – External Interrupt Mask Register (Enable or Disable)
  3. EIFR – External Interrupt Flag Register (Flag of external interrupt source)

 These feature are common for most of the 40-pin AVR ATMega series.

In this example I use these interrupt sources to toggle each LED at PortB.

  1. /*
  2. * 4-external_interrupt.c
  3. *
  4. * Created: 1/25/2026 7:12:38 PM
  5. * Author : Admin
  6. */

  7. #include <avr/io.h>
  8. #include "avr/interrupt.h"
  9. #include <util/delay.h>
  10. #define F_CPU 16000000UL

  11. int main(void)
  12. {
  13. /* Replace with your application code */
  14. DDRB=0xFF;
  15. DDRB&=~(1<<2);
  16. DDRD=0x01;
  17. PINB=(1<<2);
  18. PIND=(1<<2)|(1<<3);
  19. EIMSK=0x07;
  20. sei();
  21. while (1)
  22. {
  23. PORTD^=1;
  24. _delay_ms(500);
  25. }
  26. }

  27. /*
  28. Interrupt Service Routine (ISR)
  29. for External Interrupt
  30. */
  31. ISR(INT0_vect){
  32. PORTB^=(1<<5);
  33. }

  34. ISR(INT1_vect){
  35. PORTB^=(1<<6);
  36. }

  37. ISR(INT2_vect){
  38. PORTB^=(1<<7);
  39. }

 

Proteus VSM simulate this program correctly. 

ATMega644P External Interrupt Programming
Proteus Schematic and Simulation

However in real hardware the input button bounce. So we need to add a short delay time in the ISR or adding a low pass filter to each input button. 

ATMega644P External Interrupt Programming
Testing in Real Hardware

Multiplexing Display Example

Since the interrupts happens very fast it's suitable to make a counting display that counts the time of switch pressing. The on-board display has up to six digits that able display the number of 999999.

  1. /*
  2. * 4-ext_interrupt_6_digit_16M.c
  3. *
  4. * Created: 1/26/2026 8:53:49 PM
  5. * Author : Admin
  6. */

  7. #include <avr/io.h>
  8. #include <avr/interrupt.h>
  9. #include <util/delay.h>
  10. #define F_CPU 16000000UL

  11. const uint8_t cc_7[16]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,
  12. 0x07,0x7F,0x6F,0x77,0x7C,0x39,0x5E,0x79,0x71};
  13. const uint16_t d_time=5;
  14. volatile long count=0;
  15. int main(void)
  16. {
  17. /* Replace with your application code */
  18. DDRB=0xFF;
  19. DDRC=0xFF;
  20. DDRD=0x00;
  21. PIND=(1<<2)|(1<<3);
  22. EIMSK=0x03;
  23. sei();
  24. while (1)
  25. {
  26. PORTC=0;
  27. PORTB=cc_7[count/100000];
  28. PORTC=0x20;
  29. _delay_ms(d_time);
  30. PORTC=0;
  31. PORTB=cc_7[(count%100000)/10000];
  32. PORTC=0x40;
  33. _delay_ms(d_time);
  34. PORTC=0;
  35. PORTB=cc_7[(count%10000)/1000];
  36. PORTC=0x80;
  37. _delay_ms(d_time);
  38. PORTC=0;
  39. PORTB=cc_7[(count%1000)/100];
  40. PORTC=0x04;
  41. _delay_ms(d_time);
  42. PORTC=0;
  43. PORTB=cc_7[(count%100)/10];
  44. PORTC=0x08;
  45. _delay_ms(d_time);
  46. PORTC=0;
  47. PORTB=cc_7[count%10];
  48. PORTC=0x10;
  49. _delay_ms(d_time);
  50. }
  51. }

  52. /*
  53. Interrupt Service Routine (ISR)
  54. for External Interrupt
  55. */
  56. ISR(INT0_vect){
  57. count++;
  58. if(count>999999) count=0;
  59. }

  60. ISR(INT1_vect){
  61. count--;
  62. if(count<0) count=999999;
  63. }

Whenever each buttons are pressed it will update the value on the display.

ATMega644P External Interrupt Programming
Program Simulation

In Proteus VSM the display run very smooth without flickering.

ATMega644P External Interrupt Programming

However in real hardware the display flickers whenever any button is pressed due to switch bouncing. It does not increase or decrease by one.

I tested this program on my AVR Prototype Board that offered by PCBWay.com

I have been using PCBWay for many years now. PCBWay fabricate PCBs at low cost, fast processing time for only 24 hours, and fast delivery time using any carrier options. This double side 10cmx10cm can be fabricate at only 5USD for 5 to 10pcs by PCBWay. It's a standard PCB with silk screen and solder mask.

A DIY dsPIC30F2010 and dsPIC30F1010 Prototype Board with Programmer
10 PCBs for only 5USD
 

For different size of PCB we can instantly quote on PCBWay website using a zip PCB Gerber file without account.

A DIY dsPIC30F2010 and dsPIC30F1010 Prototype Board with Programmer
PCBWay Instant Quote


I tested this demo example on my AVR Prototype Board.

 
 

 

Tuesday, September 16, 2025

dsPIC30F2010 Prototype Board CCS PICC Examples (Continue)

In previous post I putted some examples of using the dsPIC30F2010 prototype board. However it's too long. So I need to write some remaining posts here.

dsPIC30F2010 Prototype Board CCS PICC Examples (Continue)
PCBWay.com Sponsor PCB Project

 

Creating a PWM Output Using Code Generation Wizard

Generating a PWM output signal could be done from scratch with a few line of code using CCS PICC. We can use its code generation wizard or even manually. 

dsPIC30F2010 Prototype Board CCS PICC Examples (Continue)
PWM Output Pin of OC1
 

After clicking on Create Project it will generate source code. Then pressing F9 to compile this project.

The main.c C source code is just like below.

  1. #include <main.h>


  2. void main()
  3. {

  4. while(TRUE)
  5. {
  6. //TODO: User Code
  7. }

  8. }

 Then double click on the main.h header file we will see its source code.

  1. #include <30F2010.h>
  2. #device ICSP=1
  3. #use delay(crystal=20000000)

  4. #FUSES NOWDT //No Watch Dog Timer
  5. #FUSES CKSFSM //Clock Switching is enabled, fail Safe clock monitor is enabled


  6. #use pwm(OC1,TIMER=2,FREQUENCY=10000,DUTY=0)


It will generate a PWM signal output at pin OC1 (RC13) with a frequency of 10kHz and 0% duty cycle. If we want a 50% duty cycle we need to change the DUTY parameter to 50, and rebuilt it.

PWM Duty Cycle Adjusting with ADC

After using the code generation wizard I got some idea of using PWM in CCS PICC. So I modify and write more codes to adjust PWM signal. I use the on-board ADC input from a potentiometer. Then it will convert to PWM duty cycle ranging from 0% to 100%.

  1. #include "board.h"

  2. #use pwm(OC1,TIMER=2,FREQUENCY=10000,STREAM=_1,DUTY=50)
  3. void main()
  4. {
  5. long adc_value = 0;
  6. float duty_cycle = 0;
  7. setup_adc_ports(sAN4);
  8. setup_adc(ADC_CLOCK_INTERNAL | ADC_TAD_MUL_31);


  9. while(TRUE)
  10. {
  11. //TODO: User Code
  12. set_adc_channel(4);
  13. delay_us(10);
  14. adc_value = read_adc();
  15. duty_cycle = (1000.0*adc_value)/1023;
  16. pwm_set_duty(_1,(int)duty_cycle);
  17. //pwm_set_duty_percent(_1,(int)duty_cycle);
  18. delay_ms(100);
  19. }

  20. }


And its "board.h" file:

  1. #include <30F2010.h>
  2. #device ADC=10
  3. #device ICSP=1
  4. #fuses HS,NODEBUG,NOWDT,PR,CKSFSM
  5. #use delay(crystal=20000000)


  6. #use FIXED_IO( D_outputs=PIN_D1,PIN_D0 )
  7. #use rs232(UART1, baud=9600, stream=UART_PORT1)

  8. #define LED0 PIN_D0
  9. #define LED1 PIN_D1
  10. #define SW0 PIN_C13
  11. #define SW1 PIN_C14

  12. #define DELAY 500


It work fine without wiring additional components. However we can connect the OC1(RC13) PWM pin to a larger LED ( for instance a 5VDC 10mm LED).

 

dsPIC30F2010 Prototype Board CCS PICC Examples (Continue)
Low Duty Cycle

dsPIC30F2010 Prototype Board CCS PICC Examples (Continue)
High Duty Cycle

Click here to download its source file.  

ADC with On-board Tactile Switches and PWM

Fortunately there are two on-board tactile switches that could be used to adjust PWM duty cycle. So I will use ADC channel 4, SW4 (RC13) and SW5(RC14) to adjust PWM duty cycle of OC1 and OC2 respectively.

dsPIC30F2010 Prototype Board CCS PICC Examples (Continue)
PWM Adjustment Using Pot and Tactile Switches

The PWM OC1 is generated by Timer 2 while the PWM OC2 is generated by Timer 3. 

  1. #include "board.h"

  2. #use pwm(OC1,TIMER=2,FREQUENCY=10000,STREAM=_1,DUTY=0)
  3. #use pwm(OC2,TIMER=3,FREQUENCY=10000,STREAM=_2,DUTY=0)

  4. void main()
  5. {
  6. long adc_value = 0;
  7. int oc2_count=0;
  8. float duty_cycle = 0;
  9. set_pullup(TRUE,PIN_C13);
  10. set_pullup(TRUE,PIN_C14);
  11. setup_adc_ports(sAN4);
  12. setup_adc(ADC_CLOCK_INTERNAL | ADC_TAD_MUL_31);

  13. while(TRUE)
  14. {
  15. //TODO: User Code
  16. set_adc_channel(4);
  17. delay_us(10);
  18. adc_value = read_adc();
  19. duty_cycle = (1000.0*adc_value)/1023;
  20. pwm_set_duty(_1,(int)duty_cycle);
  21. if(input(SW0)==0){
  22. if(oc2_count<1000) oc2_count+=100;
  23. pwm_set_duty(_2,oc2_count);
  24. delay_ms(250);
  25. }
  26. if(input(SW1)==0){
  27. if(oc2_count>0) oc2_count-=100;
  28. pwm_set_duty(_2,oc2_count);
  29. delay_ms(250);
  30. }
  31. }

  32. }


Its "board.h" header file:

  1. #include <30F2010.h>
  2. #device ADC=10
  3. #device ICSP=1
  4. #fuses HS,NODEBUG,NOWDT,PR,CKSFSM
  5. #use delay(crystal=20000000)

  6. #use rs232(UART1, baud=9600, stream=UART_PORT1)

  7. #define LED0 PIN_D0
  8. #define LED1 PIN_D1
  9. #define SW0 PIN_C13
  10. #define SW1 PIN_C14

  11. #define DELAY 500

Click here to download its source file.

Timer Tick Example

We can use timer tick for timing delay and scheduling instead of using the delay function. We can call it from scratch using the CCS PICC IDE PIC24 project wizard.

dsPIC30F2010 Prototype Board CCS PICC Examples (Continue)
Timer Tick Example Using Timer 1

 Then we get generated code lists below.

  • main.h
  1. #include <30F2010.h>
  2. #device ICSP=1
  3. #use delay(crystal=20000000)

  4. #FUSES NOWDT //No Watch Dog Timer
  5. #FUSES CKSFSM //Clock Switching is enabled, fail Safe clock monitor is enabled


  6. #use timer(timer=1,tick=100us,bits=32,NOISR)

  7. #define TICK_TYPE unsigned int32

  • main.c

 

  1. #include <main.h>
  2. TICK_TYPE GetTickDifference(TICK_TYPE currTick, TICK_TYPE prevTick)
  3. {
  4. return(currTick-prevTick);
  5. }

  6. void timer_1_tick(void)
  7. {
  8. //TODO: User Code
  9. }


  10. void main()
  11. {

  12. TICK_TYPE CurrentTick,PreviousTick;



  13. //Example program using Tick Timer
  14. CurrentTick = PreviousTick = get_ticks();

  15. while(TRUE)
  16. {
  17. CurrentTick = get_ticks();

  18. if(GetTickDifference(CurrentTick, PreviousTick) >= ((TICK_TYPE)TICKS_PER_SECOND*1)/1000)
  19. {
  20. timer_1_tick();
  21. PreviousTick = CurrentTick;
  22. }

  23. //TODO: User Code
  24. }

  25. }

 Then I need to add some codes to these existing source codes.

  •  main.h

 

  1. #include <30F2010.h>
  2. #device ICSP=1
  3. #use delay(crystal=20000000)

  4. #FUSES NOWDT //No Watch Dog Timer
  5. #FUSES CKSFSM //Clock Switching is enabled, fail Safe clock monitor is enabled


  6. #use FIXED_IO( D_outputs=PIN_D1,PIN_D0 )

  7. #define LED1 PIN_D0
  8. #define LED2 PIN_D1


  9. #use timer(timer=1,tick=100us,bits=32,NOISR)

  10. #define TICK_TYPE unsigned int32


  • main.c
  1. #include <main.h>

  2. unsigned int16 count_1_ms=0, count_100_ms=0;

  3. TICK_TYPE GetTickDifference(TICK_TYPE currTick, TICK_TYPE prevTick)
  4. {
  5. return(currTick-prevTick);
  6. }

  7. void timer_1_tick(void)
  8. {
  9. //TODO: User Code
  10. count_1_ms++;
  11. if(count_1_ms>=100) {
  12. output_toggle(LED2);
  13. count_1_ms=0;
  14. count_100_ms++;
  15. }
  16. if(count_100_ms>=5){
  17. output_toggle(LED1);
  18. count_100_ms=0;
  19. }
  20. }


  21. void main()
  22. {

  23. TICK_TYPE CurrentTick,PreviousTick;



  24. //Example program using Tick Timer
  25. CurrentTick = PreviousTick = get_ticks();

  26. while(TRUE)
  27. {
  28. CurrentTick = get_ticks();

  29. if(GetTickDifference(CurrentTick, PreviousTick) >= ((TICK_TYPE)TICKS_PER_SECOND*1)/1000)
  30. {
  31. timer_1_tick();
  32. PreviousTick = CurrentTick;
  33. }

  34. //TODO: User Code
  35. }

  36. }

 It will blink LEDs connect to RD0 and RD1 at different rates.

 

dsPIC30F2010 Prototype Board CCS PICC Examples (Continue)
RD0 and RD1 at different rates

dsPIC30F2010 Prototype Board CCS PICC Examples (Continue)
RD0 and RD1 at different rates

 Click here to download its source file.

Timer 1 Interrupt Example Using Coder Generation Wizard

Timer1 module operates in many modes up to software configuration, internal, gated and external. We can write its source manually or even using the CCS PICC code generation wizard. 

dsPIC30F2010 Prototype Board CCS PICC Examples (Continue)
Using Code Generation Wizard

Then it will generate a skeleton code below that we have to add more code manually.

  1. #include <main.h>

  2. #INT_TIMER1
  3. void timer1_isr(void)
  4. {

  5. }



  6. void main()
  7. {

  8. setup_timer1(TMR_INTERNAL | TMR_DIV_BY_1, 1000);

  9. enable_interrupts(INT_TIMER1);
  10. enable_interrupts(INTR_GLOBAL);

  11. while(TRUE)
  12. {
  13. //TODO: User Code
  14. }

  15. }

 Then I need to add more codes both in main function and Timer interrupt service routine "#INT_TIMER1".

 

  1. #include <main.h>

  2. unsigned int16 timer_1_counts=0;
  3. #INT_TIMER1
  4. void timer1_isr(void)
  5. {
  6. output_toggle(PIN_D0);
  7. timer_1_counts++;
  8. clear_interrupt(INT_TIMER1);
  9. }



  10. void main()
  11. {

  12. setup_timer1(TMR_INTERNAL | TMR_DIV_BY_256, 1000);

  13. enable_interrupts(INT_TIMER1);
  14. enable_interrupts(INTR_GLOBAL);

  15. while(TRUE)
  16. {
  17. //TODO: User Code
  18. if(timer_1_counts>=100){
  19. output_toggle(pin_d1);
  20. timer_1_counts=0;
  21. }
  22. }

  23. }

This source codes will blink pin RD0 and RD1 at different rates. Click here to download its source file.

Change Notify (CN) Interrupt

Change Notify Interrupt (CNI) allow the program to fast response to external event change. For instance a change from logic high to low or vice versa. There are two tactile switches connect to RC13(CN1) and RC14(CN0) respectively. There are no external pull up or pull down resistors. So you need to add more external components to detect input logic change requirement.

dsPIC30F2010 Prototype Board CCS PICC Examples (Continue)
TABLE 8-2: INPUT CHANGE NOTIFICATION REGISTER MAP (BITS 15-0)

Fortunately the Change Notify Interrupt (CNI) come with internal pull-up enable feature that we can enable or disable it by software setting. The CNENx and CNPUx special register responsible for this task. 

dsPIC30F2010 Prototype Board CCS PICC Examples (Continue) 

The program below demonstrate a simple use of Change Notify (CN) Interrupt of pin CN0(RC14). The LED connects to pin RD0 keeps blinking at the rate of 500ms in main program's loop. Whenever the CN0 input logic changes to logic low the CNI occurs. It will toggle the LED connects to pin RD1.

  • main.c 
  1. #include <main.h>

  2. /*CN Pull Up Enable Register*/
  3. #byte CNPU1=0x0C4;
  4. #bit CN0PU=CNPU1.0;
  5. /*CN Interrupt Enable Register*/
  6. #byte CNIEN1=0x0C0;
  7. #bit CN0EN=CNIEN1.0;

  8. /*Interrupt Service Routine for CN Interrupt*/
  9. #INT_CNI
  10. void cni_isr(void)
  11. {
  12. if(!input(CN0)) output_toggle(LED2);
  13. clear_interrupt(INT_CNI);
  14. }


  15. void main()
  16. {
  17. /*PortC As Inputs*/
  18. set_tris_c(0xFFFF);
  19. /*Turn On CN0 PullUp and CN0 Interrupt*/
  20. CN0PU=1;
  21. CN0EN=1;
  22. /*Enable Interrupt*/
  23. enable_interrupts(INTR_CN_PIN|PIN_C13);
  24. enable_interrupts(INTR_GLOBAL);
  25. clear_interrupt(INT_CNI);
  26. while(TRUE)
  27. {
  28. //TODO: User Code
  29. output_toggle(LED1);
  30. delay_ms(500);
  31. }

  32. }
  •  main.h
  1. #include <30F2010.h>
  2. #device ICSP=1
  3. #use delay(crystal=20000000)

  4. #FUSES NOWDT
  5. //No Watch Dog Timer
  6. #FUSES CKSFSM
  7. //Clock Switching is enabled, fail Safe clock monitor is enabled


  8. #use FIXED_IO( D_outputs=PIN_D1,PIN_D0 )

  9. #define CN1 PIN_C13
  10. #define CN0 PIN_C14
  11. #define LED1 PIN_D0
  12. #define LED2 PIN_D1



 I tested this demo program on my dsPIC30F2010 prototype board. It work fine and very fast. Click here to download this example program.

Now I use all tactile switches connect to RC13 and RC14 to generate Change Notification Interrupt (CNI). Every time the CN interrupts occur it will toggle the LEDs.

  • main.c

 

  1. #include <main.h>

  2. /*CN Pull Up Enable Register*/
  3. #byte CNPU1=0x0C4;
  4. #bit CN0PU=CNPU1.0;
  5. #bit CN1PU=CNPU1.1;
  6. /*CN Interrupt Enable Register*/
  7. #byte CNIEN1=0x0C0;
  8. #bit CN0EN=CNIEN1.0;
  9. #bit CN1EN=CNIEN1.1;

  10. /*Interrupt Service Routine for CN Interrupt*/
  11. #INT_CNI
  12. void cni_isr(void)
  13. {
  14. if(!input(CN0)) output_toggle(LED2);
  15. if(!input(CN1)) output_toggle(LED1);
  16. clear_interrupt(INT_CNI);
  17. }


  18. void main()
  19. {
  20. /*PortC As Inputs*/
  21. set_tris_c(0xFFFF);
  22. /*Turn On CN0 PullUp and CN0 and CN1 Interrupt*/
  23. CN0PU=1;
  24. CN0EN=1;
  25. CN1PU=1;
  26. CN1EN=1;
  27. /*Enable Interrupt*/
  28. //enable_interrupts(INTR_CN_PIN|PIN_C13);
  29. //enable_interrupts(INTR_CN_PIN|PIN_C14);
  30. enable_interrupts(INT_CNI);
  31. enable_interrupts(INTR_GLOBAL);
  32. clear_interrupt(INT_CNI);
  33. while(TRUE)
  34. {
  35. //TODO: User Code
  36. }

  37. }

I take some special registers of CN interrupt to use in this program because using the CCS PICC built-in library is not enough.

  • main.h
  1. #include <30F2010.h>
  2. #device ICSP=1
  3. #use delay(crystal=20000000)

  4. #FUSES NOWDT
  5. //No Watch Dog Timer
  6. #FUSES CKSFSM
  7. //Clock Switching is enabled, fail Safe clock monitor is enabled


  8. #use FIXED_IO( D_outputs=PIN_D1,PIN_D0 )

  9. #define CN1 PIN_C13
  10. #define CN0 PIN_C14
  11. #define LED1 PIN_D0
  12. #define LED2 PIN_D1




There are some bounce while pressing the tactile switches. So it's suitable to add and RC filter circuit to eliminate this noise. Using a software delay in the ISR is a good choice to bypass this noisy bouncing period.

dsPIC30F2010 Prototype Board CCS PICC Examples (Continue)

dsPIC30F2010 Prototype Board CCS PICC Examples (Continue)

dsPIC30F2010 Prototype Board CCS PICC Examples (Continue)

dsPIC30F2010 Prototype Board CCS PICC Examples (Continue)
 

Click here to download this program example.
 

Search This Blog

Labels

23K256 (1) 24C16B (2) 25AA010A (2) 8051 (7) 93AA46B (1) ADC (34) Analog Comparator (1) Arduino (16) ARM (13) AT89C52 (7) ATMega32 (58) ATMega644P (27) AVR (87) Bootloader (1) CCS PICC (31) Change Notify Interrupt (CNI) (2) DAC (2) DHT11 (4) Display (133) Distance Sensor (3) ds1307 (10) DS18B20 (5) ds3231 (1) ds3232 (2) dsPIC (5) dsPIC30F1010 (3) dsPIC30F2010 (5) EEPROM (5) Environment Sensor (5) ESP32 (1) esp8266 (1) Graphical LCD (2) I2C (38) ILI9341 (1) Input/Output (75) Interrupt (22) Keil (5) Keypad (16) KS0108 (2) LCD (75) LM35 (3) Master/Slave (2) MAX7221 (1) MCP23017 (8) MCP23S17 (7) MCP4921 (1) MCP4922 (2) Meter (3) MikroC (2) Motor (15) MPLABX (73) Nokia 5110 LCD (4) OLED (2) One-Wire (7) Oscillator (8) PCB (10) PCD8544 (3) PCF8574 (10) PIC (108) PIC12F (3) PIC16F628A (3) PIC16F630 (2) PIC16F716 (4) PIC16F818 (11) PIC16F818/819 (3) PIC16F84A (16) PIC16F876A (2) PIC16F877A (9) PIC16F88 (2) PIC16F887 (60) PIC18 (19) PIC18F1220 (5) PIC18F2550 (5) PIC18F4550 (12) PICKit2 (1) Pin Change Interrupt (1) PWM (12) RTC (12) SBN0064G (1) Sensor (13) SH1106 (3) Shift Register (13) Shift Registers (10) Software TWI (2) SPI (39) ST7735 (1) STM32 (11) STM32 Black Pill (1) STM32 Blue Pill (12) STM32 HAL (5) STM32CubeIDE (13) STM32F103C8T6 (9) STM32F401CCU6 (1) SysTick (4) temperature sensor (13) TFT (1) TG12864A (1) Thermometer (22) Timer/Counter (32) TM1637 (2) twi (10) UART (8) Ultrasonic (4) Voltmeter (7) WDT (1) XC16 (2) XC8 (96)