Monday, April 27, 2020

ATMega32 digital counter using external interrupt and multiplexed display

In the previous example, we discuss about the external interrupt of ATMega32 and interfacing the digital output to seven segments display.

Now we drive into an simple application of making a digital counter that could drive up to 4 digits with only one port and four control signals.

multiplexed seven segments display of any digits

Multiplexed seven segments display is made of multi digit. Each digit share the same LED segments, but distinct common.

NFD-5641Ax multiplexed seven segment display.
It has four digit common cathode. It has only one segment port,
but different common pin for each digit.

We use multiplexing method to cut down the number of port's pin to drive a multi-digits display.

Multiplexing a display is very simple to explain:

  1. Clear all common pins of all digit
  2. Output LED data to LED segments
  3. Enable a specific digit's common pin (for common cathode display, put that common to Low) 
  4. Wait for about 10 ms
  5. Repeat all step above.    
Practically, we can multiplex up to 8 digits.

In this example, I use three external interrupt pins:
  • INT0 for count down
  • INT1 for reset
  • INT2 for count up
The four-digit counter could count up to 10000 value.
Schematic for simulation
In real world, we have to add power supply pin +5 V and GND.
Four digit multiplexed seven segments display common anode type, commonly 0.56 inches size.

Source code and design file could be download here:

/* 
* interruptCounter.c
*
* Created: 4/27/2020 5:21:19 PM
* Author : aki-technical
*/

#include <avr/io.h>
#include "avr/interrupt.h"

#define F_CPU 16000000UL
#include "util/delay.h"

unsigned int cnt=0;

void ssd(){
/*SEVEN SEGMENT MAP FOR COMMON
CATHODE TYPE SEVEN SEGMENT DISPLAY
*/
unsigned char ssd[16]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,
0x07,0x7F,0x6F,0x77,0x7C,0x39,0x5E,0x79,0x71};
//Digit 1 1000's
PORTD=0b00001100;
PORTC=ssd[cnt/1000];
PORTD=0b00011100;
_delay_ms(10);

//Digit 3 100's
PORTD=0b00001100;
PORTC=ssd[(cnt%1000)/100];
PORTD=0b00101100;
_delay_ms(10);

//Digit 2 10's
PORTD=0b00001100;
PORTC=ssd[(cnt%100)/10];
PORTD=0b01001100;
_delay_ms(10);

//Digit 1 1's
PORTD=0b00001100;
PORTC=ssd[cnt%10];
PORTD=0b10001100;
_delay_ms(10);

}
int main(void)
{
//PORTD IS OUTPUT
DDRC=0xFF;
//PD7.4 ARE OUTPUT CONTROL PIN
DDRD|=(1<<4)|(1<<5)|(1<<6)|(1<<7);
//PB2 USED FOR INT2
PORTB=(1<<2);
//INT0 AND INT1
PORTD=(1<<2)|(1<<3);
//SET EXTERNAL INTERRUPT FOR INT0, INT1 AND INT1
GICR=(1<<7)|(1<<6)|(1<<5);
//SET GLOBLE INTERRUPT
sei();
while (1)
{
ssd();
}
}

/*
Interrupt Service Routine for
Interrupt0
*/
ISR(INT0_vect){
if(cnt>0) cnt--;
}

/*
Interrupt Service Routine for
Interrupt1
*/
ISR(INT1_vect){
cnt=0;
}

/*
Interrupt Service Routine for
Interrupt2
*/
ISR(INT2_vect){
if(cnt<10000) cnt++;
}


Back to main tutorial page ATMega32 tutorials in C with Atmel Studio 7.

No comments:

Post a Comment

Search This Blog

Labels

25AA010A (1) 8051 (7) 93AA46B (1) ADC (30) Analog Comparator (1) Arduino (15) ARM (6) AT89C52 (7) ATMega32 (56) AVR (57) CCS PICC (28) DAC (1) DHT11 (2) Display (105) Distance Sensor (3) DS18B20 (3) dsPIC (2) dsPIC30F1010 (2) EEPROM (5) Environment Sensor (4) esp8266 (1) I2C (29) Input/Output (67) Interrupt (19) Keil (5) Keypad (10) LCD (47) Master/Slave (1) MAX7221 (1) MCP23017 (5) MCP23S17 (4) Meter (3) MikroC (2) Motor (15) MPLABX (71) Nokia 5110 LCD (3) OLED (2) One-Wire (6) Oscillator (8) PCB (6) PCD8544 (3) PCF8574 (5) PIC (107) PIC12F (2) PIC16F628A (2) PIC16F630 (1) PIC16F716 (3) PIC16F818 (10) PIC16F818/819 (2) PIC16F84A (15) PIC16F876A (1) PIC16F877A (9) PIC16F88 (1) PIC16F887 (60) PIC18 (19) PIC18F1220 (4) PIC18F2550 (3) PIC18F4550 (12) PWM (11) RTC (8) Sensor (10) SH1106 (1) Shift Register (11) Shift Registers (3) SPI (24) STM32 (6) STM32 Blue Pill (6) STM32CubeIDE (6) STM32F103C8T6 (6) SysTick (3) temperature sensor (11) Thermometer (21) Timer/Counter (31) TM1637 (2) UART (7) Ultrasonic (4) Voltmeter (7) WDT (1) XC16 (2) XC8 (94)